Skip to content

Commit e4737ee

Browse files
authored
Add AlertBanner component (#68)
## What does this change? Adds the `AlertBanner` component. [Figma](https://www.figma.com/design/gmHnKr3tOzvnYp1FZeIl4t/Stand--Editorial-tool-Design-System--WIP%F0%9F%9A%A7-?node-id=32-8137&m=dev) # AlertBanner A full-width banner used to communicate high-priority status messages at page or section level. It supports four levels (`information`, `success`, `warning`, `error`), optional icon display, custom icons, and an optional dismiss action. ## When to use - To show important status feedback that should be visible across the full container width - For success, warning, error, or informational messages tied to a page or workflow - When a message may need optional dismissal via a close button ## Peer dependencies - `@emotion/react` - `react` - `react-dom` - `typescript` See the `peerDependencies` section of `package.json` for compatible versions. See [custom component build](#custom-component-build) for usage without React/Emotion. ## Example usage <SandboxReact componentName={componentName} componentTsx={componentTsx} /> ```tsx import { AlertBanner } from '@guardian/stand/alert-banner'; /* types, if required */ import type { AlertBannerProps, AlertBannerTheme, } from '@guardian/stand/alert-banner'; <AlertBanner level="information"> You are working in the CODE Environment </AlertBanner>; <AlertBanner level="warning" showIcon> Your session will expire in 2 minutes. </AlertBanner>; <AlertBanner level="error" closeButtonProps={{ onPress: () => console.log('dismissed') }} > Unable to save changes. Try again. </AlertBanner>; ``` ## Props | Name | Type | Required | Default | Description | | ------------------ | ---------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `level` | `'error' \| 'success' \| 'information' \| 'warning'` | Yes | N/A | Severity level of the banner. Controls the background treatment and the default icon choice when `showIcon` is enabled. | | `children` | `React.ReactNode` | No | N/A | Content rendered inside the banner. | | `showIcon` | `boolean` | No | `false` | When `true`, renders an icon before the message content. Uses a level-based default icon unless overridden by `icon`. | | `icon` | `IconProps['symbol'] \| SVGElement` | No | N/A | Optional custom icon. Accepts a Material Symbols name (`string`) or non-string icon element (for example an inline SVG). | | `closeButtonProps` | `Partial<IconButtonProps>` | No | N/A | Optional props for the close button. If provided, a close icon button is rendered and the props are forwarded to `IconButton` (with defaults for `variant`, `size`, `symbol`, and `ariaLabel`). | | `theme` | `Partial<AlertBannerTheme>` | No | N/A | Custom theme token overrides merged over the component defaults. | | `cssOverrides` | `SerializedStyles \| SerializedStyles[]` | No | N/A | Additional Emotion CSS styles applied to the root element. | | `className` | `string` | No | N/A | Additional class name(s) for the root element. | ## Customisation We recommend using the AlertBanner component as provided, but it can be customised using the `theme` or `cssOverrides` props as required. ### Custom theme The `theme` prop allows you to override specific design tokens for the AlertBanner component: ```tsx import { baseColors } from '@guardian/stand'; import type { AlertBannerTheme } from '@guardian/stand/alert-banner'; import { AlertBanner } from '@guardian/stand/alert-banner'; const customTheme: Partial<AlertBannerTheme> = { error: { 'background-color': baseColors.red[100], }, shared: { content: { color: baseColors.red[700], }, }, }; const Component = () => ( <AlertBanner level="error" theme={customTheme}> Unable to save changes. </AlertBanner> ); ``` ### CSS overrides The `cssOverrides` prop allows you to pass custom CSS to the AlertBanner component: ```tsx import { AlertBanner } from '@guardian/stand/alert-banner'; import { css } from '@emotion/react'; const customStyles = css\` box-shadow: inset 0 -2px 0 currentColor; text-transform: uppercase; letter-spacing: 0.04em; \`; const Component = () => ( <AlertBanner level="success" cssOverrides={customStyles}> Changes published successfully. </AlertBanner> ); ```
2 parents c7ee1d1 + 45215c1 commit e4737ee

15 files changed

Lines changed: 970 additions & 1 deletion

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@guardian/stand': patch
3+
---
4+
5+
Add AlertBanner component

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@
104104
"import": "./dist/text-area.js",
105105
"require": "./dist/text-area.cjs"
106106
},
107+
"./alert-banner": {
108+
"types": "./dist/types/alert-banner.d.ts",
109+
"import": "./dist/alert-banner.js",
110+
"require": "./dist/alert-banner.cjs"
111+
},
107112
"./byline": {
108113
"types": "./dist/types/byline.d.ts",
109114
"import": "./dist/byline.js",
@@ -155,7 +160,8 @@
155160
"./component/textInput.css": "./dist/styleD/build/css/component/textInput.css",
156161
"./component/radioGroup.css": "./dist/styleD/build/css/component/radioGroup.css",
157162
"./component/checkbox.css": "./dist/styleD/build/css/component/checkbox.css",
158-
"./component/textArea.css": "./dist/styleD/build/css/component/textArea.css"
163+
"./component/textArea.css": "./dist/styleD/build/css/component/textArea.css",
164+
"./component/alertBanner.css": "./dist/styleD/build/css/component/alertBanner.css"
159165
},
160166
"//typesVersions": "Provides backward compatibility for TypeScript moduleResolution: node - maps subpath imports to correct type definition files. When adding new components with their own entry points, ensure to add them here.",
161167
"typesVersions": {
@@ -228,6 +234,9 @@
228234
],
229235
"text-area": [
230236
"./dist/types/text-area.d.ts"
237+
],
238+
"alert-banner": [
239+
"./dist/types/alert-banner.d.ts"
231240
]
232241
}
233242
},

rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const input = {
3939
typography: 'src/typography.ts',
4040
icon: 'src/icon.ts',
4141
favicon: 'src/favicon.ts',
42+
'alert-banner': 'src/alert-banner.ts',
4243
'radio-group': 'src/radio-group.ts',
4344
checkbox: 'src/checkbox.ts',
4445
'text-area': 'src/text-area.ts',

src/alert-banner.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* AlertBanner component entry point
3+
*
4+
* Peer dependencies required to use these components:
5+
* - `@emotion/react`
6+
* - `react`
7+
* - `react-dom`
8+
* - `typescript`
9+
*
10+
* See the `peerDependencies` section of package.json for compatible versions.
11+
*
12+
* If you only need the built CSS (./component/alertBanner.css),
13+
* you don't need to install these.
14+
*/
15+
export { AlertBanner } from './components/alert-banner/AlertBanner';
16+
export type { AlertBannerProps } from './components/alert-banner/types';
17+
export type { AlertBannerTheme } from './components/alert-banner/styles';
18+
export { componentAlertBanner } from './styleD/build/typescript/component/alertBanner';
19+
export type { ComponentAlertBanner } from './styleD/build/typescript/component/alertBanner';
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import { Meta, Story } from '@storybook/addon-docs/blocks';
2+
import AlertBannerStories, {
3+
Information,
4+
Error,
5+
Success,
6+
Warning,
7+
InformationWithIconAndCloseButton,
8+
CustomTheme,
9+
CssOverrides,
10+
} from './AlertBanner.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={AlertBannerStories} />
25+
26+
# AlertBanner
27+
28+
A full-width banner used to communicate high-priority status messages at page or section level. It supports four levels (`information`, `success`, `warning`, `error`), optional icon display, custom icons, and an optional dismiss action.
29+
30+
## When to use
31+
32+
- To show important status feedback that should be visible across the full container width
33+
- For success, warning, error, or informational messages tied to a page or workflow
34+
- When a message may need optional dismissal via a close button
35+
36+
## Peer dependencies
37+
38+
- `@emotion/react`
39+
- `react`
40+
- `react-dom`
41+
- `typescript`
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
50+
componentName={componentName}
51+
componentTsx={componentTsx}
52+
flowColumn
53+
/>
54+
55+
```tsx
56+
import { AlertBanner } from '@guardian/stand/alert-banner';
57+
58+
/* types, if required */
59+
import type {
60+
AlertBannerProps,
61+
AlertBannerTheme,
62+
} from '@guardian/stand/alert-banner';
63+
64+
<AlertBanner level="information">
65+
You are working in the CODE Environment
66+
</AlertBanner>;
67+
68+
<AlertBanner level="warning" showIcon>
69+
Your session will expire in 2 minutes.
70+
</AlertBanner>;
71+
72+
<AlertBanner
73+
level="error"
74+
closeButtonProps={{ onPress: () => console.log('dismissed') }}
75+
>
76+
Unable to save changes. Try again.
77+
</AlertBanner>;
78+
```
79+
80+
## Props
81+
82+
| Name | Type | Required | Default | Description |
83+
| ------------------ | ---------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
84+
| `level` | `'error' \| 'success' \| 'information' \| 'warning'` | Yes | N/A | Severity level of the banner. Controls the background treatment and the default icon choice when `showIcon` is enabled. |
85+
| `children` | `React.ReactNode` | No | N/A | Content rendered inside the banner. |
86+
| `showIcon` | `boolean` | No | `false` | When `true`, renders an icon before the message content. Uses a level-based default icon unless overridden by `icon`. |
87+
| `icon` | `IconProps['symbol'] \| SVGElement` | No | N/A | Optional custom icon. Accepts a Material Symbols name (`string`) or non-string icon element (for example an inline SVG). |
88+
| `closeButtonProps` | `Partial<IconButtonProps>` | No | N/A | Optional props for the close button. If provided, a close icon button is rendered and the props are forwarded to `IconButton` (with defaults for `variant`, `size`, `symbol`, and `ariaLabel`). |
89+
| `theme` | `Partial<AlertBannerTheme>` | No | N/A | Custom theme token overrides merged over the component defaults. |
90+
| `cssOverrides` | `SerializedStyles \| SerializedStyles[]` | No | N/A | Additional Emotion CSS styles applied to the root element. |
91+
| `className` | `string` | No | N/A | Additional class name(s) for the root element. |
92+
93+
## Stories
94+
95+
### Information
96+
97+
<Story of={Information} />
98+
99+
### Success
100+
101+
<Story of={Success} />
102+
103+
### Warning
104+
105+
<Story of={Warning} />
106+
107+
### Error
108+
109+
<Story of={Error} />
110+
111+
### Information with Icon and Close Button
112+
113+
<Story of={InformationWithIconAndCloseButton} />
114+
115+
## Customisation
116+
117+
We recommend using the AlertBanner component as provided, but it can be customised using the `theme` or `cssOverrides` props as required.
118+
119+
### Custom theme
120+
121+
The `theme` prop allows you to override specific design tokens for the AlertBanner component:
122+
123+
<Story of={CustomTheme} />
124+
125+
```tsx
126+
import { baseColors } from '@guardian/stand';
127+
import type { AlertBannerTheme } from '@guardian/stand/alert-banner';
128+
import { AlertBanner } from '@guardian/stand/alert-banner';
129+
130+
const customTheme: Partial<AlertBannerTheme> = {
131+
error: {
132+
'background-color': baseColors.red[100],
133+
},
134+
shared: {
135+
content: {
136+
color: baseColors.red[700],
137+
},
138+
},
139+
};
140+
141+
const Component = () => (
142+
<AlertBanner level="error" theme={customTheme}>
143+
Unable to save changes.
144+
</AlertBanner>
145+
);
146+
```
147+
148+
### CSS overrides
149+
150+
The `cssOverrides` prop allows you to pass custom CSS to the AlertBanner component:
151+
152+
<Story of={CssOverrides} />
153+
154+
```tsx
155+
import { AlertBanner } from '@guardian/stand/alert-banner';
156+
import { css } from '@emotion/react';
157+
158+
const customStyles = css\`
159+
box-shadow: inset 0 -2px 0 currentColor;
160+
text-transform: uppercase;
161+
letter-spacing: 0.04em;
162+
\`;
163+
164+
const Component = () => (
165+
<AlertBanner level="success" cssOverrides={customStyles}>
166+
Changes published successfully.
167+
</AlertBanner>
168+
);
169+
```
170+
171+
## Custom Component Build
172+
173+
If you're not using React/Emotion, you can create a custom AlertBanner component using the styles defined in the `AlertBannerTheme` type.
174+
175+
**`css`**
176+
177+
You can import the AlertBanner styles as CSS from the package:
178+
179+
<SandboxCss
180+
componentName={componentName}
181+
componentHtml={componentHtml}
182+
componentCss={componentCss}
183+
/>
184+
185+
**TypeScript/JavaScript**
186+
187+
Use the `componentAlertBanner` variable and the `ComponentAlertBanner` type:
188+
189+
<SandboxJs componentName={componentName} componentJs={componentJs} />

0 commit comments

Comments
 (0)