diff --git a/.changeset/tame-mice-lick.md b/.changeset/tame-mice-lick.md new file mode 100644 index 000000000..96b33bb6a --- /dev/null +++ b/.changeset/tame-mice-lick.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/wonder-blocks-toolbar": minor +--- + +Allow title to also support React nodes diff --git a/__docs__/wonder-blocks-toolbar/toolbar.argtypes.tsx b/__docs__/wonder-blocks-toolbar/toolbar.argtypes.tsx index 0d0578c28..a80862c0b 100644 --- a/__docs__/wonder-blocks-toolbar/toolbar.argtypes.tsx +++ b/__docs__/wonder-blocks-toolbar/toolbar.argtypes.tsx @@ -7,6 +7,7 @@ import magnifyingGlassPlus from "@phosphor-icons/core/regular/magnifying-glass-p import magnifyingGlassMinus from "@phosphor-icons/core/regular/magnifying-glass-minus.svg"; import Button from "@khanacademy/wonder-blocks-button"; +import {View} from "@khanacademy/wonder-blocks-core"; import IconButton from "@khanacademy/wonder-blocks-icon-button"; import {Strut} from "@khanacademy/wonder-blocks-layout"; import Link from "@khanacademy/wonder-blocks-link"; @@ -45,6 +46,23 @@ export const leftContentMappings: Mappings = { ), + exitWithTitle: ( + + + | + + Algebra TestBETA + + + ), }; const buttonStyle = {width: 160} as const; diff --git a/__docs__/wonder-blocks-toolbar/toolbar.stories.tsx b/__docs__/wonder-blocks-toolbar/toolbar.stories.tsx index a62763268..e0eb7bcea 100644 --- a/__docs__/wonder-blocks-toolbar/toolbar.stories.tsx +++ b/__docs__/wonder-blocks-toolbar/toolbar.stories.tsx @@ -3,7 +3,7 @@ import {StyleSheet} from "aphrodite"; import type {Meta, StoryObj} from "@storybook/react"; import {View} from "@khanacademy/wonder-blocks-core"; -import {spacing} from "@khanacademy/wonder-blocks-tokens"; +import {semanticColor, spacing} from "@khanacademy/wonder-blocks-tokens"; import Toolbar from "@khanacademy/wonder-blocks-toolbar"; import packageConfig from "../../packages/wonder-blocks-toolbar/package.json"; @@ -211,3 +211,27 @@ Dark.parameters = { }, }, }; + +/** + * Sometimes we need to have a custom toolbar to include a custom component or a + * more complex layout in the center of the toolbar. This can be achieved by + * passing a React node to the `title` prop. + * + * **NOTE:** This approach should be used with caution, as it may break the + * layout of the toolbar. + */ +export const CustomToolbar: StoryComponentType = { + args: { + leftContent: leftContentMappings.exitWithTitle, + rightContent: rightContentMappings.primaryButton, + title: ( + + ), + }, +}; diff --git a/packages/wonder-blocks-toolbar/src/components/toolbar.tsx b/packages/wonder-blocks-toolbar/src/components/toolbar.tsx index 96322e75c..04ed13840 100644 --- a/packages/wonder-blocks-toolbar/src/components/toolbar.tsx +++ b/packages/wonder-blocks-toolbar/src/components/toolbar.tsx @@ -40,22 +40,16 @@ type Props = AriaProps & { */ subtitle?: string; /** - * The main title rendered in larger bold text. + * The main title rendered in larger bold text. It also supports rendering + * React nodes (use with caution). */ - title?: string; + title?: string | React.ReactNode; /** * Test ID used for e2e testing. */ testId?: string; }; -type DefaultProps = { - color: Props["color"]; - leftContent: Props["leftContent"]; - rightContent: Props["rightContent"]; - size: Props["size"]; -}; - /** * The `Toolbar` component is a generic toolbar wrapper that exposes * customization options. An optional `title` and `subtitle` property can be @@ -73,74 +67,70 @@ type DefaultProps = { * /> * ``` */ -export default class Toolbar extends React.Component { - static defaultProps: DefaultProps = { - color: "light", - leftContent: null, - rightContent: null, - size: "medium", - }; - - render(): React.ReactNode { - const {color, leftContent, rightContent, size, subtitle, title} = - this.props; - - const TitleComponent = subtitle ? LabelLarge : HeadingSmall; +export default function Toolbar({ + color = "light", + leftContent, + rightContent, + size = "medium", + subtitle, + title, +}: Props): React.ReactElement { + const TitleComponent = subtitle ? LabelLarge : HeadingSmall; - return ( + return ( + - - {leftContent} - + {leftContent} + - {title && ( - - - - {title} - - {subtitle && ( - - {subtitle} - - )} - + {title && typeof title === "string" ? ( + + + + {title} + + {subtitle && ( + + {subtitle} + + )} - )} - - - {rightContent} + ) : ( + // We don't use wideColumn here to allow more flexibility with + // the custom node. + + {title} + + )} + + + {rightContent} - ); - } + + ); } const sharedStyles = StyleSheet.create({