Improve code preview
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
import { ButtonProps, Text } from '@backstage/canon';
|
||||
import { Stack, Inline, Button } from '@backstage/canon';
|
||||
|
||||
const variants: {
|
||||
variant: ButtonProps['variant'];
|
||||
size: ButtonProps['size'];
|
||||
}[] = [
|
||||
{ variant: 'primary', size: 'small' },
|
||||
{ variant: 'primary', size: 'medium' },
|
||||
{ variant: 'secondary', size: 'small' },
|
||||
{ variant: 'secondary', size: 'medium' },
|
||||
{ variant: 'tertiary', size: 'small' },
|
||||
{ variant: 'tertiary', size: 'medium' },
|
||||
];
|
||||
|
||||
const capitalizeFirstLetter = (string: string): string => {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
};
|
||||
|
||||
export const ButtonPlayground = () => {
|
||||
return (
|
||||
<Stack>
|
||||
{variants.map(({ variant, size }) => (
|
||||
<Stack key={`${variant}-${size}`}>
|
||||
<Text>
|
||||
{capitalizeFirstLetter(variant as string)} -{' '}
|
||||
{capitalizeFirstLetter(size as string)}
|
||||
</Text>
|
||||
<Inline alignY="center">
|
||||
<Button iconStart="cloud" variant={variant} size={size}>
|
||||
Button
|
||||
</Button>
|
||||
<Button iconEnd="chevronRight" variant={variant} size={size}>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconStart="cloud"
|
||||
iconEnd="chevronRight"
|
||||
style={{ width: '200px' }}
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
</Inline>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -1,16 +1,19 @@
|
||||
'use client';
|
||||
|
||||
import { Inline, Stack, Text } from '@backstage/canon';
|
||||
import { ReactNode } from 'react';
|
||||
import { Grid, Stack, Text } from '@backstage/canon';
|
||||
import { screenSizes } from '@/utils/data';
|
||||
import { Frame } from '@/components/Frame';
|
||||
import { usePlayground } from '@/utils/playground-context';
|
||||
import { ButtonPlayground } from './button';
|
||||
import { CheckboxPlayground } from './checkbox';
|
||||
import { ButtonPlayground } from '@/snippets/button';
|
||||
import { CheckboxPlayground } from '@/snippets/checkbox';
|
||||
import { HeadingPlayground } from '@/snippets/heading';
|
||||
import { TextPlayground } from '@/snippets/text';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export default function PlaygroundPage() {
|
||||
const { selectedScreenSizes, selectedComponents } = usePlayground();
|
||||
const { selectedScreenSizes } = usePlayground();
|
||||
|
||||
const filteredScreenSizes = screenSizes.filter(item =>
|
||||
selectedScreenSizes.includes(item.slug),
|
||||
@@ -57,17 +60,23 @@ const Content = () => {
|
||||
{selectedComponents.find(c => c === 'checkbox') && (
|
||||
<Line content={<CheckboxPlayground />} title="Checkbox" />
|
||||
)}
|
||||
{selectedComponents.find(c => c === 'heading') && (
|
||||
<Line content={<HeadingPlayground />} title="Heading" />
|
||||
)}
|
||||
{selectedComponents.find(c => c === 'text') && (
|
||||
<Line content={<TextPlayground />} title="Text" />
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const Line = ({ content, title }: { content: ReactNode; title: string }) => {
|
||||
return (
|
||||
<Inline gap={{ xs: 'xs', md: 'xl' }}>
|
||||
<div style={{ width: '100px' }}>
|
||||
<Grid gap={{ xs: 'xs', md: 'xl' }}>
|
||||
<Grid.Item colSpan={2}>
|
||||
<Text>{title}</Text>
|
||||
</div>
|
||||
{content}
|
||||
</Inline>
|
||||
</Grid.Item>
|
||||
<Grid.Item colSpan={10}>{content}</Grid.Item>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
.containerEmpty {
|
||||
padding: 24px;
|
||||
padding: 78px 40px;
|
||||
}
|
||||
|
||||
.breakpointContainer {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.codeBlock {
|
||||
border-radius: 0.5rem;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--canon-border-base);
|
||||
position: relative;
|
||||
background: transparent;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import ReactFrame from 'react-frame-component';
|
||||
import '@backstage/canon/src/css/core.css';
|
||||
@@ -16,10 +18,13 @@ export const Frame = ({ children }: { children: React.ReactNode }) => {
|
||||
<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" />
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -53,4 +53,14 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
padding: 0 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--canon-surface-2);
|
||||
}
|
||||
}
|
||||
|
||||
.line.active {
|
||||
background-color: var(--canon-surface-2);
|
||||
}
|
||||
|
||||
@@ -50,34 +50,40 @@ export const Docs = () => {
|
||||
}}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
{data.map(section => (
|
||||
<Fragment key={section.title}>
|
||||
<Box marginTop="lg" marginBottom="2xs">
|
||||
<Text variant="body" weight="bold">
|
||||
{section.title}
|
||||
</Text>
|
||||
</Box>
|
||||
{section.content.map(item => (
|
||||
<Link
|
||||
href={`${section.url}/${item.slug}`}
|
||||
key={item.slug}
|
||||
className={styles.line}
|
||||
>
|
||||
<Text variant="body">{item.title}</Text>
|
||||
<Text
|
||||
variant="body"
|
||||
style={{ color: 'var(--canon-text-secondary)' }}
|
||||
>
|
||||
{item.status === 'alpha' && 'Alpha'}
|
||||
{item.status === 'beta' && 'Beta'}
|
||||
{item.status === 'inProgress' && 'In Progress'}
|
||||
{item.status === 'stable' && 'Stable'}
|
||||
{item.status === 'deprecated' && 'Deprecated'}
|
||||
{data.map(section => {
|
||||
return (
|
||||
<Fragment key={section.title}>
|
||||
<Box marginTop="lg" marginBottom="2xs">
|
||||
<Text variant="body" weight="bold">
|
||||
{section.title}
|
||||
</Text>
|
||||
</Link>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</Box>
|
||||
{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 : ''}`}
|
||||
>
|
||||
<Text variant="body">{item.title}</Text>
|
||||
<Text
|
||||
variant="body"
|
||||
style={{ color: 'var(--canon-text-secondary)' }}
|
||||
>
|
||||
{item.status === 'alpha' && 'Alpha'}
|
||||
{item.status === 'beta' && 'Beta'}
|
||||
{item.status === 'inProgress' && 'In Progress'}
|
||||
{item.status === 'stable' && 'Stable'}
|
||||
{item.status === 'deprecated' && 'Deprecated'}
|
||||
</Text>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { TabsVersion, TabsPages, TabsTheme } from '../Tabs';
|
||||
import { Docs } from './docs';
|
||||
import { Playground } from './playground';
|
||||
import { cookies } from 'next/headers';
|
||||
import Link from 'next/link';
|
||||
|
||||
export const Sidebar = async () => {
|
||||
const cookieStore = await cookies();
|
||||
@@ -12,16 +13,18 @@ export const Sidebar = async () => {
|
||||
return (
|
||||
<div className={styles.sidebar}>
|
||||
<div className={styles.content}>
|
||||
<svg
|
||||
width="89"
|
||||
height="27"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={styles.logo}
|
||||
>
|
||||
<path d="M77.414 9.71h3.036v2.992l-.264-.022c.279-.88.748-1.65 1.408-2.31.675-.66 1.533-.99 2.574-.99 1.086 0 1.9.352 2.442 1.056.558.689.836 1.598.836 2.728v7.502H84.41v-6.6c0-.66-.117-1.159-.352-1.496-.234-.338-.623-.506-1.166-.506-.601 0-1.122.271-1.562.814a4.321 4.321 0 0 0-.88 1.848v5.94h-3.036V9.71ZM69.868 21.04c-1.13 0-2.142-.257-3.036-.77a5.547 5.547 0 0 1-2.068-2.09c-.484-.895-.726-1.892-.726-2.992 0-1.115.242-2.112.726-2.992a5.503 5.503 0 0 1 2.068-2.112c.88-.514 1.892-.77 3.036-.77 1.144 0 2.156.256 3.036.77a5.347 5.347 0 0 1 2.046 2.112c.498.88.748 1.87.748 2.97 0 1.114-.25 2.12-.748 3.014a5.343 5.343 0 0 1-2.068 2.09c-.88.513-1.885.77-3.014.77Zm0-2.618c.557 0 1.048-.132 1.474-.396a2.79 2.79 0 0 0 .99-1.144c.234-.499.352-1.064.352-1.694 0-.63-.118-1.188-.352-1.672a2.764 2.764 0 0 0-.99-1.166c-.426-.279-.917-.418-1.474-.418-.558 0-1.05.14-1.474.418a2.764 2.764 0 0 0-.99 1.166c-.22.484-.33 1.041-.33 1.672 0 .63.11 1.195.33 1.694.234.484.564.865.99 1.144.425.264.916.396 1.474.396ZM52.385 9.71h3.036v2.992l-.264-.022c.279-.88.748-1.65 1.408-2.31.675-.66 1.533-.99 2.574-.99 1.085 0 1.9.352 2.442 1.056.557.689.836 1.598.836 2.728v7.502h-3.036v-6.6c0-.66-.117-1.159-.352-1.496-.235-.338-.623-.506-1.166-.506-.601 0-1.122.271-1.562.814a4.321 4.321 0 0 0-.88 1.848v5.94h-3.036V9.71ZM43.904 20.952c-1.026 0-1.87-.308-2.53-.924-.66-.616-.99-1.416-.99-2.398 0-1.115.418-2.01 1.254-2.684.85-.69 2.105-1.034 3.762-1.034h2.75l-.924.352v-.462c0-.572-.176-1.02-.528-1.342-.352-.338-.931-.506-1.738-.506-.69 0-1.386.154-2.09.462-.704.308-1.29.69-1.76 1.144v-2.882c.47-.352 1.1-.66 1.892-.924a7.942 7.942 0 0 1 2.486-.396c1.599 0 2.78.41 3.542 1.232.778.806 1.166 1.914 1.166 3.322v5.742c0 .176.008.352.022.528.03.161.066.322.11.484h-3.014v-3.3l.044 1.386a4.044 4.044 0 0 1-1.32 1.606c-.572.396-1.283.594-2.134.594Zm.858-2.156c.558 0 1.049-.206 1.474-.616.44-.426.77-.954.99-1.584v-.792h-1.562c-.762 0-1.334.146-1.716.44-.381.278-.572.674-.572 1.188 0 .41.125.74.374.99.264.25.602.374 1.012.374ZM34.66 21.04c-1.525 0-2.874-.345-4.047-1.034-1.174-.704-2.09-1.68-2.75-2.926-.646-1.247-.968-2.662-.968-4.246 0-1.584.322-2.992.968-4.224.66-1.232 1.576-2.193 2.75-2.882 1.173-.704 2.522-1.056 4.048-1.056.968 0 1.818.11 2.552.33.748.22 1.356.506 1.826.858v3.498c-.396-.484-.96-.895-1.694-1.232-.719-.338-1.51-.506-2.376-.506-.939 0-1.775.22-2.508.66-.719.44-1.284 1.056-1.694 1.848-.396.792-.594 1.694-.594 2.706 0 1.026.198 1.943.594 2.75.41.792.975 1.408 1.694 1.848.733.44 1.57.66 2.508.66.88 0 1.68-.162 2.398-.484.718-.323 1.276-.726 1.672-1.21v3.41a5.686 5.686 0 0 1-1.87.902c-.704.22-1.54.33-2.508.33ZM11.275 6.271c.276.526.019 1.152-.464 1.498a5.846 5.846 0 0 0 1.004 10.082c.454.205.789.632.789 1.13v6.206a.837.837 0 0 1-.838.837C5.33 26.024.112 20.804.112 14.366V.862C.112.399.487.024.95.024c4.483 0 8.376 2.533 10.325 6.247Z" />
|
||||
<path d="M14.037 16.729a4.237 4.237 0 0 0 4.234-4.24 4.237 4.237 0 0 0-4.234-4.242 4.237 4.237 0 0 0-4.234 4.241 4.237 4.237 0 0 0 4.234 4.24Z" />
|
||||
</svg>
|
||||
<Link href="/">
|
||||
<svg
|
||||
width="89"
|
||||
height="27"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={styles.logo}
|
||||
>
|
||||
<path d="M77.414 9.71h3.036v2.992l-.264-.022c.279-.88.748-1.65 1.408-2.31.675-.66 1.533-.99 2.574-.99 1.086 0 1.9.352 2.442 1.056.558.689.836 1.598.836 2.728v7.502H84.41v-6.6c0-.66-.117-1.159-.352-1.496-.234-.338-.623-.506-1.166-.506-.601 0-1.122.271-1.562.814a4.321 4.321 0 0 0-.88 1.848v5.94h-3.036V9.71ZM69.868 21.04c-1.13 0-2.142-.257-3.036-.77a5.547 5.547 0 0 1-2.068-2.09c-.484-.895-.726-1.892-.726-2.992 0-1.115.242-2.112.726-2.992a5.503 5.503 0 0 1 2.068-2.112c.88-.514 1.892-.77 3.036-.77 1.144 0 2.156.256 3.036.77a5.347 5.347 0 0 1 2.046 2.112c.498.88.748 1.87.748 2.97 0 1.114-.25 2.12-.748 3.014a5.343 5.343 0 0 1-2.068 2.09c-.88.513-1.885.77-3.014.77Zm0-2.618c.557 0 1.048-.132 1.474-.396a2.79 2.79 0 0 0 .99-1.144c.234-.499.352-1.064.352-1.694 0-.63-.118-1.188-.352-1.672a2.764 2.764 0 0 0-.99-1.166c-.426-.279-.917-.418-1.474-.418-.558 0-1.05.14-1.474.418a2.764 2.764 0 0 0-.99 1.166c-.22.484-.33 1.041-.33 1.672 0 .63.11 1.195.33 1.694.234.484.564.865.99 1.144.425.264.916.396 1.474.396ZM52.385 9.71h3.036v2.992l-.264-.022c.279-.88.748-1.65 1.408-2.31.675-.66 1.533-.99 2.574-.99 1.085 0 1.9.352 2.442 1.056.557.689.836 1.598.836 2.728v7.502h-3.036v-6.6c0-.66-.117-1.159-.352-1.496-.235-.338-.623-.506-1.166-.506-.601 0-1.122.271-1.562.814a4.321 4.321 0 0 0-.88 1.848v5.94h-3.036V9.71ZM43.904 20.952c-1.026 0-1.87-.308-2.53-.924-.66-.616-.99-1.416-.99-2.398 0-1.115.418-2.01 1.254-2.684.85-.69 2.105-1.034 3.762-1.034h2.75l-.924.352v-.462c0-.572-.176-1.02-.528-1.342-.352-.338-.931-.506-1.738-.506-.69 0-1.386.154-2.09.462-.704.308-1.29.69-1.76 1.144v-2.882c.47-.352 1.1-.66 1.892-.924a7.942 7.942 0 0 1 2.486-.396c1.599 0 2.78.41 3.542 1.232.778.806 1.166 1.914 1.166 3.322v5.742c0 .176.008.352.022.528.03.161.066.322.11.484h-3.014v-3.3l.044 1.386a4.044 4.044 0 0 1-1.32 1.606c-.572.396-1.283.594-2.134.594Zm.858-2.156c.558 0 1.049-.206 1.474-.616.44-.426.77-.954.99-1.584v-.792h-1.562c-.762 0-1.334.146-1.716.44-.381.278-.572.674-.572 1.188 0 .41.125.74.374.99.264.25.602.374 1.012.374ZM34.66 21.04c-1.525 0-2.874-.345-4.047-1.034-1.174-.704-2.09-1.68-2.75-2.926-.646-1.247-.968-2.662-.968-4.246 0-1.584.322-2.992.968-4.224.66-1.232 1.576-2.193 2.75-2.882 1.173-.704 2.522-1.056 4.048-1.056.968 0 1.818.11 2.552.33.748.22 1.356.506 1.826.858v3.498c-.396-.484-.96-.895-1.694-1.232-.719-.338-1.51-.506-2.376-.506-.939 0-1.775.22-2.508.66-.719.44-1.284 1.056-1.694 1.848-.396.792-.594 1.694-.594 2.706 0 1.026.198 1.943.594 2.75.41.792.975 1.408 1.694 1.848.733.44 1.57.66 2.508.66.88 0 1.68-.162 2.398-.484.718-.323 1.276-.726 1.672-1.21v3.41a5.686 5.686 0 0 1-1.87.902c-.704.22-1.54.33-2.508.33ZM11.275 6.271c.276.526.019 1.152-.464 1.498a5.846 5.846 0 0 0 1.004 10.082c.454.205.789.632.789 1.13v6.206a.837.837 0 0 1-.838.837C5.33 26.024.112 20.804.112 14.366V.862C.112.399.487.024.95.024c4.483 0 8.376 2.533 10.325 6.247Z" />
|
||||
<path d="M14.037 16.729a4.237 4.237 0 0 0 4.234-4.24 4.237 4.237 0 0 0-4.234-4.242 4.237 4.237 0 0 0-4.234 4.241 4.237 4.237 0 0 0 4.234 4.24Z" />
|
||||
</svg>
|
||||
</Link>
|
||||
<div className={styles.actions}>
|
||||
<TabsVersion themeName={themeName} />
|
||||
<TabsTheme theme={theme} />
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { CodeBlock } from '../CodeBlock';
|
||||
import { Text } from '@backstage/canon';
|
||||
import { Collapsible } from '@base-ui-components/react/collapsible';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
interface SnippetProps {
|
||||
preview: ReactNode;
|
||||
code: string;
|
||||
align?: 'left' | 'center';
|
||||
px?: number;
|
||||
py?: number;
|
||||
open?: boolean;
|
||||
}
|
||||
|
||||
export const Snippet = ({
|
||||
preview,
|
||||
code = '',
|
||||
align = 'left',
|
||||
px = 2,
|
||||
py = 2,
|
||||
open = false,
|
||||
}: SnippetProps) => {
|
||||
return (
|
||||
<Collapsible.Root className={styles.container} defaultOpen={open}>
|
||||
<div
|
||||
className={`${styles.preview} ${styles[align]}`}
|
||||
style={{ padding: `${py}rem ${px}rem` }}
|
||||
>
|
||||
{preview}
|
||||
<Collapsible.Trigger className={styles.trigger}>
|
||||
<Text variant="body">View code</Text>
|
||||
</Collapsible.Trigger>
|
||||
</div>
|
||||
<Collapsible.Panel className={styles.Panel}>
|
||||
<CodeBlock code={code} />
|
||||
</Collapsible.Panel>
|
||||
</Collapsible.Root>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.preview {
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 0 0 1px var(--canon-border-base);
|
||||
background-color: var(--canon-background);
|
||||
background-image: radial-gradient(rgba(0, 0, 0, 0.08) 1px, transparent 0);
|
||||
background-position: calc((8px / 2) * -1) calc((8px / 2) * -1);
|
||||
background-size: 8px 8px;
|
||||
position: relative;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.trigger {
|
||||
all: unset;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .preview {
|
||||
background-image: radial-gradient(
|
||||
rgba(255, 255, 255, 0.1) 1px,
|
||||
transparent 0
|
||||
);
|
||||
}
|
||||
@@ -1,16 +1,33 @@
|
||||
import { Story } from '../components/Story';
|
||||
import { CodeBlock } from '../components/CodeBlock';
|
||||
import { PropsTable } from '../components/PropsTable';
|
||||
import { Snippet } from '../components/Snippet';
|
||||
import {
|
||||
Button1,
|
||||
Button2,
|
||||
Button3,
|
||||
Button4,
|
||||
Button5,
|
||||
Button6,
|
||||
} from '../snippets/button';
|
||||
|
||||
# Button
|
||||
|
||||
A button component that can be used to trigger actions.
|
||||
|
||||
<Story id="button--primary" />
|
||||
|
||||
<CodeBlock
|
||||
code={`<Button>Click me</Button>
|
||||
`}
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
preview={<Button1 />}
|
||||
code={`<Inline alignY="center">
|
||||
<Button iconStart="cloud" variant="primary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="secondary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="tertiary">
|
||||
Button
|
||||
</Button>
|
||||
</Inline>`}
|
||||
/>
|
||||
|
||||
## API reference
|
||||
@@ -50,14 +67,21 @@ A button component that can be used to trigger actions.
|
||||
|
||||
Here's a view when buttons have different variants.
|
||||
|
||||
<Story id="button--variants" />
|
||||
|
||||
<CodeBlock
|
||||
title="Usage"
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button1 />}
|
||||
code={`<Inline alignY="center">
|
||||
<Button variant="primary">Primary</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="tertiary">Tertiary</Button>
|
||||
<Button iconStart="cloud" variant="primary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="secondary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="tertiary">
|
||||
Button
|
||||
</Button>
|
||||
</Inline>`}
|
||||
/>
|
||||
|
||||
@@ -65,10 +89,11 @@ Here's a view when buttons have different variants.
|
||||
|
||||
Here's a view when buttons have different sizes.
|
||||
|
||||
<Story id="button--sizes" />
|
||||
|
||||
<CodeBlock
|
||||
title="Usage"
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button2 />}
|
||||
code={`<Inline alignY="center">
|
||||
<Button size="small">Small</Button>
|
||||
<Button size="medium">Medium</Button>
|
||||
@@ -79,10 +104,11 @@ Here's a view when buttons have different sizes.
|
||||
|
||||
Here's a view when buttons have icons.
|
||||
|
||||
<Story id="button--with-icons" />
|
||||
|
||||
<CodeBlock
|
||||
title="Usage"
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button3 />}
|
||||
code={`<Inline alignY="center">
|
||||
<Button iconStart="cloud">Button</Button>
|
||||
<Button iconEnd="chevronRight">Button</Button>
|
||||
@@ -94,9 +120,11 @@ Here's a view when buttons have icons.
|
||||
|
||||
Here's a view when buttons are full width.
|
||||
|
||||
<Story id="button--full-width" />
|
||||
|
||||
<CodeBlock
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button4 />}
|
||||
code={`<Stack style={{ width: '300px' }}>
|
||||
<Button fullWidth>Full width</Button>
|
||||
</Stack>`}
|
||||
@@ -106,17 +134,23 @@ Here's a view when buttons are full width.
|
||||
|
||||
Here's a view when buttons are disabled.
|
||||
|
||||
<Story id="button--disabled" />
|
||||
|
||||
<CodeBlock title="Usage" code={`<Button disabled>Button</Button>`} />
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button5 />}
|
||||
code={`<Button disabled>Button</Button>`}
|
||||
/>
|
||||
|
||||
### Responsive
|
||||
|
||||
Here's a view when buttons are responsive.
|
||||
|
||||
<Story id="button--responsive" />
|
||||
|
||||
<CodeBlock
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
open
|
||||
preview={<Button6 />}
|
||||
code={`<Button
|
||||
variant={{ xs: 'primary', sm: 'secondary', md: 'tertiary' }}
|
||||
size={{ xs: 'small', sm: 'medium' }}>
|
||||
|
||||
@@ -5,9 +5,6 @@ const nextConfig: NextConfig = {
|
||||
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
|
||||
};
|
||||
|
||||
const withMDX = createMDX({
|
||||
// Add markdown plugins here, as desired
|
||||
});
|
||||
const withMDX = createMDX({});
|
||||
|
||||
// Merge MDX config with Next.js config
|
||||
export default withMDX(nextConfig);
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
'use client';
|
||||
|
||||
import { ButtonProps, Text } from '@backstage/canon';
|
||||
import { Stack, Inline, Button } from '@backstage/canon';
|
||||
|
||||
const variants: string[] = ['primary', 'secondary', 'tertiary'];
|
||||
|
||||
const capitalizeFirstLetter = (string: string): string => {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
};
|
||||
|
||||
export const Button1 = () => {
|
||||
return (
|
||||
<Inline alignY="center">
|
||||
<Button iconStart="cloud" variant="primary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="secondary">
|
||||
Button
|
||||
</Button>
|
||||
<Button iconStart="cloud" variant="tertiary">
|
||||
Button
|
||||
</Button>
|
||||
</Inline>
|
||||
);
|
||||
};
|
||||
|
||||
export const Button2 = () => {
|
||||
return (
|
||||
<Inline alignY="center">
|
||||
<Button size="small">Small</Button>
|
||||
<Button size="medium">Medium</Button>
|
||||
</Inline>
|
||||
);
|
||||
};
|
||||
|
||||
export const Button3 = () => {
|
||||
return (
|
||||
<Inline alignY="center">
|
||||
<Button iconStart="cloud">Button</Button>
|
||||
<Button iconEnd="chevronRight">Button</Button>
|
||||
<Button
|
||||
iconStart="cloud"
|
||||
iconEnd="chevronRight"
|
||||
style={{ width: '200px' }}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
</Inline>
|
||||
);
|
||||
};
|
||||
|
||||
export const Button4 = () => {
|
||||
return (
|
||||
<Stack style={{ width: '300px' }}>
|
||||
<Button>Full width</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export const Button5 = () => {
|
||||
return <Button disabled>Button</Button>;
|
||||
};
|
||||
|
||||
export const Button6 = () => {
|
||||
return null;
|
||||
return (
|
||||
<Button
|
||||
variant={{ xs: 'primary', sm: 'secondary', md: 'tertiary' }}
|
||||
size={{ xs: 'small', sm: 'medium' }}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const ButtonPlayground = () => {
|
||||
return (
|
||||
<Stack>
|
||||
{variants.map(variant => (
|
||||
<Stack key={variant}>
|
||||
<Text>{capitalizeFirstLetter(variant as string)}</Text>
|
||||
{['small', 'medium'].map(size => (
|
||||
<Inline alignY="center" key={size}>
|
||||
<Button
|
||||
iconStart="cloud"
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconEnd="chevronRight"
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
<Button
|
||||
iconStart="cloud"
|
||||
iconEnd="chevronRight"
|
||||
style={{ width: '200px' }}
|
||||
variant={variant as ButtonProps['variant']}
|
||||
size={size as ButtonProps['size']}
|
||||
>
|
||||
Button
|
||||
</Button>
|
||||
</Inline>
|
||||
))}
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Text, Heading } from '@backstage/canon';
|
||||
import { Stack } from '@backstage/canon';
|
||||
|
||||
export const HeadingPlayground = () => {
|
||||
return (
|
||||
<Stack>
|
||||
<Text>All variants</Text>
|
||||
<Heading variant="display">Display</Heading>
|
||||
<Heading variant="title1">Title 1</Heading>
|
||||
<Heading variant="title2">Title 2</Heading>
|
||||
<Heading variant="title3">Title 3</Heading>
|
||||
<Heading variant="title4">Title 4</Heading>
|
||||
<Heading variant="title5">Title 5</Heading>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Text } from '@backstage/canon';
|
||||
import { Stack } from '@backstage/canon';
|
||||
|
||||
export const TextPlayground = () => {
|
||||
return (
|
||||
<Stack>
|
||||
<Text>Subtitle</Text>
|
||||
<Text variant="subtitle" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Body</Text>
|
||||
<Text variant="body" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Caption</Text>
|
||||
<Text variant="caption" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
<Text>Label</Text>
|
||||
<Text variant="label" style={{ maxWidth: '600px' }}>
|
||||
A man looks at a painting in a museum and says, “Brothers and sisters I
|
||||
have none, but that man's father is my father's son.” Who is
|
||||
in the painting?
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -70,7 +70,7 @@ export const components: Page[] = [
|
||||
{
|
||||
title: 'Button',
|
||||
slug: 'button',
|
||||
status: 'alpha',
|
||||
status: 'inProgress',
|
||||
},
|
||||
{
|
||||
title: 'Checkbox',
|
||||
|
||||
Reference in New Issue
Block a user