diff --git a/.changeset/shiny-dingos-check.md b/.changeset/shiny-dingos-check.md new file mode 100644 index 000000000..b047afaed --- /dev/null +++ b/.changeset/shiny-dingos-check.md @@ -0,0 +1,5 @@ +--- +'spectacle': minor +--- + +feat: Add single and multiple code pane Slide Layouts with options. diff --git a/docs/api-reference.md b/docs/api-reference.md index 440ee1207..e43c2fca7 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -448,3 +448,38 @@ A vertically-centered Quote layout for if you want to present a quote and attrib | `attribution` | `ReactNode` | ✅ | `William Shakespeare` | | `quoteProps` | [Text Props](#typography-tags) | ❌ | { fontSize: "100px" } | | `attributionProps` | [Text Props](#typography-tags) | ❌ | { fontSize: "48px" } | + +### `SlideLayout.Code` + +A layout with a single code pane and an optional title for if you want one code block per slide. + +| Props | Type | Required | Example | +|-----------------|-----------------------------------|----------|------------------------------------------------------------------| +| `...slideProps` | [Slide Props](#slide) | ❌ | | +| `title` | `string` | ❌ | `Show me the code!` | +| `titleProps` | [Heading Props](#typography-tags) | ❌ | `{ color: 'red' }` | +| `children` | `string` | ✅ | `const Component = (props: componentProps): JSX.Element = {...}` | +| `language` | `boolean` | ✅ | `false` | +| `codePaneProps` | `CodePaneProps` | ❌ | | + +### `SlideLayout.MultiCodeLayout` + +A layout with multiple code panes and optional descriptions, and an optional title for if you want more than one code block per slide or code with description text. + +| Props | Type | Required | Example | +|-----------------|-----------------------------------|----------|---------------------------------------------------------------------------------------------------------------------| +| `...slideProps` | [Slide Props](#slide) | ❌ | | +| `title` | `string` | ❌ | `Show me the code!` | +| `titleProps` | [Heading Props](#typography-tags) | ❌ | `{ color: 'red' }` | +| `numColumns` | `number` | ❌ | `{2}` | +| `codeBlocks` | `CodeBlock[]` | ✅ | `[{ code: 'console.log("hello world!")', language: 'jsx', description: 'Say hello', codePaneProps: {...} }, {...}]` | + +where + +```ts +type CodeBlock = Omit & { + code: CodePaneProps['children']; + description?: string | ReactNode; + descriptionProps?: ComponentProps; +} +``` diff --git a/packages/spectacle/src/components/code-pane.tsx b/packages/spectacle/src/components/code-pane.tsx index 496891cb5..000f546a4 100644 --- a/packages/spectacle/src/components/code-pane.tsx +++ b/packages/spectacle/src/components/code-pane.tsx @@ -149,7 +149,6 @@ const CodePane = forwardRef( * default theme with no valid values. */ const { - size: { width = 1366 }, space = [0, 0, 0], fontSizes: { monospace = '20px' } } = theme; @@ -157,7 +156,6 @@ const CodePane = forwardRef( return { padding: space[0], margin: 0, - width: width - space[2] * 2 - space[0] * 2, fontSize: monospace }; }, [theme]); diff --git a/packages/spectacle/src/components/slide-layout.test.tsx b/packages/spectacle/src/components/slide-layout.test.tsx index da61e06c8..12e1886a7 100644 --- a/packages/spectacle/src/components/slide-layout.test.tsx +++ b/packages/spectacle/src/components/slide-layout.test.tsx @@ -272,4 +272,59 @@ describe('SlideLayout', () => { fontSize: '48px' }); }); + + it('SlideLayout.Code should render a titled slide with title props passed through', () => { + const { getByText } = renderInDeck( + + {'console.log("Hello World!");'} + + ); + + expect(getByText('Hello World!')).toHaveStyle({ fontSize: '24px' }); + }); + + it('SlideLayout.MultiCodeLayout should contain more than one code pane', () => { + const { queryAllByTestId } = renderInDeck( + + ); + + expect(queryAllByTestId('CodePane')).toHaveLength(2); + }); + + it('SlideLayout.MultiCodeLayout should render multiple code panes with description props passed through', () => { + const { getByText } = renderInDeck( + + ); + + expect(getByText('assign a variable to a string.')).toHaveStyle({ + color: 'blue' + }); + expect(getByText('reassign the variable.')).toHaveStyle({ + color: 'cyan' + }); + }); }); diff --git a/packages/spectacle/src/components/slide-layout.tsx b/packages/spectacle/src/components/slide-layout.tsx index b56845f84..0ed57ecc0 100644 --- a/packages/spectacle/src/components/slide-layout.tsx +++ b/packages/spectacle/src/components/slide-layout.tsx @@ -1,5 +1,7 @@ +import * as React from 'react'; import Slide, { SlideProps } from './slide/slide'; -import { Box, FlexBox } from './layout-primitives'; +import { Box, FlexBox, Grid } from './layout-primitives'; +import CodePane, { CodePaneProps } from './code-pane'; import { ComponentProps, Fragment, ReactNode } from 'react'; import { Heading, @@ -192,11 +194,110 @@ const Quote = ({ ); +/** + * Generic Codepane utility with optional Description text + */ +const CodeLayout = ({ + text, + textProps, + children, + ...props +}: CodePaneProps & { + text?: string | ReactNode; + textProps?: ComponentProps; +}) => ( + + {text ? ( + + {text} + + ) : null} + {children} + +); + +/** + * single Code Pane with optional Title layout + */ +const Code = ({ + children, + language, + title, + titleProps, + codePaneProps, + ...rest +}: Omit & { + children: string; + language: string; + title?: string | ReactNode; + titleProps?: ComponentProps; + codePaneProps?: CodePaneProps; +}) => { + return ( + + + {title ? {title} : null} + + {children} + + + + ); +}; + +/** + * multiple Code Panes with optional Description, with optional Title layout + */ +const MultiCodeLayout = ({ + codeBlocks, + title, + titleProps, + numColumns = 1, + ...rest +}: Omit & { + codeBlocks: Array< + Omit & { + code: CodePaneProps['children']; + description?: string | ReactNode; + descriptionProps?: ComponentProps; + } + >; + title?: string | ReactNode; + titleProps?: ComponentProps; + numColumns?: number; +}) => { + return ( + + + {title ? {title} : null} + + {codeBlocks.map( + ({ description, descriptionProps, code, ...codePaneProps }, i) => ( + + {code} + + ) + )} + + + + ); +}; + /** * Layouts to consider: * - Image (left, right, full bleed?) * - Intro - * - Code Snippet (syntax highlighting) */ export default { @@ -207,5 +308,7 @@ export default { Section, BigFact, Quote, - Statement + Statement, + Code, + MultiCodeLayout };