From 39b3c2e12395f8527b95480e79215bd53394bb2e Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 31 Dec 2024 17:33:11 +0100 Subject: [PATCH] Add more functionalities to our playground Signed-off-by: Charles de Dreuille --- microsite-canon/app/playground/button.tsx | 50 +++++++++++++ microsite-canon/app/playground/checkbox.tsx | 18 +++++ microsite-canon/app/playground/page.tsx | 73 ++++++++++++------- .../app/playground/styles.module.css | 4 + microsite-canon/app/providers.tsx | 5 +- .../components/Sidebar/Sidebar.module.css | 2 +- microsite-canon/components/Sidebar/index.tsx | 1 + .../components/Sidebar/playground.tsx | 39 +++++++++- microsite-canon/utils/data.ts | 8 +- microsite-canon/utils/playground-context.tsx | 41 +++++++++++ .../canon/src/components/Button/Button.tsx | 5 +- .../canon/src/components/Button/styles.css | 6 +- packages/canon/src/components/Button/types.ts | 1 + .../canon/src/components/Table/styles.css | 2 +- 14 files changed, 219 insertions(+), 36 deletions(-) create mode 100644 microsite-canon/app/playground/button.tsx create mode 100644 microsite-canon/app/playground/checkbox.tsx create mode 100644 microsite-canon/utils/playground-context.tsx diff --git a/microsite-canon/app/playground/button.tsx b/microsite-canon/app/playground/button.tsx new file mode 100644 index 0000000000..14b44e5d1c --- /dev/null +++ b/microsite-canon/app/playground/button.tsx @@ -0,0 +1,50 @@ +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/checkbox.tsx b/microsite-canon/app/playground/checkbox.tsx new file mode 100644 index 0000000000..5bb0d5f610 --- /dev/null +++ b/microsite-canon/app/playground/checkbox.tsx @@ -0,0 +1,18 @@ +import { Text } from '@backstage/canon'; +import { Stack, Inline, Checkbox } from '@backstage/canon'; + +export const CheckboxPlayground = () => { + return ( + + + All variants + + + + + + + + + ); +}; diff --git a/microsite-canon/app/playground/page.tsx b/microsite-canon/app/playground/page.tsx index 99ade9b774..f7823030be 100644 --- a/microsite-canon/app/playground/page.tsx +++ b/microsite-canon/app/playground/page.tsx @@ -1,15 +1,32 @@ 'use client'; -import styles from './styles.module.css'; -import { Text } from '@backstage/canon'; +import { Inline, Stack, Text } from '@backstage/canon'; import { screenSizes } from '@/utils/data'; import { Frame } from '@/components/Frame'; -import { Stack, Inline, Button } from '@backstage/canon'; +import { usePlayground } from '@/utils/playground-context'; +import { ButtonPlayground } from './button'; +import { CheckboxPlayground } from './checkbox'; +import styles from './styles.module.css'; +import { ReactNode } from 'react'; export default function PlaygroundPage() { + const { selectedScreenSizes, selectedComponents } = usePlayground(); + + const filteredScreenSizes = screenSizes.filter(item => + selectedScreenSizes.includes(item.slug), + ); + + if (filteredScreenSizes.length === 0) { + return ( +
+ +
+ ); + } + return (
- {screenSizes.map(screenSize => ( + {filteredScreenSizes.map(screenSize => (
- - - Button - Primary - Small - - - - - - - - - - +
@@ -48,3 +45,29 @@ export default function PlaygroundPage() {
); } + +const Content = () => { + const { selectedComponents } = usePlayground(); + + return ( + + {selectedComponents.find(c => c === 'button') && ( + } title="Button" /> + )} + {selectedComponents.find(c => c === 'checkbox') && ( + } title="Checkbox" /> + )} + + ); +}; + +const Line = ({ content, title }: { content: ReactNode; title: string }) => { + return ( + +
+ {title} +
+ {content} +
+ ); +}; diff --git a/microsite-canon/app/playground/styles.module.css b/microsite-canon/app/playground/styles.module.css index 13b896a879..28763e4126 100644 --- a/microsite-canon/app/playground/styles.module.css +++ b/microsite-canon/app/playground/styles.module.css @@ -6,6 +6,10 @@ overflow-x: scroll; } +.containerEmpty { + padding: 24px; +} + .breakpointContainer { flex-shrink: 0; margin-top: 40px; diff --git a/microsite-canon/app/providers.tsx b/microsite-canon/app/providers.tsx index 23229653ac..9f999602f6 100644 --- a/microsite-canon/app/providers.tsx +++ b/microsite-canon/app/providers.tsx @@ -3,11 +3,14 @@ import { ReactNode } from 'react'; import { CanonProvider } from '@backstage/canon'; import { ThemeProvider } from 'next-themes'; +import { PlaygroundProvider } from '@/utils/playground-context'; export const Providers = ({ children }: { children: ReactNode }) => { return ( - {children} + + {children} + ); }; diff --git a/microsite-canon/components/Sidebar/Sidebar.module.css b/microsite-canon/components/Sidebar/Sidebar.module.css index 91dc8e03cc..738e7877c2 100644 --- a/microsite-canon/components/Sidebar/Sidebar.module.css +++ b/microsite-canon/components/Sidebar/Sidebar.module.css @@ -13,7 +13,7 @@ overflow: hidden; } -.sidebar svg path { +.logo path { fill: var(--canon-text-primary); } diff --git a/microsite-canon/components/Sidebar/index.tsx b/microsite-canon/components/Sidebar/index.tsx index 641f0d73ad..5778efaba0 100644 --- a/microsite-canon/components/Sidebar/index.tsx +++ b/microsite-canon/components/Sidebar/index.tsx @@ -12,6 +12,7 @@ export const Sidebar = () => { height="27" fill="none" xmlns="http://www.w3.org/2000/svg" + className={styles.logo} > diff --git a/microsite-canon/components/Sidebar/playground.tsx b/microsite-canon/components/Sidebar/playground.tsx index 8a6eaef4f8..da772ee3f9 100644 --- a/microsite-canon/components/Sidebar/playground.tsx +++ b/microsite-canon/components/Sidebar/playground.tsx @@ -5,11 +5,38 @@ import { Box, Checkbox, Text } from '@backstage/canon'; import { motion } from 'framer-motion'; import styles from './Sidebar.module.css'; import { usePathname } from 'next/navigation'; -import { screenSizes } from '@/utils/data'; +import { screenSizes, ScreenSize } 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]); + } + }; + + console.log(selectedComponents); return ( { {components.map(({ slug, title }) => (
{title} - + handleComponentCheckboxChange(slug)} + />
))} @@ -46,7 +76,10 @@ export const Playground = () => { {screenSizes.map(({ slug, title }) => (
{title} - + handleCheckboxChange(slug)} + />
))}
diff --git a/microsite-canon/utils/data.ts b/microsite-canon/utils/data.ts index 206fa8c0ce..ca95a2a350 100644 --- a/microsite-canon/utils/data.ts +++ b/microsite-canon/utils/data.ts @@ -71,7 +71,13 @@ export const components = [ }, ]; -export const screenSizes = [ +export type ScreenSize = { + title: string; + slug: string; + width: number; +}; + +export const screenSizes: ScreenSize[] = [ { title: 'Mobile', slug: 'mobile', width: 390 }, { title: 'Tablet', slug: 'tablet', width: 768 }, { title: 'Desktop', slug: 'desktop', width: 1280 }, diff --git a/microsite-canon/utils/playground-context.tsx b/microsite-canon/utils/playground-context.tsx new file mode 100644 index 0000000000..63ff1e20f7 --- /dev/null +++ b/microsite-canon/utils/playground-context.tsx @@ -0,0 +1,41 @@ +import React, { createContext, useContext, ReactNode, useState } from 'react'; +import { components } from './data'; + +// Create a context with an empty array as the default value +const PlaygroundContext = createContext<{ + selectedScreenSizes: string[]; + setSelectedScreenSizes: (screenSizes: string[]) => void; + selectedComponents: string[]; + setSelectedComponents: (components: string[]) => void; +}>({ + selectedScreenSizes: [], + setSelectedScreenSizes: () => {}, + selectedComponents: [], + setSelectedComponents: () => {}, +}); + +// Create a provider component +export const PlaygroundProvider = ({ children }: { children: ReactNode }) => { + const [selectedScreenSizes, setSelectedScreenSizes] = useState([]); + const [selectedComponents, setSelectedComponents] = useState( + components.map(component => component.slug), + ); + + return ( + + {children} + + ); +}; + +// Create a custom hook to use the screen sizes +export const usePlayground = () => { + return useContext(PlaygroundContext); +}; diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index e4166e5c79..081d09a1d5 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -29,6 +29,8 @@ export const Button = forwardRef( iconStart, iconEnd, children, + style, + ...rest } = props; const { getResponsiveValue } = useCanon(); @@ -39,7 +41,7 @@ export const Button = forwardRef( return (