diff --git a/microsite-canon/app/playground/button.tsx b/microsite-canon/app/playground/button.tsx deleted file mode 100644 index 14b44e5d1c..0000000000 --- a/microsite-canon/app/playground/button.tsx +++ /dev/null @@ -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 ( - - {variants.map(({ variant, size }) => ( - - - {capitalizeFirstLetter(variant as string)} -{' '} - {capitalizeFirstLetter(size as string)} - - - - - - - - ))} - - ); -}; diff --git a/microsite-canon/app/playground/page.tsx b/microsite-canon/app/playground/page.tsx index f7823030be..fcd8866770 100644 --- a/microsite-canon/app/playground/page.tsx +++ b/microsite-canon/app/playground/page.tsx @@ -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') && ( } title="Checkbox" /> )} + {selectedComponents.find(c => c === 'heading') && ( + } title="Heading" /> + )} + {selectedComponents.find(c => c === 'text') && ( + } title="Text" /> + )} ); }; const Line = ({ content, title }: { content: ReactNode; title: string }) => { return ( - -
+ + {title} -
- {content} -
+ + {content} + ); }; diff --git a/microsite-canon/app/playground/styles.module.css b/microsite-canon/app/playground/styles.module.css index 28763e4126..5280021836 100644 --- a/microsite-canon/app/playground/styles.module.css +++ b/microsite-canon/app/playground/styles.module.css @@ -7,7 +7,7 @@ } .containerEmpty { - padding: 24px; + padding: 78px 40px; } .breakpointContainer { diff --git a/microsite-canon/components/CodeBlock/styles.module.css b/microsite-canon/components/CodeBlock/styles.module.css index 6affa1b13d..e74714e07c 100644 --- a/microsite-canon/components/CodeBlock/styles.module.css +++ b/microsite-canon/components/CodeBlock/styles.module.css @@ -1,5 +1,5 @@ .codeBlock { - border-radius: 0.5rem; + border-radius: 4px; border: 1px solid var(--canon-border-base); position: relative; background: transparent; diff --git a/microsite-canon/components/Frame/index.tsx b/microsite-canon/components/Frame/index.tsx index 40b6641dfb..6f11ea1665 100644 --- a/microsite-canon/components/Frame/index.tsx +++ b/microsite-canon/components/Frame/index.tsx @@ -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 }) => {
`} + mountTarget=".frame-root" head={ <> + } > diff --git a/microsite-canon/components/Sidebar/Sidebar.module.css b/microsite-canon/components/Sidebar/Sidebar.module.css index ac9aefb0a6..112ef0fe4b 100644 --- a/microsite-canon/components/Sidebar/Sidebar.module.css +++ b/microsite-canon/components/Sidebar/Sidebar.module.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); } diff --git a/microsite-canon/components/Sidebar/docs.tsx b/microsite-canon/components/Sidebar/docs.tsx index 1c88adcc34..2dea964d64 100644 --- a/microsite-canon/components/Sidebar/docs.tsx +++ b/microsite-canon/components/Sidebar/docs.tsx @@ -50,34 +50,40 @@ export const Docs = () => { }} transition={{ duration: 0.2 }} > - {data.map(section => ( - - - - {section.title} - - - {section.content.map(item => ( - - {item.title} - - {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 ( + + + + {section.title} - - ))} - - ))} + + {section.content.map(item => { + const isActive = pathname === `${section.url}/${item.slug}`; + + return ( + + {item.title} + + {item.status === 'alpha' && 'Alpha'} + {item.status === 'beta' && 'Beta'} + {item.status === 'inProgress' && 'In Progress'} + {item.status === 'stable' && 'Stable'} + {item.status === 'deprecated' && 'Deprecated'} + + + ); + })} + + ); + })} ); }; diff --git a/microsite-canon/components/Sidebar/index.tsx b/microsite-canon/components/Sidebar/index.tsx index ef53c99aa7..9bce121760 100644 --- a/microsite-canon/components/Sidebar/index.tsx +++ b/microsite-canon/components/Sidebar/index.tsx @@ -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 (
- - - - + + + + + +
diff --git a/microsite-canon/components/Snippet/index.tsx b/microsite-canon/components/Snippet/index.tsx new file mode 100644 index 0000000000..0893eed51c --- /dev/null +++ b/microsite-canon/components/Snippet/index.tsx @@ -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 ( + +
+ {preview} + + View code + +
+ + + +
+ ); +}; diff --git a/microsite-canon/components/Snippet/styles.module.css b/microsite-canon/components/Snippet/styles.module.css new file mode 100644 index 0000000000..ed3faa4dcd --- /dev/null +++ b/microsite-canon/components/Snippet/styles.module.css @@ -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 + ); +} diff --git a/microsite-canon/content/button.mdx b/microsite-canon/content/button.mdx index 1e205cdb3c..bed9477a17 100644 --- a/microsite-canon/content/button.mdx +++ b/microsite-canon/content/button.mdx @@ -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. - - -Click me -`} +} + code={` + + + +`} /> ## 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. - - -} code={` - - - + + + `} /> @@ -65,10 +89,11 @@ Here's a view when buttons have different variants. Here's a view when buttons have different sizes. - - -} code={` @@ -79,10 +104,11 @@ Here's a view when buttons have different sizes. Here's a view when buttons have icons. - - -} code={` @@ -94,9 +120,11 @@ Here's a view when buttons have icons. Here's a view when buttons are full width. - - -} code={` `} @@ -106,17 +134,23 @@ Here's a view when buttons are full width. Here's a view when buttons are disabled. - - -Button`} /> +} + code={``} +/> ### Responsive Here's a view when buttons are responsive. - - -} code={` + + + + ); +}; + +export const Button2 = () => { + return ( + + + + + ); +}; + +export const Button3 = () => { + return ( + + + + + + ); +}; + +export const Button4 = () => { + return ( + + + + ); +}; + +export const Button5 = () => { + return ; +}; + +export const Button6 = () => { + return null; + return ( + + ); +}; + +export const ButtonPlayground = () => { + return ( + + {variants.map(variant => ( + + {capitalizeFirstLetter(variant as string)} + {['small', 'medium'].map(size => ( + + + + + + ))} + + ))} + + ); +}; diff --git a/microsite-canon/app/playground/checkbox.tsx b/microsite-canon/snippets/checkbox.tsx similarity index 100% rename from microsite-canon/app/playground/checkbox.tsx rename to microsite-canon/snippets/checkbox.tsx diff --git a/microsite-canon/snippets/heading.tsx b/microsite-canon/snippets/heading.tsx new file mode 100644 index 0000000000..c6b3ec5902 --- /dev/null +++ b/microsite-canon/snippets/heading.tsx @@ -0,0 +1,16 @@ +import { Text, Heading } from '@backstage/canon'; +import { Stack } from '@backstage/canon'; + +export const HeadingPlayground = () => { + return ( + + All variants + Display + Title 1 + Title 2 + Title 3 + Title 4 + Title 5 + + ); +}; diff --git a/microsite-canon/snippets/text.tsx b/microsite-canon/snippets/text.tsx new file mode 100644 index 0000000000..ab3dbafb32 --- /dev/null +++ b/microsite-canon/snippets/text.tsx @@ -0,0 +1,33 @@ +import { Text } from '@backstage/canon'; +import { Stack } from '@backstage/canon'; + +export const TextPlayground = () => { + return ( + + Subtitle + + 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? + + Body + + 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? + + Caption + + 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? + + Label + + 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? + + + ); +}; diff --git a/microsite-canon/utils/data.ts b/microsite-canon/utils/data.ts index c5531fc8e8..f99ef2dbe8 100644 --- a/microsite-canon/utils/data.ts +++ b/microsite-canon/utils/data.ts @@ -70,7 +70,7 @@ export const components: Page[] = [ { title: 'Button', slug: 'button', - status: 'alpha', + status: 'inProgress', }, { title: 'Checkbox',