|
| 1 | +import { Meta, Story } from '@storybook/addon-docs/blocks'; |
| 2 | +import TopBarNavigationStories, { |
| 3 | + CssOverrides, |
| 4 | + CustomTheme, |
| 5 | + Default, |
| 6 | + WithIcon, |
| 7 | + WithMenu, |
| 8 | + Selected, |
| 9 | + Disabled, |
| 10 | +} from './TopBarNavigation.stories'; |
| 11 | +import { |
| 12 | + SandboxReact, |
| 13 | + SandboxCss, |
| 14 | + SandboxJs, |
| 15 | +} from '../../../util/storybook/sandbox/Sandbox'; |
| 16 | +import { |
| 17 | + componentName, |
| 18 | + componentCss, |
| 19 | + componentHtml, |
| 20 | + componentJs, |
| 21 | + componentTsx, |
| 22 | +} from './sandbox'; |
| 23 | + |
| 24 | +<Meta of={TopBarNavigationStories} /> |
| 25 | + |
| 26 | +# TopBarNavigation |
| 27 | + |
| 28 | +The Top Bar Navigation component is a link to another part of a tool, and also shows the currently navigated page or section. |
| 29 | + |
| 30 | +## When to use |
| 31 | + |
| 32 | +- In a Top Bar component |
| 33 | +- When you have multiple pages or tabs in an app and need a way to navigate between them |
| 34 | + |
| 35 | +## Peer dependencies |
| 36 | + |
| 37 | +- `@emotion/react` |
| 38 | +- `react` |
| 39 | +- `react-dom` |
| 40 | +- `typescript` |
| 41 | +- ToDo: react aria if menu? |
| 42 | + |
| 43 | +See the `peerDependencies` section of `package.json` for compatible versions. |
| 44 | + |
| 45 | +See [custom component build](#custom-component-build) for usage without React/Emotion. |
| 46 | + |
| 47 | +## Example usage |
| 48 | + |
| 49 | +<SandboxReact componentName={componentName} componentTsx={componentTsx} /> |
| 50 | + |
| 51 | +```tsx |
| 52 | +import { TopBarNavigation } from '@guardian/stand/TopBar'; |
| 53 | + |
| 54 | +/* types, if required */ |
| 55 | +import type { |
| 56 | + TopBarNavigationProps, |
| 57 | + TopBarNavigationTheme, |
| 58 | +} from '@guardian/stand/TopBar'; |
| 59 | + |
| 60 | +export const Component = () => ( |
| 61 | + <TopBarNavigation text="Recipe" icon="yakitori" /> |
| 62 | +); |
| 63 | +``` |
| 64 | + |
| 65 | +## Props |
| 66 | + |
| 67 | +| Name | Type | Required | Default | Description | |
| 68 | +| -------------- | ----------------------------------------------------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 69 | +| `text` | `string` | Yes | N/A | Text content to render inside the component. | |
| 70 | +| `size` | `'md'` \| `'sm'` | No | `'md'` | Size of the component - affects text and icon. | |
| 71 | +| `isSelected` | `boolean` | No | `false` | Whether this navigation component represents the currently selected navigation option. | |
| 72 | +| `icon` | `IconProps['symbol']` \| `Exclude<IconProps['children'], string>` | No | N/A | Icon rendered inside the navigation. Accepts a `MaterialSymbol` name or a non-string `ReactNode` (e.g. an SVG element). Size is default. | |
| 73 | +| `menuChildren` | `ReactNode` | No | `false` | Menu sections and items to render in the dropdown menu - only children of type MenuSection and MenuItem will be rendered. `href` and `onPress` will be ignored if this prop is supplied. | |
| 74 | +| `href` | `string` | No | N/A | A URL to link to handle navigation. | |
| 75 | +| `onPress` | `(e: PressEvent) => void` | No | N/A | On Press handler that handles navigation. | |
| 76 | +| `theme` | `TopBarNavigationTheme` | No | N/A | Custom theme overrides. | |
| 77 | +| `cssOverrides` | `SerializedStyles` | No | N/A | Custom CSS styles. | |
| 78 | +| `className` | `string` | No | N/A | Additional class name(s). | |
| 79 | + |
| 80 | +## Stories |
| 81 | + |
| 82 | +### Default |
| 83 | + |
| 84 | +<Story of={Default} /> |
| 85 | + |
| 86 | +### With Icon |
| 87 | + |
| 88 | +<Story of={WithIcon} /> |
| 89 | + |
| 90 | +### With Menu |
| 91 | + |
| 92 | +<Story of={WithMenu} /> |
| 93 | + |
| 94 | +### Selected |
| 95 | + |
| 96 | +<Story of={Selected} /> |
| 97 | + |
| 98 | +### Disabled |
| 99 | + |
| 100 | +<Story of={Disabled} /> |
| 101 | + |
| 102 | +## Customisation |
| 103 | + |
| 104 | +We recommend using the TopBarNavigation component as provided, but it can be customised using the `theme` or `cssOverrides` props as required. |
| 105 | + |
| 106 | +### Custom theme |
| 107 | + |
| 108 | +The `theme` prop allows you to override specific design tokens for the TopBarNavigation component: |
| 109 | + |
| 110 | +<Story of={CustomTheme} /> |
| 111 | + |
| 112 | +```tsx |
| 113 | +import type { TopBarNavigationTheme } from '@guardian/stand/TopBar'; |
| 114 | +import { TopBarNavigation } from '@guardian/stand/TopBar'; |
| 115 | +import { baseColors } from '@guardian/stand'; |
| 116 | + |
| 117 | +const customTheme: Partial<TopBarNavigationTheme> = { |
| 118 | + selected: { |
| 119 | + color: baseColors.blue[200], |
| 120 | + 'border-bottom': `5px solid ${baseColors['cool-purple'][700]}`, |
| 121 | + }, |
| 122 | +}; |
| 123 | + |
| 124 | +const Component = () => ( |
| 125 | + <TopBarNavigation |
| 126 | + theme={customTheme} |
| 127 | + icon="file_upload" |
| 128 | + text="Navigation" |
| 129 | + isSelected={true} |
| 130 | + /> |
| 131 | +); |
| 132 | +``` |
| 133 | + |
| 134 | +### CSS overrides |
| 135 | + |
| 136 | +The `cssOverrides` prop allows you to pass custom CSS to the TopBarNavigation component: |
| 137 | + |
| 138 | +<Story of={CssOverrides} /> |
| 139 | + |
| 140 | +```tsx |
| 141 | +import { TopBarNavigation } from '@guardian/stand/TopBar'; |
| 142 | +import { semanticColors } from '@guardian/stand'; |
| 143 | +import { css } from '@emotion/react'; |
| 144 | + |
| 145 | +const customStyles = css\` |
| 146 | + background-color: ${semanticColors.surface['dark-1']}; |
| 147 | + color: ${semanticColors.text['inverse-default']}; |
| 148 | +\`; |
| 149 | +
|
| 150 | +const Component = () => ( |
| 151 | + <TopBarNavigation |
| 152 | + cssOverrides={customStyles} |
| 153 | + icon="file_upload" |
| 154 | + text="Navigation" |
| 155 | + isSelected={true} |
| 156 | + /> |
| 157 | +); |
| 158 | +``` |
| 159 | + |
| 160 | +## Custom Component Build |
| 161 | + |
| 162 | +If you're not using React/Emotion, you can create a custom TopBarNavigation component using the styles defined in the `TopBarNavigationTheme` type. |
| 163 | + |
| 164 | +**`css`** |
| 165 | + |
| 166 | +You can import the TopBarNavigation styles as CSS from the package: |
| 167 | + |
| 168 | +<SandboxCss |
| 169 | + componentName={componentName} |
| 170 | + componentHtml={componentHtml} |
| 171 | + componentCss={componentCss} |
| 172 | +/> |
| 173 | + |
| 174 | +**TypeScript/JavaScript** |
| 175 | + |
| 176 | +Use the `componentTopBarNavigation` variable and the `ComponentTopBarNavigation` type: |
| 177 | + |
| 178 | +<SandboxJs componentName={componentName} componentJs={componentJs} /> |
0 commit comments