Merge branch 'master' into bui-text
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
"@mdx-js/loader": "^3.1.0",
|
||||
"@mdx-js/react": "^3.1.0",
|
||||
"@next/mdx": "15.3.4",
|
||||
"@remixicon/react": "^4.6.0",
|
||||
"@storybook/react": "^8.6.8",
|
||||
"@uiw/codemirror-themes": "^4.23.7",
|
||||
"@uiw/react-codemirror": "^4.23.7",
|
||||
@@ -32,7 +33,6 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"react-frame-component": "^5.2.7",
|
||||
"shiki": "^1.26.1",
|
||||
"storybook": "^8.6.8"
|
||||
},
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.pageContainer {
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 64px;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
import styles from './layout.module.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Backstage UI',
|
||||
description: 'UI library for Backstage',
|
||||
};
|
||||
|
||||
export default function DocsLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return <div className={styles.pageContainer}>{children}</div>;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode } from 'react';
|
||||
import { Grid, Flex, Text } from '../../../../../packages/ui';
|
||||
import { screenSizes } from '@/utils/data';
|
||||
import { Frame } from '@/components/Frame';
|
||||
import { usePlayground } from '@/utils/playground-context';
|
||||
import {
|
||||
ButtonSnippet,
|
||||
CheckboxSnippet,
|
||||
HeadingSnippet,
|
||||
TextSnippet,
|
||||
} from '@/snippets/stories-snippets';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
export default function PlaygroundPage() {
|
||||
const { selectedScreenSizes } = usePlayground();
|
||||
|
||||
const filteredScreenSizes = screenSizes.filter(item =>
|
||||
selectedScreenSizes.includes(item.slug),
|
||||
);
|
||||
|
||||
if (filteredScreenSizes.length === 0) {
|
||||
return (
|
||||
<div className={styles.containerEmpty}>
|
||||
<Content />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
{filteredScreenSizes.map(screenSize => (
|
||||
<div
|
||||
className={styles.breakpointContainer}
|
||||
style={{ width: screenSize.width }}
|
||||
key={screenSize.slug}
|
||||
>
|
||||
<Text>
|
||||
{screenSize.title} - {screenSize.width}px
|
||||
</Text>
|
||||
<div className={styles.breakpointContent}>
|
||||
<Frame>
|
||||
<Content />
|
||||
</Frame>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Content = () => {
|
||||
const { selectedComponents } = usePlayground();
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="4">
|
||||
{selectedComponents.find(c => c === 'button') && (
|
||||
<Line content={<ButtonSnippet story="Playground" />} title="Button" />
|
||||
)}
|
||||
{selectedComponents.find(c => c === 'checkbox') && (
|
||||
<Line
|
||||
content={<CheckboxSnippet story="Playground" />}
|
||||
title="Checkbox"
|
||||
/>
|
||||
)}
|
||||
{selectedComponents.find(c => c === 'heading') && (
|
||||
<Line content={<HeadingSnippet story="Playground" />} title="Heading" />
|
||||
)}
|
||||
{selectedComponents.find(c => c === 'text') && (
|
||||
<Line content={<TextSnippet story="Playground" />} title="Text" />
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
const Line = ({ content, title }: { content: ReactNode; title: string }) => {
|
||||
return (
|
||||
<Grid.Root gap={{ xs: '2', md: '4' }}>
|
||||
<Grid.Item colSpan="2">
|
||||
<Text>{title}</Text>
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan="10">{content}</Grid.Item>
|
||||
</Grid.Root>
|
||||
);
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
.container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 24px;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.containerEmpty {
|
||||
padding: 78px 40px;
|
||||
}
|
||||
|
||||
.breakpointContainer {
|
||||
flex-shrink: 0;
|
||||
margin-top: 40px;
|
||||
height: calc(100vh - 86px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.breakpointContent {
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border);
|
||||
background-color: var(--bg);
|
||||
padding: 16px;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
.container {
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
width: calc(100% - 64px);
|
||||
margin-inline: 0 16px;
|
||||
margin-left: 32px;
|
||||
margin-right: 32px;
|
||||
margin-top: 112px;
|
||||
margin-bottom: 48px;
|
||||
padding-inline: 40px;
|
||||
padding-block: 48px;
|
||||
background-color: var(--panel);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
width: calc(100% - 332px - 40px);
|
||||
margin-left: 332px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { Sidebar } from '../components/Sidebar';
|
||||
import { Toolbar } from '@/components/Toolbar';
|
||||
import { Providers } from './providers';
|
||||
import { CustomTheme } from '@/components/CustomTheme';
|
||||
import styles from '../css/page.module.css';
|
||||
import styles from './layout.module.css';
|
||||
|
||||
import '../css/globals.css';
|
||||
import '/public/theme-backstage.css';
|
||||
@@ -15,11 +15,31 @@ export const metadata: Metadata = {
|
||||
metadataBase: new URL('https://ui.backstage.io'),
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
async function getLatestPackageVersion(): Promise<string> {
|
||||
try {
|
||||
const response = await fetch('https://registry.npmjs.org/@backstage/ui', {
|
||||
next: { revalidate: 3600 }, // Cache for 1 hour
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch package info');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data['dist-tags']?.latest;
|
||||
} catch (error) {
|
||||
console.error('Error fetching package version:', error);
|
||||
return '0.0.0';
|
||||
}
|
||||
}
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
const packageVersion = await getLatestPackageVersion();
|
||||
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
@@ -29,14 +49,12 @@ export default function RootLayout({
|
||||
>
|
||||
<body>
|
||||
<Providers>
|
||||
<div className={styles.global}>
|
||||
<Sidebar />
|
||||
<div className={styles.container}>
|
||||
<Toolbar />
|
||||
{children}
|
||||
</div>
|
||||
<CustomTheme />
|
||||
<Sidebar version={packageVersion} />
|
||||
<Toolbar />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>{children}</div>
|
||||
</div>
|
||||
<CustomTheme />
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { changelog } from '@/utils/changelog';
|
||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
||||
import { formattedMDXComponents } from '@/mdx-components';
|
||||
import type { Component } from '@/utils/changelog';
|
||||
|
||||
export const ChangelogComponent = ({ component }: { component: Component }) => {
|
||||
const componentChangelog = changelog.filter(c =>
|
||||
c.components.includes(component),
|
||||
);
|
||||
|
||||
return (
|
||||
<MDXRemote
|
||||
components={formattedMDXComponents}
|
||||
source={`
|
||||
## Changelog
|
||||
|
||||
${componentChangelog
|
||||
?.map(change => {
|
||||
const prs =
|
||||
change.prs.length > 0 &&
|
||||
change.prs
|
||||
.map(
|
||||
pr =>
|
||||
`[#${pr}](https://github.com/backstage/backstage/pull/${pr})`,
|
||||
)
|
||||
.join(', ');
|
||||
return `- \`${change.version}\` - ${change.description} ${prs}`;
|
||||
})
|
||||
.join('\n')}`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,68 +0,0 @@
|
||||
import { Tabs } from '@/components/Tabs';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
import type { ComponentInfosProps } from './types';
|
||||
import styles from '@/css/mdx.module.css';
|
||||
import Link from 'next/link';
|
||||
import { changelog } from '@/utils/changelog';
|
||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
||||
import { formattedMDXComponents } from '@/mdx-components';
|
||||
|
||||
export const ComponentInfos = ({
|
||||
usageCode,
|
||||
component,
|
||||
classNames,
|
||||
}: ComponentInfosProps) => {
|
||||
const componentChangelog = changelog.filter(c =>
|
||||
c.components.includes(component),
|
||||
);
|
||||
|
||||
return (
|
||||
<Tabs.Root>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab>Usage</Tabs.Tab>
|
||||
{classNames && classNames.length > 0 && <Tabs.Tab>Theming</Tabs.Tab>}
|
||||
<Tabs.Tab>Changelog</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Tabs.Panel>
|
||||
<CodeBlock code={usageCode} />
|
||||
</Tabs.Panel>
|
||||
{classNames && classNames.length > 0 && (
|
||||
<Tabs.Panel>
|
||||
<p className={styles.p}>
|
||||
We recommend starting with our{' '}
|
||||
<Link className={styles.a} href="/theme/theming">
|
||||
global tokens
|
||||
</Link>{' '}
|
||||
to customize the library and align it with your brand. For
|
||||
additional flexibility, you can use the provided class names for
|
||||
each element listed below.
|
||||
</p>
|
||||
<MDXRemote
|
||||
components={formattedMDXComponents}
|
||||
source={`${classNames
|
||||
?.map(className => `- \`${className}\``)
|
||||
.join('\n')}`}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
)}
|
||||
<Tabs.Panel>
|
||||
<MDXRemote
|
||||
components={formattedMDXComponents}
|
||||
source={`${componentChangelog
|
||||
?.map(change => {
|
||||
const prs =
|
||||
change.prs.length > 0 &&
|
||||
change.prs
|
||||
.map(
|
||||
pr =>
|
||||
`[#${pr}](https://github.com/backstage/backstage/pull/${pr})`,
|
||||
)
|
||||
.join(', ');
|
||||
return `- \`${change.version}\` - ${change.description} ${prs}`;
|
||||
})
|
||||
.join('\n')}`}
|
||||
/>
|
||||
</Tabs.Panel>
|
||||
</Tabs.Root>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { ComponentInfos } from './ComponentInfos';
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { Component } from '@/utils/changelog';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export interface ComponentInfosProps {
|
||||
usageCode?: string;
|
||||
classNames?: string[];
|
||||
component: Component;
|
||||
children: ReactNode;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
.container {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
width: 240px;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import ReactFrame from 'react-frame-component';
|
||||
|
||||
export const Frame = ({ children }: { children: React.ReactNode }) => {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setShow(true);
|
||||
}, []);
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<ReactFrame
|
||||
loading="lazy"
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
initialContent={`<!DOCTYPE html><html data-theme="light"><head></head><body><div class="frame-root"></div></body></html>`}
|
||||
mountTarget=".frame-root"
|
||||
head={
|
||||
<>
|
||||
<link rel="stylesheet" href="/core.css" />
|
||||
<link rel="stylesheet" href="/components.css" />
|
||||
<link rel="stylesheet" href="/backstage.css" />
|
||||
</>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</ReactFrame>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
.container {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.component {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--secondary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
||||
import { formattedMDXComponents } from '@/mdx-components';
|
||||
import styles from './PageTitle.module.css';
|
||||
|
||||
export const PageTitle = ({
|
||||
title,
|
||||
description,
|
||||
type = 'component',
|
||||
}: {
|
||||
title: string;
|
||||
type?: string;
|
||||
description: string;
|
||||
}) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.component}>{type}</div>
|
||||
<MDXRemote
|
||||
components={formattedMDXComponents}
|
||||
source={`# ${title}\n\n${description}`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -6,99 +6,46 @@
|
||||
.sidebar {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
border-radius: 8px;
|
||||
width: 300px;
|
||||
height: calc(100vh - 32px);
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.025);
|
||||
top: 112px;
|
||||
left: 0;
|
||||
width: 332px;
|
||||
height: calc(100vh - 112px);
|
||||
color: var(--primary);
|
||||
background-color: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--secondary);
|
||||
margin-inline: 32px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.versionLinks {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
a {
|
||||
color: var(--secondary);
|
||||
transition: color 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.viewport {
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.logoContainer {
|
||||
padding-left: 6px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.logo path {
|
||||
fill: var(--primary);
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
padding: 12px 0;
|
||||
color: var(--primary);
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.line {
|
||||
text-decoration: none;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 26px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--surface-1);
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
.line.active {
|
||||
background-color: var(--surface-1);
|
||||
}
|
||||
|
||||
.line.active .lineTitle {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.lineTitle {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
.lineStatus {
|
||||
font-size: 14px;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
.scrollbar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -110,7 +57,6 @@
|
||||
transition: opacity 150ms 300ms;
|
||||
right: -20px;
|
||||
|
||||
&[data-hovering],
|
||||
&[data-scrolling] {
|
||||
opacity: 1;
|
||||
transition-duration: 75ms;
|
||||
@@ -130,3 +76,70 @@
|
||||
border-radius: inherit;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.viewport {
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 20px 64px;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 500;
|
||||
padding: 0 12px 4px;
|
||||
color: var(--secondary);
|
||||
margin-top: 40px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.line {
|
||||
text-decoration: none;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 26px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--action);
|
||||
}
|
||||
}
|
||||
|
||||
.line.active {
|
||||
background-color: var(--action);
|
||||
}
|
||||
|
||||
.line.active .lineTitle {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.lineTitle {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.lineStatus {
|
||||
font-size: 14px;
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { components, overview, layoutComponents, theme } from '@/utils/data';
|
||||
import { motion } from 'motion/react';
|
||||
import styles from './Sidebar.module.css';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
const data = [
|
||||
{
|
||||
title: 'Overview',
|
||||
content: overview,
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
title: 'Theme',
|
||||
content: theme,
|
||||
url: '/theme',
|
||||
},
|
||||
{
|
||||
title: 'Layout Components',
|
||||
content: layoutComponents,
|
||||
url: '/components',
|
||||
},
|
||||
{
|
||||
title: 'Components',
|
||||
content: components,
|
||||
url: '/components',
|
||||
},
|
||||
];
|
||||
|
||||
export const Docs = () => {
|
||||
const pathname = usePathname();
|
||||
const isPlayground = pathname.includes('/playground');
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={styles.section}
|
||||
animate={{
|
||||
x: isPlayground ? -10 : 0,
|
||||
opacity: isPlayground ? 0 : 1,
|
||||
visibility: isPlayground ? 'hidden' : 'visible',
|
||||
}}
|
||||
initial={{
|
||||
x: isPlayground ? -10 : 0,
|
||||
opacity: isPlayground ? 0 : 1,
|
||||
visibility: isPlayground ? 'hidden' : 'visible',
|
||||
}}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
{data.map(section => {
|
||||
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={`${styles.line} ${isActive ? styles.active : ''}`}
|
||||
>
|
||||
<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>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -1,77 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { components } from '@/utils/data';
|
||||
import { Checkbox } from '@backstage/ui';
|
||||
import { motion } from 'motion/react';
|
||||
import styles from './Sidebar.module.css';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { screenSizes } from '@/utils/data';
|
||||
import { usePlayground } from '@/utils/playground-context';
|
||||
|
||||
export const Playground = () => {
|
||||
const pathname = usePathname();
|
||||
const isPlayground = pathname.includes('/playground');
|
||||
const {
|
||||
selectedScreenSizes,
|
||||
setSelectedScreenSizes,
|
||||
selectedComponents,
|
||||
setSelectedComponents,
|
||||
} = usePlayground();
|
||||
|
||||
const handleComponentCheckboxChange = (slug: string) => {
|
||||
if (selectedComponents.find(item => item === slug)) {
|
||||
const res = selectedComponents.filter(item => item !== slug);
|
||||
setSelectedComponents(res);
|
||||
} else {
|
||||
setSelectedComponents([...selectedComponents, slug]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCheckboxChange = (slug: string) => {
|
||||
if (selectedScreenSizes.find(item => item === slug)) {
|
||||
const res = selectedScreenSizes.filter(item => item !== slug);
|
||||
setSelectedScreenSizes(res);
|
||||
} else {
|
||||
setSelectedScreenSizes([...selectedScreenSizes, slug]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={styles.section}
|
||||
animate={{
|
||||
opacity: isPlayground ? 1 : 0,
|
||||
x: isPlayground ? 0 : 20,
|
||||
visibility: isPlayground ? 'visible' : 'hidden',
|
||||
}}
|
||||
initial={{
|
||||
opacity: isPlayground ? 1 : 0,
|
||||
x: isPlayground ? 0 : 20,
|
||||
visibility: isPlayground ? 'visible' : 'hidden',
|
||||
}}
|
||||
transition={{ duration: 0.2 }}
|
||||
style={{ position: 'absolute' }}
|
||||
>
|
||||
<div className={styles.sectionTitle}>Components</div>
|
||||
{components.map(({ slug, title }) => (
|
||||
<div className={styles.line} key={slug}>
|
||||
<div className={styles.lineTitle}>{title}</div>
|
||||
<Checkbox
|
||||
checked={selectedComponents.includes(slug)}
|
||||
onChange={() => handleComponentCheckboxChange(slug)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<div className={styles.sectionTitle}> Screen sizes</div>
|
||||
{screenSizes.map(({ slug, title }) => (
|
||||
<div className={styles.line} key={slug}>
|
||||
<div className={styles.lineTitle}>{title}</div>
|
||||
<Checkbox
|
||||
checked={selectedScreenSizes.includes(slug)}
|
||||
onChange={() => handleCheckboxChange(slug)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
import { MDXRemote } from 'next-mdx-remote-client/rsc';
|
||||
import { formattedMDXComponents } from '@/mdx-components';
|
||||
import { Component } from '@/utils/changelog';
|
||||
import { componentDefinitions } from '../../../../packages/ui/src/utils/componentDefinitions';
|
||||
import type { DataAttributeValues } from '../../../../packages/ui/src/types';
|
||||
|
||||
export function Theming({ component }: { component: Component }) {
|
||||
const componentDefinition = componentDefinitions[component];
|
||||
|
||||
if (!componentDefinition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const classNames = componentDefinition.classNames;
|
||||
const dataAttributes = componentDefinition.dataAttributes;
|
||||
|
||||
// Get the first class name
|
||||
const firstClassName = Object.values(classNames)[0];
|
||||
|
||||
// Create array of selectors combining first class name with data attributes
|
||||
const selectorArray: string[] = [];
|
||||
|
||||
if (dataAttributes) {
|
||||
Object.entries(dataAttributes).forEach(
|
||||
([attributeName, attributeValues]) => {
|
||||
(attributeValues as DataAttributeValues).forEach(value => {
|
||||
selectorArray.push(
|
||||
`${firstClassName}[data-${attributeName}="${value}"]`,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const classNamesArray = [
|
||||
`${firstClassName}`,
|
||||
...selectorArray,
|
||||
...Object.values(classNames).slice(1),
|
||||
];
|
||||
|
||||
return (
|
||||
<MDXRemote
|
||||
components={formattedMDXComponents}
|
||||
source={`## Theming
|
||||
|
||||
Our theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
|
||||
|
||||
${classNamesArray.map(selector => `- \`${selector}\``).join('\n')}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
.toolbar {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
top: 0;
|
||||
left: 32px;
|
||||
right: 32px;
|
||||
height: 112px;
|
||||
z-index: 10;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.toolbar {
|
||||
left: 332px;
|
||||
right: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-top: 3px;
|
||||
font-size: 28px;
|
||||
color: #26c9ad;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
export { Toolbar } from './Toolbar';
|
||||
@@ -1,18 +0,0 @@
|
||||
import { ThemeSelector } from './theme';
|
||||
import { ThemeNameSelector } from './theme-name';
|
||||
import styles from './styles.module.css';
|
||||
import { Nav } from './nav';
|
||||
|
||||
export const Toolbar = () => {
|
||||
return (
|
||||
<div className={styles.toolbar}>
|
||||
<div>
|
||||
<Nav />
|
||||
</div>
|
||||
<div className={styles.actions}>
|
||||
<ThemeNameSelector />
|
||||
<ThemeSelector />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,78 +0,0 @@
|
||||
.tabs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.tabs {
|
||||
display: block;
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabsTheme {
|
||||
width: 142px;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--bg);
|
||||
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.tab {
|
||||
all: unset;
|
||||
height: 60px;
|
||||
color: var(--secondary);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
transition: color 0.2s ease-in-out;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
&[data-selected] {
|
||||
color: var(--primary);
|
||||
|
||||
& p {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0.25rem 0;
|
||||
border-radius: 0.25rem;
|
||||
outline: 2px solid var(--panel);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab p {
|
||||
color: var(--secondary) !important;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
left: 0;
|
||||
bottom: -1px;
|
||||
translate: var(--active-tab-left) -50%;
|
||||
width: var(--active-tab-width);
|
||||
height: 1px;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--primary);
|
||||
transition-property: translate, width;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { Tabs } from '@base-ui-components/react/tabs';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import styles from './nav.module.css';
|
||||
|
||||
export const Nav = () => {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
const onValueChange = (value: string) => {
|
||||
if (value === 'docs') {
|
||||
router.push('/');
|
||||
} else {
|
||||
router.push('/playground');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs.Root
|
||||
className={styles.tabs}
|
||||
value={pathname.includes('playground') ? 'playground' : 'docs'}
|
||||
onValueChange={onValueChange}
|
||||
>
|
||||
<Tabs.List className={styles.list}>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="docs"
|
||||
onClick={() => {
|
||||
router.push('/');
|
||||
}}
|
||||
>
|
||||
Documentation
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="playground"
|
||||
onClick={() => {
|
||||
router.push('/playground');
|
||||
}}
|
||||
>
|
||||
Playground
|
||||
</Tabs.Tab>
|
||||
<Tabs.Indicator className={styles.indicator} />
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
);
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
.toolbar {
|
||||
position: sticky;
|
||||
top: 16px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
border-radius: 0.5rem;
|
||||
z-index: 10;
|
||||
background-color: var(--panel);
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 1.5rem;
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.025);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
@@ -4,20 +4,20 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
height: 2rem;
|
||||
padding-left: 0.875rem;
|
||||
padding-right: 0.75rem;
|
||||
height: 3rem;
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1rem;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
border: 1px solid var(--color-gray-200);
|
||||
border-radius: 0.375rem;
|
||||
border-radius: 3rem;
|
||||
font-family: inherit;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
color: var(--color-gray-900);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background-color: var(--surface-1);
|
||||
background-color: var(--action);
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--color-blue);
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
.tabs {
|
||||
border-radius: 0.375rem;
|
||||
width: 100%;
|
||||
background-color: var(--surface-1);
|
||||
}
|
||||
|
||||
.tabsTheme {
|
||||
width: 100px;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--surface-1);
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
padding-inline: 0.25rem;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
@@ -29,9 +26,10 @@
|
||||
appearance: none;
|
||||
color: var(--secondary);
|
||||
user-select: none;
|
||||
height: 2rem;
|
||||
flex: 1;
|
||||
cursor: pointer;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
|
||||
&[data-selected] {
|
||||
color: var(--primary);
|
||||
@@ -55,7 +53,7 @@
|
||||
position: absolute;
|
||||
inset: 0.25rem 0;
|
||||
border-radius: 0.25rem;
|
||||
outline: 2px solid var(--panel);
|
||||
outline: 2px solid var(--action);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
}
|
||||
@@ -72,9 +70,9 @@
|
||||
top: 50%;
|
||||
translate: var(--active-tab-left) -50%;
|
||||
width: var(--active-tab-width);
|
||||
height: 1.5rem;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--panel);
|
||||
height: 3rem;
|
||||
border-radius: 3rem;
|
||||
background-color: var(--action);
|
||||
transition-property: translate, width;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
|
||||
@@ -8,11 +8,14 @@ import {
|
||||
snippetSizes,
|
||||
snippetFallback,
|
||||
} from './avatar.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Avatar
|
||||
|
||||
An avatar component with a fallback for initials.
|
||||
<PageTitle
|
||||
title="Avatar"
|
||||
description="An avatar component with a fallback for initials."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -21,18 +24,9 @@ An avatar component with a fallback for initials.
|
||||
code={`<Avatar src="https://avatars.githubusercontent.com/u/1540635?v=4" name="Charles de Dreuille" />`}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="avatar"
|
||||
usageCode={snippetUsage}
|
||||
classNames={[
|
||||
'bui-AvatarRoot',
|
||||
'bui-AvatarRoot[data-size="small"]',
|
||||
'bui-AvatarRoot[data-size="medium"]',
|
||||
'bui-AvatarRoot[data-size="large"]',
|
||||
'bui-AvatarImage',
|
||||
'bui-AvatarFallback',
|
||||
]}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={snippetUsage} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -63,3 +57,7 @@ If the image is not available, the avatar will show the initials of the name.
|
||||
preview={<AvatarSnippet story="Fallback" />}
|
||||
code={snippetFallback}
|
||||
/>
|
||||
|
||||
<Theming component="Avatar" />
|
||||
|
||||
<ChangelogComponent component="avatar" />
|
||||
|
||||
@@ -10,11 +10,15 @@ import {
|
||||
boxResponsiveSnippet,
|
||||
} from './box.props';
|
||||
import { spacingPropDefs } from '@/utils/propDefs';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Box
|
||||
|
||||
Box is the lowest-level component in Backstage UI. It provides a consistent API for styling and layout.
|
||||
<PageTitle
|
||||
type="Layout"
|
||||
title="Box"
|
||||
description="Box is the lowest-level component in Backstage UI. It provides a consistent API for styling and layout."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -23,7 +27,9 @@ Box is the lowest-level component in Backstage UI. It provides a consistent API
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<ComponentInfos component="box" usageCode={snippetUsage} />
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={snippetUsage} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -53,3 +59,7 @@ A simple example of how to use the Box component.
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
<CodeBlock code={boxResponsiveSnippet} />
|
||||
|
||||
<Theming component="Box" />
|
||||
|
||||
<ChangelogComponent component="box" />
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
buttonIconResponsiveSnippet,
|
||||
buttonIconAsLinkSnippet,
|
||||
} from './button-icon.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# ButtonIcon
|
||||
|
||||
A button component with a single icon that can be used to trigger actions.
|
||||
<PageTitle
|
||||
title="ButtonIcon"
|
||||
description="A button component with a single icon that can be used to trigger actions."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,11 +28,9 @@ A button component with a single icon that can be used to trigger actions.
|
||||
code={buttonIconDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="button-icon"
|
||||
classNames={['bui-Button', 'bui-ButtonIcon']}
|
||||
usageCode={buttonIconUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={buttonIconUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -78,3 +79,7 @@ Here's a view when buttons are disabled.
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
<CodeBlock code={buttonIconResponsiveSnippet} />
|
||||
|
||||
<Theming component="ButtonIcon" />
|
||||
|
||||
<ChangelogComponent component="button-icon" />
|
||||
|
||||
@@ -11,11 +11,14 @@ import {
|
||||
buttonLinkDisabledSnippet,
|
||||
buttonLinkResponsiveSnippet,
|
||||
} from './button-link.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# ButtonLink
|
||||
|
||||
A button component that can be used as a link.
|
||||
<PageTitle
|
||||
title="ButtonLink"
|
||||
description="A button component that can be used as a link."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -24,11 +27,9 @@ A button component that can be used as a link.
|
||||
code={buttonLinkVariantsSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="button-link"
|
||||
classNames={['bui-Button', 'bui-ButtonLink']}
|
||||
usageCode={buttonLinkSnippetUsage}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={buttonLinkSnippetUsage} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -89,3 +90,7 @@ Here's a view when buttons are disabled.
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
<CodeBlock code={buttonLinkResponsiveSnippet} />
|
||||
|
||||
<Theming component="ButtonLink" />
|
||||
|
||||
<ChangelogComponent component="button-link" />
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
buttonResponsiveSnippet,
|
||||
buttonAsLinkSnippet,
|
||||
} from './button.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
|
||||
# Button
|
||||
|
||||
A button component that can be used to trigger actions.
|
||||
<PageTitle
|
||||
title="Button"
|
||||
description="A button component that can be used to trigger actions."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,11 +28,9 @@ A button component that can be used to trigger actions.
|
||||
code={buttonVariantsSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="button"
|
||||
classNames={['bui-Button']}
|
||||
usageCode={buttonSnippetUsage}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={buttonSnippetUsage} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -102,3 +103,7 @@ If you want to use a button as a link, please use the `ButtonLink` component.
|
||||
preview={<ButtonLinkSnippet story="Variants" />}
|
||||
code={buttonAsLinkSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Button" />
|
||||
|
||||
<ChangelogComponent component="button" />
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
cardLongBodySnippet,
|
||||
cardListRowSnippet,
|
||||
} from './card.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Card
|
||||
|
||||
A card component that can be used to display content in a box.
|
||||
<PageTitle
|
||||
title="Card"
|
||||
description="A card component that can be used to display content in a box."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,11 +28,9 @@ A card component that can be used to display content in a box.
|
||||
code={cardDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="card"
|
||||
classNames={['bui-Card', 'bui-CardHeader', 'bui-CardBody', 'bui-CardFooter']}
|
||||
usageCode={cardUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={cardUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -82,3 +83,7 @@ Here's a view when card has a list.
|
||||
code={cardListRowSnippet}
|
||||
open
|
||||
/>
|
||||
|
||||
<Theming component="Card" />
|
||||
|
||||
<ChangelogComponent component="card" />
|
||||
|
||||
@@ -8,11 +8,14 @@ import {
|
||||
checkboxDefaultSnippet,
|
||||
checkboxVariantsSnippet,
|
||||
} from './checkbox.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Checkbox
|
||||
|
||||
A checkbox component that can be used to trigger actions.
|
||||
<PageTitle
|
||||
title="Checkbox"
|
||||
description="A checkbox component that can be used to trigger actions."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -21,11 +24,9 @@ A checkbox component that can be used to trigger actions.
|
||||
code={checkboxDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="checkbox"
|
||||
classNames={['bui-Checkbox']}
|
||||
usageCode={checkboxUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={checkboxUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -44,3 +45,7 @@ Here's a view when checkboxes have different variants.
|
||||
preview={<CheckboxSnippet story="AllVariants" />}
|
||||
code={checkboxVariantsSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Checkbox" />
|
||||
|
||||
<ChangelogComponent component="checkbox" />
|
||||
|
||||
@@ -11,11 +11,14 @@ import {
|
||||
collapsibleTriggerSnippet,
|
||||
collapsibleOpenSnippet,
|
||||
} from './collapsible.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Collapsible
|
||||
|
||||
An avatar component with a fallback for initials.
|
||||
<PageTitle
|
||||
title="Collapsible"
|
||||
description="A collapsible component that can be used to display content in a box."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,15 +28,9 @@ An avatar component with a fallback for initials.
|
||||
code={collapsibleDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="collapsible"
|
||||
classNames={[
|
||||
'bui-CollapsibleRoot',
|
||||
'bui-CollapsibleTrigger',
|
||||
'bui-CollapsiblePanel',
|
||||
]}
|
||||
usageCode={collapsibleUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={collapsibleUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -69,3 +66,7 @@ Open the panel by default by setting the `defaultOpen` prop to `true`.
|
||||
preview={<CollapsibleSnippet story="Open" />}
|
||||
code={collapsibleOpenSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Collapsible" />
|
||||
|
||||
<ChangelogComponent component="collapsible" />
|
||||
|
||||
@@ -9,12 +9,15 @@ import {
|
||||
containerSimpleSnippet,
|
||||
containerResponsiveSnippet,
|
||||
} from './container.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Container
|
||||
|
||||
The container component let you use our default max-width and center the
|
||||
content on the page.
|
||||
<PageTitle
|
||||
type="Layout"
|
||||
title="Container"
|
||||
description="The container component let you use our default max-width and center the content on the page."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -22,11 +25,9 @@ content on the page.
|
||||
code={containerDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="container"
|
||||
classNames={['bui-Container']}
|
||||
usageCode={containerUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={containerUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -46,3 +47,7 @@ The Container component also supports responsive values, making it easy to
|
||||
create responsive designs.
|
||||
|
||||
<CodeBlock code={containerResponsiveSnippet} />
|
||||
|
||||
<Theming component="Container" />
|
||||
|
||||
<ChangelogComponent component="container" />
|
||||
|
||||
@@ -12,11 +12,15 @@ import {
|
||||
flexAlignSnippet,
|
||||
} from './flex.props';
|
||||
import { spacingPropDefs } from '@/utils/propDefs';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Flex
|
||||
|
||||
A responsive flex container component for vertical stacking with customizable gaps.
|
||||
<PageTitle
|
||||
type="Layout"
|
||||
title="Flex"
|
||||
description="A responsive flex container component for vertical stacking with customizable gaps."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -25,11 +29,9 @@ A responsive flex container component for vertical stacking with customizable ga
|
||||
code={flexDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="flex"
|
||||
classNames={['bui-Flex']}
|
||||
usageCode={flexUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={flexUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -60,3 +62,7 @@ The Flex component also supports responsive alignment, making it easy to
|
||||
create responsive designs.
|
||||
|
||||
<CodeBlock code={flexAlignSnippet} />
|
||||
|
||||
<Theming component="Flex" />
|
||||
|
||||
<ChangelogComponent component="flex" />
|
||||
|
||||
@@ -14,12 +14,15 @@ import {
|
||||
gridResponsiveSnippet,
|
||||
gridStartEndSnippet,
|
||||
} from './grid.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Grid
|
||||
|
||||
A layout component that helps to create simple column-based layouts as well as
|
||||
more complex ones.
|
||||
<PageTitle
|
||||
type="Layout"
|
||||
title="Grid"
|
||||
description="A layout component that helps to create simple column-based layouts as well as more complex ones."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -27,11 +30,9 @@ more complex ones.
|
||||
code={gridDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="grid"
|
||||
classNames={['bui-Grid', 'bui-GridItem']}
|
||||
usageCode={gridUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={gridUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -91,3 +92,7 @@ responsive designs.
|
||||
The start and end props can be used to position the item in the grid.
|
||||
|
||||
<CodeBlock code={gridStartEndSnippet} />
|
||||
|
||||
<Theming component="Grid" />
|
||||
|
||||
<ChangelogComponent component="grid" />
|
||||
|
||||
@@ -7,11 +7,14 @@ import {
|
||||
iconUsageSnippet,
|
||||
iconDefaultSnippet,
|
||||
} from './icon.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Icon
|
||||
|
||||
Icons are used to represent an action or a state.
|
||||
<PageTitle
|
||||
title="Icon"
|
||||
description="Icons are used to represent an action or a state."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -20,12 +23,14 @@ Icons are used to represent an action or a state.
|
||||
code={iconDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="icon"
|
||||
classNames={['bui-Icon']}
|
||||
usageCode={iconUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={iconUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
<PropsTable data={iconPropDefs} />
|
||||
|
||||
<Theming component="Icon" />
|
||||
|
||||
<ChangelogComponent component="icon" />
|
||||
|
||||
@@ -16,11 +16,14 @@ import {
|
||||
linkRouterSnippet,
|
||||
linkTruncateSnippet,
|
||||
} from './link.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Link
|
||||
|
||||
A link component that supports both internal routing and external navigation.
|
||||
<PageTitle
|
||||
title="Link"
|
||||
description="A link component that renders a `<a>` element."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -29,29 +32,9 @@ A link component that supports both internal routing and external navigation.
|
||||
code={linkDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="link"
|
||||
classNames={[
|
||||
'bui-Link',
|
||||
'bui-Text',
|
||||
"bui-Text[data-variant='title-large']",
|
||||
"bui-Text[data-variant='title-medium']",
|
||||
"bui-Text[data-variant='title-small']",
|
||||
"bui-Text[data-variant='title-x-small']",
|
||||
"bui-Text[data-variant='body-large']",
|
||||
"bui-Text[data-variant='body-medium']",
|
||||
"bui-Text[data-variant='body-small']",
|
||||
"bui-Text[data-variant='body-x-small']",
|
||||
"bui-Text[data-weight='regular']",
|
||||
"bui-Text[data-weight='bold']",
|
||||
"bui-Text[data-color='primary']",
|
||||
"bui-Text[data-color='secondary']",
|
||||
"bui-Text[data-color='danger']",
|
||||
"bui-Text[data-color='warning']",
|
||||
"bui-Text[data-color='success']",
|
||||
]}
|
||||
usageCode={linkUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={linkUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -113,3 +96,7 @@ The `Link` component has a `truncate` prop that can be used to truncate the text
|
||||
preview={<LinkSnippet story="Truncate" />}
|
||||
code={linkTruncateSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Link" />
|
||||
|
||||
<ChangelogComponent component="link" />
|
||||
|
||||
@@ -13,11 +13,14 @@ import {
|
||||
menuHoverSnippet,
|
||||
menuSubmenuSnippet,
|
||||
} from './menu.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Menu
|
||||
|
||||
A list of actions in a dropdown, enhanced with keyboard navigation.
|
||||
<PageTitle
|
||||
title="Menu"
|
||||
description="A list of actions in a dropdown, enhanced with keyboard navigation."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -26,27 +29,9 @@ A list of actions in a dropdown, enhanced with keyboard navigation.
|
||||
code={menuDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="menu"
|
||||
classNames={[
|
||||
'bui-MenuTrigger',
|
||||
'bui-MenuBackdrop',
|
||||
'bui-MenuPositioner',
|
||||
'bui-MenuPopup',
|
||||
'bui-MenuArrow',
|
||||
'bui-MenuItem',
|
||||
'bui-MenuGroup',
|
||||
'bui-MenuGroupLabel',
|
||||
'bui-MenuRadioGroup',
|
||||
'bui-MenuRadioItem',
|
||||
'bui-MenuRadioItemIndicator',
|
||||
'bui-MenuCheckboxItem',
|
||||
'bui-MenuCheckboxItemIndicator',
|
||||
'bui-MenuSubmenuTrigger',
|
||||
'bui-MenuSeparator',
|
||||
]}
|
||||
usageCode={menuUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={menuUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -103,3 +88,7 @@ You can nest menus to create a more complex navigation structure.
|
||||
preview={<MenuSnippet story="Submenu" />}
|
||||
code={menuSubmenuSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="Menu" />
|
||||
|
||||
<ChangelogComponent component="menu" />
|
||||
|
||||
@@ -12,11 +12,15 @@ import {
|
||||
radioGroupValidationSnippet,
|
||||
radioGroupReadOnlySnippet,
|
||||
} from './radio-group.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
|
||||
# RadioGroup
|
||||
|
||||
A radio group allows a user to select a single item from a list of mutually exclusive options.
|
||||
<PageTitle
|
||||
title="RadioGroup"
|
||||
description="A radio group allows a user to select a single item from a list of mutually exclusive options."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,11 +29,9 @@ A radio group allows a user to select a single item from a list of mutually excl
|
||||
code={radioGroupDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="radio-group"
|
||||
classNames={['bui-RadioGroup', 'bui-RadioGroupContent']}
|
||||
usageCode={radioGroupUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={radioGroupUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -96,3 +98,7 @@ You can make the radio group read only by adding the `isReadOnly` prop to the `R
|
||||
preview={<RadioGroupSnippet story="ReadOnly" />}
|
||||
code={radioGroupReadOnlySnippet}
|
||||
/>
|
||||
|
||||
<Theming component="RadioGroup" />
|
||||
|
||||
<ChangelogComponent component="radio-group" />
|
||||
|
||||
@@ -8,11 +8,15 @@ import {
|
||||
searchFieldSizesSnippet,
|
||||
searchFieldDescriptionSnippet,
|
||||
} from './search-field.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
|
||||
# SearchField
|
||||
|
||||
A SearchField is a text field designed for searches.
|
||||
<PageTitle
|
||||
title="SearchField"
|
||||
description="A SearchField is a text field designed for searches."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -21,22 +25,9 @@ A SearchField is a text field designed for searches.
|
||||
code={searchFieldDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="searchfield"
|
||||
classNames={[
|
||||
'bui-SearchField',
|
||||
'bui-TextField',
|
||||
'bui-InputWrapper',
|
||||
'bui-Input',
|
||||
'bui-InputIcon',
|
||||
'bui-FieldLabelWrapper',
|
||||
'bui-FieldLabel',
|
||||
'bui-FieldDescription',
|
||||
'bui-FieldSecondaryLabel',
|
||||
'bui-FieldError',
|
||||
]}
|
||||
usageCode={searchFieldUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={searchFieldUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -67,3 +58,7 @@ Here's a simple SearchField with a description.
|
||||
preview={<SearchFieldSnippet story="WithDescription" />}
|
||||
code={searchFieldDescriptionSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="SearchField" />
|
||||
|
||||
<ChangelogComponent component="search-field" />
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
selectResponsiveSnippet,
|
||||
selectIconSnippet,
|
||||
} from './select.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Select
|
||||
|
||||
A common form component for choosing a predefined value in a dropdown menu.
|
||||
<PageTitle
|
||||
title="Select"
|
||||
description="A common form component for choosing a predefined value in a dropdown menu."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -25,20 +28,9 @@ A common form component for choosing a predefined value in a dropdown menu.
|
||||
code={selectDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="select"
|
||||
classNames={[
|
||||
'bui-Select',
|
||||
'bui-SelectTrigger',
|
||||
'bui-SelectValue',
|
||||
'bui-SelectIcon',
|
||||
'bui-SelectList',
|
||||
'bui-SelectItem',
|
||||
'bui-SelectItemIndicator',
|
||||
'bui-SelectItemLabel',
|
||||
]}
|
||||
usageCode={selectUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={selectUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -100,3 +92,7 @@ Here's a view when the select is disabled.
|
||||
Here's a view when the select is responsive.
|
||||
|
||||
<CodeBlock code={selectResponsiveSnippet} />
|
||||
|
||||
<Theming component="Select" />
|
||||
|
||||
<ChangelogComponent component="select" />
|
||||
|
||||
@@ -9,11 +9,14 @@ import {
|
||||
skeletonDemo1Snippet,
|
||||
skeletonDemo2Snippet,
|
||||
} from './skeleton.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Skeleton
|
||||
|
||||
Use to show a placeholder while content is loading.
|
||||
<PageTitle
|
||||
title="Skeleton"
|
||||
description="Use to show a placeholder while content is loading."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -22,11 +25,9 @@ Use to show a placeholder while content is loading.
|
||||
code={skeletonDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="skeleton"
|
||||
classNames={['bui-Skeleton']}
|
||||
usageCode={skeletonUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={skeletonUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -57,3 +58,7 @@ You can use a mix of different sizes to create a more complex skeleton.
|
||||
code={skeletonDemo2Snippet}
|
||||
open
|
||||
/>
|
||||
|
||||
<Theming component="Skeleton" />
|
||||
|
||||
<ChangelogComponent component="skeleton" />
|
||||
|
||||
@@ -3,11 +3,14 @@ import { Snippet } from '@/components/Snippet';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
import { SwitchSnippet } from '@/snippets/stories-snippets';
|
||||
import { switchPropDefs, snippetUsage } from './switch.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Switch
|
||||
|
||||
A control that indicates whether a setting is on or off.
|
||||
<PageTitle
|
||||
title="Switch"
|
||||
description="A control that indicates whether a setting is on or off."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -16,11 +19,9 @@ A control that indicates whether a setting is on or off.
|
||||
code={`<Switch />`}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="switch"
|
||||
usageCode={snippetUsage}
|
||||
classNames={['bui-Switch', 'bui-SwitchIndicator']}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={snippetUsage} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -39,3 +40,7 @@ A switch can be disabled using the `isDisabled` prop.
|
||||
preview={<SwitchSnippet story="Disabled" />}
|
||||
code={`<Switch isDisabled />`}
|
||||
/>
|
||||
|
||||
<Theming component="Switch" />
|
||||
|
||||
<ChangelogComponent component="switch" />
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
# Table (Coming soon)
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
|
||||
<PageTitle
|
||||
title="Table"
|
||||
description="A table component that can be used to display data in a grid. (Coming soon)"
|
||||
/>
|
||||
|
||||
@@ -10,11 +10,14 @@ import {
|
||||
tabsUsageSnippet,
|
||||
tabsDefaultSnippet,
|
||||
} from './tabs.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Tabs
|
||||
|
||||
A component for toggling between related panels on the same page.
|
||||
<PageTitle
|
||||
title="Tabs"
|
||||
description="A component for toggling between related panels on the same page."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -22,17 +25,9 @@ A component for toggling between related panels on the same page.
|
||||
code={tabsDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="tabs"
|
||||
classNames={[
|
||||
'bui-TabsRoot',
|
||||
'bui-TabsList',
|
||||
'bui-TabsTab',
|
||||
'bui-TabsPanel',
|
||||
'bui-TabsIndicator',
|
||||
]}
|
||||
usageCode={tabsUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={tabsUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -59,3 +54,7 @@ An individual interactive tab button that toggles the corresponding panel. Rende
|
||||
A panel displayed when the corresponding tab is active. Renders a `<div>` element.
|
||||
|
||||
<PropsTable data={tabsPanelPropDefs} />
|
||||
|
||||
<Theming component="Tabs" />
|
||||
|
||||
<ChangelogComponent component="tabs" />
|
||||
|
||||
@@ -8,11 +8,15 @@ import {
|
||||
textFieldSizesSnippet,
|
||||
textFieldDescriptionSnippet,
|
||||
} from './text-field.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
import { CodeBlock } from '@/components/CodeBlock';
|
||||
|
||||
# TextField
|
||||
|
||||
A text field component for your forms.
|
||||
<PageTitle
|
||||
title="TextField"
|
||||
description="A text field component for your forms."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
align="center"
|
||||
@@ -21,21 +25,9 @@ A text field component for your forms.
|
||||
code={textFieldDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="textfield"
|
||||
classNames={[
|
||||
'bui-TextField',
|
||||
'bui-InputWrapper',
|
||||
'bui-Input',
|
||||
'bui-InputIcon',
|
||||
'bui-FieldLabelWrapper',
|
||||
'bui-FieldLabel',
|
||||
'bui-FieldDescription',
|
||||
'bui-FieldSecondaryLabel',
|
||||
'bui-FieldError',
|
||||
]}
|
||||
usageCode={textFieldUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={textFieldUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -66,3 +58,7 @@ Here's a simple TextField with a description.
|
||||
preview={<TextFieldSnippet story="WithDescription" />}
|
||||
code={textFieldDescriptionSnippet}
|
||||
/>
|
||||
|
||||
<Theming component="TextField" />
|
||||
|
||||
<ChangelogComponent component="text-field" />
|
||||
|
||||
@@ -12,11 +12,14 @@ import {
|
||||
textResponsiveSnippet,
|
||||
textColorsSnippet,
|
||||
} from './text.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Text
|
||||
|
||||
The `Text` component is used to display content on your page.
|
||||
<PageTitle
|
||||
title="Text"
|
||||
description="The `Text` component is used to display content on your page."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -24,29 +27,9 @@ The `Text` component is used to display content on your page.
|
||||
code={textDefaultSnippet}
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="text"
|
||||
classNames={[
|
||||
'bui-Text',
|
||||
"bui-Text[data-variant='title-large']",
|
||||
"bui-Text[data-variant='title-medium']",
|
||||
"bui-Text[data-variant='title-small']",
|
||||
"bui-Text[data-variant='title-x-small']",
|
||||
"bui-Text[data-variant='body-large']",
|
||||
"bui-Text[data-variant='body-medium']",
|
||||
"bui-Text[data-variant='body-small']",
|
||||
"bui-Text[data-variant='body-x-small']",
|
||||
"bui-Text[data-weight='regular']",
|
||||
"bui-Text[data-weight='bold']",
|
||||
"bui-Text[data-color='primary']",
|
||||
"bui-Text[data-color='secondary']",
|
||||
"bui-Text[data-color='danger']",
|
||||
"bui-Text[data-color='warning']",
|
||||
"bui-Text[data-color='success']",
|
||||
'bui-Text[data-truncate]',
|
||||
]}
|
||||
usageCode={textUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={textUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -103,3 +86,7 @@ You can also use the `variant` prop to change the appearance of the text based
|
||||
on the screen size.
|
||||
|
||||
<CodeBlock code={textResponsiveSnippet} />
|
||||
|
||||
<Theming component="Text" />
|
||||
|
||||
<ChangelogComponent component="text" />
|
||||
|
||||
@@ -8,11 +8,14 @@ import {
|
||||
tooltipTriggerPropDefs,
|
||||
tooltipPropDefs,
|
||||
} from './tooltip.props';
|
||||
import { ComponentInfos } from '@/components/ComponentInfos';
|
||||
import { PageTitle } from '@/components/PageTitle';
|
||||
import { Theming } from '@/components/Theming';
|
||||
import { ChangelogComponent } from '@/components/ChangelogComponent';
|
||||
|
||||
# Tooltip
|
||||
|
||||
A tooltip displays a description of an element on hover or focus.
|
||||
<PageTitle
|
||||
title="Tooltip"
|
||||
description="A tooltip displays a description of an element on hover or focus."
|
||||
/>
|
||||
|
||||
<Snippet
|
||||
py={4}
|
||||
@@ -21,11 +24,9 @@ A tooltip displays a description of an element on hover or focus.
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<ComponentInfos
|
||||
component="tooltip"
|
||||
classNames={['bui-Tooltip', 'bui-ToltipArrow']}
|
||||
usageCode={tooltipUsageSnippet}
|
||||
/>
|
||||
## Usage
|
||||
|
||||
<CodeBlock code={tooltipUsageSnippet} />
|
||||
|
||||
## API reference
|
||||
|
||||
@@ -40,3 +41,7 @@ The trigger will wrap both the trigger and the tooltip.
|
||||
The tooltip will wrap the content of the tooltip.
|
||||
|
||||
<PropsTable data={tooltipPropDefs} />
|
||||
|
||||
<Theming component="Tooltip" />
|
||||
|
||||
<ChangelogComponent component="tooltip" />
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
--bg: #f8f8f8;
|
||||
--panel: #fff;
|
||||
--primary: #000;
|
||||
--secondary: #757575;
|
||||
--secondary: #929292;
|
||||
--action: #fff;
|
||||
--link: #4f5ce0;
|
||||
--font-regular: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
'Helvetica Neue', Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
@@ -17,17 +18,16 @@
|
||||
|
||||
[data-theme='dark'] {
|
||||
--bg: #000;
|
||||
--panel: #1a1a1a;
|
||||
--panel: #181818;
|
||||
--primary: #fff;
|
||||
--secondary: #818181;
|
||||
--action: #202020;
|
||||
--link: #4856e8;
|
||||
--border: #2a2a2a;
|
||||
--surface-1: #282828;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: var(--bg);
|
||||
color: var(--primary);
|
||||
font-family: var(--font-regular);
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
.h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-top: 4rem;
|
||||
margin-bottom: 1.5rem;
|
||||
font-size: 3rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1.25rem;
|
||||
color: var(--primary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.h2 {
|
||||
@@ -10,6 +11,7 @@
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
color: var(--primary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.h3 {
|
||||
@@ -17,6 +19,7 @@
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--primary);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.p {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
.global {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
padding-left: 332px;
|
||||
}
|
||||
}
|
||||
|
||||
.page {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.page p {
|
||||
color: var(--primary);
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 64px 24px 64px;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
|
||||
.header img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.pageContainer {
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 64px;
|
||||
}
|
||||
+10
-12
@@ -907,6 +907,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@remixicon/react@npm:^4.6.0":
|
||||
version: 4.6.0
|
||||
resolution: "@remixicon/react@npm:4.6.0"
|
||||
peerDependencies:
|
||||
react: ">=18.2.0"
|
||||
checksum: 10/d92c8131734062fca8d82d55dd8f3f4e28cb72c5eefda528c8aba5f3298f0c847342eecdbd7787d6da5af21b699d735f6cf27f151f0c982c1c9f06a78b235c94
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rtsao/scc@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@rtsao/scc@npm:1.1.0"
|
||||
@@ -2302,6 +2311,7 @@ __metadata:
|
||||
"@mdx-js/loader": "npm:^3.1.0"
|
||||
"@mdx-js/react": "npm:^3.1.0"
|
||||
"@next/mdx": "npm:15.3.4"
|
||||
"@remixicon/react": "npm:^4.6.0"
|
||||
"@storybook/react": "npm:^8.6.8"
|
||||
"@types/mdx": "npm:^2.0.13"
|
||||
"@types/node": "npm:^20"
|
||||
@@ -2321,7 +2331,6 @@ __metadata:
|
||||
prop-types: "npm:^15.8.1"
|
||||
react: "npm:19.1.0"
|
||||
react-dom: "npm:19.1.0"
|
||||
react-frame-component: "npm:^5.2.7"
|
||||
shiki: "npm:^1.26.1"
|
||||
storybook: "npm:^8.6.8"
|
||||
typescript: "npm:^5"
|
||||
@@ -5587,17 +5596,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-frame-component@npm:^5.2.7":
|
||||
version: 5.2.7
|
||||
resolution: "react-frame-component@npm:5.2.7"
|
||||
peerDependencies:
|
||||
prop-types: ^15.5.9
|
||||
react: ">= 16.3"
|
||||
react-dom: ">= 16.3"
|
||||
checksum: 10/bedee0c25075cbfb6d592991937640a9c8680f9017284e73ced338cc07348b3efc99121052b60ba0923d3d4ec1ed050348ddec452f059e0b947f6bff1d5bfe24
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-is@npm:^16.13.1":
|
||||
version: 16.13.1
|
||||
resolution: "react-is@npm:16.13.1"
|
||||
|
||||
Reference in New Issue
Block a user