Improving our get started page in BUI

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2026-02-11 19:44:11 +00:00
parent 36573c6dd0
commit 13422d70aa
22 changed files with 447 additions and 480 deletions
+5 -169
View File
@@ -1,173 +1,9 @@
import { ComponentCards, ComponentCard } from '@/components/ComponentCards';
import { LayoutComponents } from '@/components/LayoutComponents';
import { CodeBlock } from '@/components/CodeBlock';
import { ComponentGrid } from '@/components/ComponentGrid';
# Components
## Layout Components
Below is the full list of components available in the library. Each component is designed to be flexible, accessible,
and easy to integrate into your plugins. We are actively working on adding more components, so check back regularly
for updates.
We built a couple of layout components to help you build responsive elements
that will be consistent with the rest of your Backstage instance. These
components are opinionated and use TypeScript to ensure that the props you
provide are the ones coming from the theme.
<CodeBlock
title="Layout components"
code={`<Flex direction="column" gap="4">
<Box>Hello World</Box>
<Inline gap="sm">
<Box>Project 1</Box>
<Box>Project 2</Box>
</Inline>
</Flex>
`}
/>
<LayoutComponents />
## Components
### Actions
<ComponentCards>
<ComponentCard
title="Button"
description="A button component to help you trigger actions."
href="/components/button"
/>
<ComponentCard
title="ButtonLink"
description="A button component to help you trigger actions."
href="/components/button-link"
/>
<ComponentCard
title="ButtonIcon"
description="A button for actions with an icon."
href="/components/button-icon"
/>
<ComponentCard
title="Link"
description="A link component to help you navigate to other pages."
href="/components/link"
/>
</ComponentCards>
### Content display
<ComponentCards>
<ComponentCard
title="Card"
description="A component to separate your content on the page."
href="/components/card"
/>
<ComponentCard
title="Collapsible"
description="A collapsible component for expandable content."
href="/components/collapsible"
/>
</ComponentCards>
### Selection and inputs
<ComponentCards>
<ComponentCard
title="Checkbox"
description="A checkbox component to help you select items."
href="/components/checkbox"
/>
<ComponentCard
title="TextField"
description="A text field component to help you input text."
href="/components/text-field"
/>
<ComponentCard
title="SearchField"
description="A search field component to help you search for items."
href="/components/search-field"
/>
<ComponentCard
title="PasswordField"
description="A password field component to help you input passwords."
href="/components/password-field"
/>
<ComponentCard
title="Select"
description="A select component to help you select items."
href="/components/select"
/>
<ComponentCard
title="Switch"
description="A switch component to help you toggle items."
href="/components/switch"
/>
<ComponentCard
title="RadioGroup"
description="A radio group component to help you select items."
href="/components/radio-group"
/>
</ComponentCards>
### Navigation
<ComponentCards>
<ComponentCard
title="Header"
description="A header component to help you display a header."
href="/components/header"
/>
<ComponentCard
title="HeaderPage"
description="A header to complement the Header component."
href="/components/header-page"
/>
<ComponentCard
title="Menu"
description="A menu component to help you display a menu."
href="/components/menu"
/>
<ComponentCard
title="Tabs"
description="A tabs component to help you display a tabs."
href="/components/tabs"
/>
</ComponentCards>
### Images and icons
<ComponentCards>
<ComponentCard
title="Avatar"
description="A avatar component to help you display user avatars."
href="/components/avatar"
/>
<ComponentCard
title="Icon"
description="A icon component to help you display icons."
href="/components/icon"
/>
</ComponentCards>
### Feedback indicators
<ComponentCards>
<ComponentCard
title="Skeleton"
description="A skeleton component to help you display loading states."
href="/components/skeleton"
/>
<ComponentCard
title="Tooltip"
description="A tooltip component to help you display a tooltip."
href="/components/tooltip"
/>
</ComponentCards>
### Typography
<ComponentCards>
<ComponentCard
title="Text"
description="A text component to help you style your text."
href="/components/text"
/>
</ComponentCards>
<ComponentGrid />
@@ -0,0 +1,46 @@
import { CodeBlock } from '@/components/CodeBlock';
import { Banner } from '@/components/Banner';
import { snippet } from './snippets';
# Installation
## Import BUI's global styles
Backstage UI works by importing a global CSS file at the root of your application. This file includes all the default styles for the components.
First, you'll need to install the package using a package manager. For example, if you're using Yarn:
<CodeBlock
lang="shell"
title="Run this command in your `packages/app` directory"
code={`yarn add @backstage/ui`}
/>
<CodeBlock
lang="tsx"
title="Add this line to `packages/app/src/index.tsx`"
code={`import '@backstage/cli/asset-types';
import ReactDOM from 'react-dom/client';
import App from './App';
import '@backstage/ui/css/styles.css'; // [!code ++]
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);`}
/>
<Banner
text="Import these styles only once at your application root. Plugin developers should skip this step to avoid conflicts."
variant="warning"
/>
## Use BUI components
As a plugin maintainer, you can use BUI components in your plugin. As mentioned above, you should not import the styles
again in your plugin as this will be handled at the root of your application. To get started, just add the library to
your plugin and import the components you need.
<CodeBlock
lang="shell"
title="Run this command in your `packages/[your-plugin]` directory"
code={`yarn add @backstage/ui`}
/>
<CodeBlock lang="tsx" title="Let's get started 🚀" code={snippet} />
@@ -0,0 +1,6 @@
export const snippet = `import { Flex, Button, Text } from '@backstage/ui';
<Flex>
<Text>Hello World</Text>
<Button>Click me</Button>
</Flex>;`;
+54 -35
View File
@@ -1,59 +1,78 @@
import { ComponentGrid } from '@/components/ComponentGrid';
import { CodeBlock } from '@/components/CodeBlock';
import { Banner } from '@/components/Banner';
import { snippet } from './snippets';
import { ColorFamily } from '@/components/ColorFamily';
import {
surfacesSnippet,
adaptiveSnippet,
customCardSnippet,
customTokensSnippet,
colorPickerSnippet,
} from './snippets';
# Welcome to Backstage UI
# Get Started with BUI
Backstage UI is a design system created specifically for Backstage, built with React, TypeScript, and vanilla CSS.
This open-source library is hosted in the Backstage monorepo. While it can be used in other projects, Backstage UI
is designed to deliver a consistent, accessible, and extensible experience tailored to Backstage users.
## Import BUI's global styles
Backstage UI is installed by default on every instance of Backstage, so you can start using it right away.
If your setup doesn&apos;t include it yet, follow the [installation guide](/get-started/installation) to get started.
Backstage UI works by importing a global CSS file at the root of your application. This file includes all the default styles for the components.
First, you'll need to install the package using a package manager. For example, if you're using Yarn:
## Layout containers
<CodeBlock
lang="shell"
title="Run this command in your `packages/app` directory"
code={`yarn add @backstage/ui`}
/>
[`Box`](/components/box), [`Flex`](/components/flex), [`Grid`](/components/grid), and [`Card`](/components/card) are the foundation of every layout in Backstage UI.
Each one offers a set of utility props that map directly to our design tokens, so you can build consistent
layouts without writing any CSS. When nested, they also act as surfaces and automatically increment the
background depth so visual hierarchy is handled for you.
<CodeBlock
lang="tsx"
title="Add this line to `packages/app/src/index.tsx`"
code={`import '@backstage/cli/asset-types';
import ReactDOM from 'react-dom/client';
import App from './App';
import '@backstage/ui/css/styles.css'; // [!code ++]
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);`}
title="Nested surfaces with automatic styling"
code={surfacesSnippet}
/>
<Banner
text="Import these styles only once at your application root. Plugin developers should skip this step to avoid conflicts."
variant="warning"
/>
## Adaptive components
## Use BUI components
As a plugin maintainer, you can use BUI components in your plugin. As mentioned above, you should not import the styles
again in your plugin as this will be handled at the root of your application. To get started, just add the library to
your plugin and import the components you need.
Components like [`Card`](/components/card), [`Button`](/components/button), [`Text`](/components/text), and others are **adaptive components**. They
automatically adjust their colors, borders, and backgrounds to match the surface they live on. Drop a
[`Button`](/components/button) inside a [`Card`](/components/card) inside a [`Box`](/components/box) and each component styles itself appropriately
without any extra configuration.
<CodeBlock
lang="shell"
title="Run this command in your `packages/[your-plugin]` directory"
code={`yarn add @backstage/ui`}
lang="tsx"
title="Nested surfaces with automatic styling"
code={adaptiveSnippet}
/>
<CodeBlock lang="tsx" title="Let's get started 🚀" code={snippet} />
## The neutral scale background colors
## Support
<ColorFamily />
Now that you have the basics down, you can start building your plugin using the new design system.
Please familiarise yourself first with our theming principles. This will help you understand the core concepts of the design system.
If you have any questions, please reach out to us on [Discord](https://discord.gg/MUpMjP2).
## Creating custom components
As much as possible we would like you to use components directly without creating custom components. If you need to create a custom component, you should use the components provided by Backstage UI.
<CodeBlock
lang="tsx"
title="Creating a custom card using BUI components"
code={customCardSnippet}
/>
If you need to build custom components outside of BUI, you can use our [design tokens](/tokens) as CSS variables to ensure your styles stay consistent with the rest of the system.
<CodeBlock
lang="tsx"
title="Creating a custom component using BUI tokens"
code={customTokensSnippet}
/>
When building custom interactive components, we strongly recommend using [React Aria](https://react-spectrum.adobe.com/react-aria/) as your foundation. React Aria provides all the necessary accessibility features out of the box — keyboard navigation, focus management, ARIA attributes, and screen reader support — so you can focus on styling and logic without worrying about compliance.
<CodeBlock
lang="tsx"
title="Building a color picker using React Aria and BUI tokens"
code={colorPickerSnippet}
/>
## Philosophy
+37 -4
View File
@@ -1,6 +1,39 @@
export const snippet = `import { Flex, Button, Text } from '@backstage/ui';
export const surfacesSnippet = `<Flex direction="column" gap="4">
<Box bg="neutral-1">
<Button variant="secondary">Hello World</Button>
</Box>
<Box bg="neutral-1">
<Button variant="secondary">Hello World</Button>
</Box>
</Flex>`;
<Flex>
export const adaptiveSnippet = `<Box bg="neutral-1">
<Card> {/* automatically set background to neutral-2 */}
<Button variant="secondary">Button with background set to neutral-3</Button>
</Card>
</Box>`;
export const customCardSnippet = `<Box bg="autoIncrement">
<Text>Hello World</Text>
<Button>Click me</Button>
</Flex>;`;
</Box>`;
export const customTokensSnippet = `<div style={{ backgroundColor: 'var(--bui-bg-solid)' }}>
<div style={{ color: 'var(--bui-fg-solid)' }}>Hello World</div>
</div>`;
export const colorPickerSnippet = `import { ColorPicker, ColorArea, ColorSlider, ColorField } from 'react-aria-components';
function MyColorPicker() {
return (
<ColorPicker defaultValue="#184">
<ColorArea
colorSpace="hsb"
xChannel="saturation"
yChannel="brightness"
style={{ width: 192, height: 192, borderRadius: 'var(--bui-radius-md)' }}
/>
<ColorSlider colorSpace="hsb" channel="hue" />
<ColorField label="Hex" />
</ColorPicker>
);
}`;
@@ -0,0 +1,94 @@
.wrapper {
display: flex;
flex-direction: column;
gap: 2rem;
margin-top: 1rem;
margin-bottom: 2rem;
}
@media (min-width: 768px) {
.wrapper {
flex-direction: row;
align-items: flex-start;
}
}
.visual {
flex: 1;
min-width: 0;
}
.text {
flex: 1;
min-width: 0;
}
.base {
border-radius: 12px;
padding: 16px;
}
.baseLabel {
display: block;
font-size: 13px;
color: var(--bui-fg-primary);
margin-bottom: 12px;
}
.level {
border-radius: 10px;
padding: 12px;
}
.levelHeader {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.level > .level > .levelHeader:last-child,
.level:not(:has(> .level)) > .levelHeader {
margin-bottom: 0;
}
.levelLabel {
font-size: 13px;
color: var(--bui-fg-primary);
white-space: nowrap;
}
.chips {
display: flex;
gap: 6px;
}
.chip {
padding: 6px 10px;
border-radius: 6px;
font-size: 11px;
font-weight: 500;
color: var(--bui-fg-primary);
white-space: nowrap;
}
.description {
color: var(--primary);
margin-top: 0;
margin-bottom: 1rem;
font-size: 1rem;
line-height: 1.5;
}
.description:last-child {
margin-bottom: 0;
}
.link {
color: var(--link);
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
@@ -0,0 +1,95 @@
'use client';
import styles from './ColorFamily.module.css';
const levels = [1, 2, 3, 4] as const;
const StateChip = ({
level,
state,
label,
}: {
level: number;
state: string;
label: string;
}) => (
<div
className={styles.chip}
style={{
backgroundColor: `var(--bui-bg-neutral-${level}${state})`,
}}
>
{label}
</div>
);
const NeutralLevel = ({
level,
children,
height,
}: {
level: number;
children?: React.ReactNode;
height?: number;
}) => (
<div
className={styles.level}
style={{
backgroundColor: `var(--bui-bg-neutral-${level})`,
...(height ? { minHeight: height } : {}),
}}
>
<div className={styles.levelHeader}>
<span className={styles.levelLabel}>Neutral {level}</span>
<div className={styles.chips}>
<StateChip level={level} state="-hover" label="Hover" />
<StateChip level={level} state="-pressed" label="Pressed" />
<StateChip level={level} state="-disabled" label="Disabled" />
</div>
</div>
{children}
</div>
);
export const ColorFamily = () => {
return (
<div className={styles.wrapper}>
<div className={styles.visual}>
<div
className={styles.base}
style={{ backgroundColor: 'var(--bui-bg-neutral-0)' }}
>
<span className={styles.baseLabel}>Neutral 0</span>
<NeutralLevel level={1}>
<NeutralLevel level={2}>
<NeutralLevel level={3}>
<NeutralLevel level={4} height={120} />
</NeutralLevel>
</NeutralLevel>
</NeutralLevel>
</div>
</div>
<div className={styles.text}>
<p className={styles.description}>
BUI uses a layered neutral scale from 0 to 4. Each level nests inside
the previous one, automatically incrementing the background depth.
This creates clear visual hierarchy without manually picking colors.
</p>
<p className={styles.description}>
Each level can be <strong>interactive</strong> or{' '}
<strong>non-interactive</strong>. A Card, for example, can be flat
(just a surface) or fully clickable with hover and pressed states. The
three interaction states (hover, pressed, disabled) are built into
every neutral level.
</p>
<p className={styles.description}>
Explore the full list of color tokens on the{' '}
<a href="/tokens" className={styles.link}>
tokens page
</a>
.
</p>
</div>
</div>
);
};
@@ -0,0 +1 @@
export { ColorFamily } from './ColorFamily';
@@ -1,54 +0,0 @@
.grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 1rem;
margin-top: 1rem;
margin-bottom: 3rem;
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1280px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
.card {
display: flex;
flex-direction: column;
justify-content: flex-end;
background-color: var(--bg);
border-radius: 8px;
border: 1px solid var(--border);
padding: 16px;
gap: 4px;
min-height: 120px;
&:hover {
background-color: var(--bg-hover);
}
}
.title {
margin: 0;
font-size: 16px;
font-weight: 600;
color: var(--primary);
}
.description {
margin: 0;
font-size: 14px;
color: var(--secondary);
}
@@ -1,23 +0,0 @@
import Link from 'next/link';
import styles from './ComponentCards.module.css';
export const ComponentCards = ({ children }: { children: React.ReactNode }) => {
return <div className={styles.grid}>{children}</div>;
};
export const ComponentCard = ({
title,
description,
href,
}: {
title: string;
description: string;
href: string;
}) => {
return (
<Link href={href} className={styles.card}>
<h3 className={styles.title}>{title}</h3>
<p className={styles.description}>{description}</p>
</Link>
);
};
@@ -1 +0,0 @@
export * from './ComponentCards';
@@ -0,0 +1,37 @@
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
margin-top: 1rem;
margin-bottom: 2rem;
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
.item {
display: flex;
align-items: center;
gap: 6px;
padding: 10px 0;
font-size: 14px;
font-weight: 400;
color: var(--primary);
text-decoration: none;
&:hover {
color: var(--link);
text-decoration: underline;
text-underline-offset: 2px;
}
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--link);
flex-shrink: 0;
}
@@ -0,0 +1,22 @@
'use client';
import Link from 'next/link';
import { components } from '@/utils/data';
import styles from './ComponentGrid.module.css';
export const ComponentGrid = () => {
return (
<div className={styles.grid}>
{components.map(item => (
<Link
key={item.slug}
href={`/components/${item.slug}`}
className={styles.item}
>
{item.title}
{item.status === 'new' && <span className={styles.dot} />}
</Link>
))}
</div>
);
};
@@ -0,0 +1 @@
export * from './ComponentGrid';
@@ -1,48 +0,0 @@
.layoutComponents {
display: flex;
justify-content: flex-start;
gap: 1rem;
flex-wrap: wrap;
margin-top: 2rem;
& svg rect {
transition: fill 0.2s ease-in-out;
}
& .box {
display: flex;
flex-direction: column;
width: calc(50% - 0.5rem);
margin-bottom: 1rem;
align-items: flex-start;
}
& .content {
flex: none;
background-color: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
width: 100%;
height: 180px;
transition: all 0.2s ease-in-out;
margin-bottom: 0.75rem;
display: flex;
align-items: center;
justify-content: center;
&:hover {
transform: translateY(-4px);
}
}
& .title {
font-size: 16px;
transition: color 0.2s ease-in-out;
margin-bottom: 0.25rem;
}
& .description {
font-size: 16px;
color: var(--secondary);
}
}
@@ -1,49 +0,0 @@
import { BoxSvg } from './svgs/box';
import { FlexSvg } from './svgs/flex';
import { GridSvg } from './svgs/grid';
import { ContainerSvg } from './svgs/container';
import styles from './LayoutComponents.module.css';
import Link from 'next/link';
export const LayoutComponents = () => {
return (
<div className={styles.layoutComponents}>
<div className={styles.box}>
<Link className={styles.content} href="/components/box">
<BoxSvg />
</Link>
<div className={styles.title}>Box</div>
<div className={styles.description}>
The most basic layout component
</div>
</div>
<div className={styles.box}>
<Link className={styles.content} href="/components/flex">
<FlexSvg />
</Link>
<div className={styles.title}>Flex</div>
<div className={styles.description}>
Arrange your components vertically
</div>
</div>
<div className={styles.box}>
<Link className={styles.content} href="/components/grid">
<GridSvg />
</Link>
<div className={styles.title}>Grid</div>
<div className={styles.description}>
Arrange your components in a grid
</div>
</div>
<div className={styles.box}>
<Link className={styles.content} href="/components/container">
<ContainerSvg />
</Link>
<div className={styles.title}>Container</div>
<div className={styles.description}>
A container for your components
</div>
</div>
</div>
);
};
@@ -1 +0,0 @@
export { LayoutComponents } from './LayoutComponents';
@@ -49,16 +49,13 @@
}
.sectionTitle {
font-size: 0.6875rem;
font-weight: 500;
padding: 0 12px 4px;
color: var(--secondary);
display: flex;
align-items: center;
gap: 8px;
color: var(--primary);
margin-top: 40px;
text-transform: uppercase;
&:first-child {
margin-top: 12px;
}
padding: 8px 12px;
margin-bottom: 8px;
}
.line {
@@ -2,7 +2,6 @@
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Fragment } from 'react';
import clsx from 'clsx';
import {
RiCollageLine,
@@ -12,26 +11,13 @@ import {
RiServiceLine,
RiStackLine,
} from '@remixicon/react';
import { components, layoutComponents } from '@/utils/data';
import { components } from '@/utils/data';
import styles from './Navigation.module.css';
interface NavigationProps {
onLinkClick?: () => void;
}
const data = [
{
title: 'Layout Components',
content: layoutComponents,
url: '/components',
},
{
title: 'Components',
content: components,
url: '/components',
},
];
export const Navigation = ({ onLinkClick }: NavigationProps) => {
const pathname = usePathname();
@@ -55,16 +41,6 @@ export const Navigation = ({ onLinkClick }: NavigationProps) => {
Tokens
</Link>
</li>
<li>
<Link
href="/components"
data-active={pathname.startsWith('/components')}
onClick={onLinkClick}
>
<RiCollageLine size={20} />
Components
</Link>
</li>
<li>
<div data-disabled={true}>
<RiStackLine size={20} />
@@ -89,35 +65,31 @@ export const Navigation = ({ onLinkClick }: NavigationProps) => {
</li>
</ul>
</nav>
{data.map(section => {
<div className={styles.sectionTitle}>
<RiCollageLine size={20} />
<span>Components</span>
</div>
{components.map(item => {
const isActive = pathname === `/components/${item.slug}`;
return (
<Fragment key={section.title}>
<div className={styles.sectionTitle}>{section.title}</div>
{section.content.map(item => {
const isActive = pathname === `${section.url}/${item.slug}`;
return (
<Link
href={`${section.url}/${item.slug}`}
key={item.slug}
className={clsx(styles.line, {
[styles.active]: isActive,
})}
onClick={onLinkClick}
>
<div className={styles.lineTitle}>{item.title}</div>
<div className={styles.lineStatus}>
{item.status === 'alpha' && 'Alpha'}
{item.status === 'beta' && 'Beta'}
{item.status === 'inProgress' && 'In Progress'}
{item.status === 'stable' && 'Stable'}
{item.status === 'deprecated' && 'Deprecated'}
</div>
</Link>
);
<Link
href={`/components/${item.slug}`}
key={item.slug}
className={clsx(styles.line, {
[styles.active]: isActive,
})}
</Fragment>
onClick={onLinkClick}
>
<div className={styles.lineTitle}>{item.title}</div>
<div className={styles.lineStatus}>
{item.status === 'alpha' && 'Alpha'}
{item.status === 'beta' && 'Beta'}
{item.status === 'inProgress' && 'In Progress'}
{item.status === 'stable' && 'Stable'}
{item.status === 'deprecated' && 'Deprecated'}
</div>
</Link>
);
})}
</>
+2 -7
View File
@@ -21,7 +21,7 @@ import styles from './Toolbar.module.css';
import { usePlayground } from '@/utils/playground-context';
import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { components, layoutComponents } from '@/utils/data';
import { components } from '@/utils/data';
import { Logo } from '@/components/Sidebar/Logo';
interface ToolbarProps {
@@ -46,12 +46,7 @@ export const Toolbar = ({ version }: ToolbarProps) => {
// Determine breadcrumb content based on current path
const getBreadcrumb = () => {
const allComponents = [...components, ...layoutComponents];
// Root page
if (pathname === '/') {
return { section: null, title: 'Getting Started' };
}
const allComponents = components;
// Components index page
if (pathname === '/components') {
+16 -20
View File
@@ -4,25 +4,6 @@ interface Page {
status?: 'alpha' | 'beta' | 'stable' | 'deprecated' | 'inProgress' | 'new';
}
export const layoutComponents: Page[] = [
{
title: 'Box',
slug: 'box',
},
{
title: 'Container',
slug: 'container',
},
{
title: 'Grid',
slug: 'grid',
},
{
title: 'Flex',
slug: 'flex',
},
];
export const components: Page[] = [
{
title: 'Accordion',
@@ -36,6 +17,10 @@ export const components: Page[] = [
title: 'Avatar',
slug: 'avatar',
},
{
title: 'Box',
slug: 'box',
},
{
title: 'Button',
slug: 'button',
@@ -56,10 +41,22 @@ export const components: Page[] = [
title: 'Checkbox',
slug: 'checkbox',
},
{
title: 'Container',
slug: 'container',
},
{
title: 'Dialog',
slug: 'dialog',
},
{
title: 'Flex',
slug: 'flex',
},
{
title: 'Grid',
slug: 'grid',
},
{
title: 'Header',
slug: 'header',
@@ -83,7 +80,6 @@ export const components: Page[] = [
{
title: 'Popover',
slug: 'popover',
status: 'new',
},
{
title: 'RadioGroup',
+1 -8
View File
@@ -1,17 +1,10 @@
import { components, layoutComponents } from './data';
import { components } from './data';
export function getPageName(slug: string): string | null {
// Search in components array
const component = components.find(c => c.slug === slug);
if (component) {
return component.title;
}
// Search in layoutComponents array
const layoutComponent = layoutComponents.find(c => c.slug === slug);
if (layoutComponent) {
return layoutComponent.title;
}
return null;
}