Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Alert)!: Move icon into strong left border and require header #1792

Merged
merged 20 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
81bda2f
Move alert icon into thick left border
VincentSmedinga Dec 15, 2024
bbed107
Require heading for Alert
VincentSmedinga Jan 15, 2025
37ddf52
Arrange heading and close button in a row
VincentSmedinga Jan 15, 2025
7c79857
Remove ‘section’ from markup
VincentSmedinga Jan 15, 2025
7a355e6
Prefer Row component over local class
VincentSmedinga Jan 15, 2025
c7678ea
Make ‘info’ the default severity
VincentSmedinga Jan 15, 2025
ad2727d
Improve examples
VincentSmedinga Jan 16, 2025
13ea6eb
Merge branch 'develop' into feat/DES-1101-update-alert-border-design
VincentSmedinga Jan 20, 2025
eb52dc3
Remove instances of obsolete class
VincentSmedinga Jan 20, 2025
d853137
Remove unnecessary alignment
VincentSmedinga Jan 20, 2025
ad0c4dc
Use box shadow for Alert border
VincentSmedinga Jan 21, 2025
ac8de7c
Rename the column indicating severity
VincentSmedinga Jan 21, 2025
4e0a28f
Copy example text from a design
VincentSmedinga Jan 21, 2025
2aeba8a
Remove example with list
VincentSmedinga Jan 21, 2025
a9607d0
Improve wording and structure of guidelines
VincentSmedinga Jan 21, 2025
8a94c59
Clarify guideline
VincentSmedinga Jan 22, 2025
9158585
Add missing Alert heading to form page example
VincentSmedinga Jan 22, 2025
89fdb3a
Add ‘information’ severity to Controls
VincentSmedinga Jan 22, 2025
20b76de
Remove incorrect appearance in forced colors mode
VincentSmedinga Jan 22, 2025
eb02f70
Merge branch 'develop' into feat/DES-1101-update-alert-border-design
VincentSmedinga Jan 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/css/src/components/alert/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ An Alert informs the user of a significant or time-sensitive message without int

There are four types of notifications:

- **Information** (blue) to bring attention to a message.
This is the default.
- **Success** (green) to reassure that a process is complete.
- **Warning** (orange) when action is needed to prevent damage.
- **Error** (red) indicates an error has occurred.
- **Confirmation** (green) to reassure that a process is complete.
- **Notification** (blue) to bring attention to a message.

## Guidelines

- Place an orange Alert directly below the Header for important and urgent information.
- Place a warning Alert directly below the Header for important and urgent information.
Examples: system outage or changes in the opening hours of a City Office.
- Ensure sufficient white space around the Alert.
- Use enough white space around the Alert.
The grid’s white space is a good reference – place the Alert in its own cell.
- By default, the Alert cannot be closed.
This functionality can be added optionally.
- Optionally, the heading can be omitted.
34 changes: 27 additions & 7 deletions packages/css/src/components/alert/alert.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,57 @@
*/

.ams-alert {
align-items: flex-start;
background-color: var(--ams-alert-background-color);
border-color: var(--ams-alert-border-color);
border-style: var(--ams-alert-border-style);
border-width: var(--ams-alert-border-width);
alimpens marked this conversation as resolved.
Show resolved Hide resolved
display: flex;
flex-direction: row;
gap: var(--ams-alert-gap);
justify-content: space-between;
padding-block: var(--ams-alert-padding-block);
padding-inline: var(--ams-alert-padding-inline);
}

.ams-alert__severity {
alimpens marked this conversation as resolved.
Show resolved Hide resolved
background-color: var(--ams-alert-icon-background-color);
border-inline-end-color: var(--ams-alert-border-color);
border-inline-end-style: solid;
border-inline-end-width: var(--ams-alert-border-width);
alimpens marked this conversation as resolved.
Show resolved Hide resolved
flex: none;
alimpens marked this conversation as resolved.
Show resolved Hide resolved
padding-block: var(--ams-alert-severity-padding-block);
padding-inline: var(--ams-alert-severity-padding-inline);
}

.ams-alert__content {
display: flex;
flex: auto;
alimpens marked this conversation as resolved.
Show resolved Hide resolved
flex-direction: column;
gap: var(--ams-alert-content-gap);
padding-block: var(--ams-alert-content-padding-block);
padding-inline: var(--ams-alert-content-padding-inline);
}

.ams-alert--error {
border-color: var(--ams-alert-error-border-color);
}

.ams-alert--info {
border-color: var(--ams-alert-info-border-color);
> .ams-alert__severity {
background-color: var(--ams-alert-error-icon-background-color);
border-inline-end-color: var(--ams-alert-error-border-color);
}
}

.ams-alert--success {
border-color: var(--ams-alert-success-border-color);

> .ams-alert__severity {
background-color: var(--ams-alert-success-icon-background-color);
border-inline-end-color: var(--ams-alert-success-border-color);
}
}

.ams-alert--warning {
border-color: var(--ams-alert-warning-border-color);

> .ams-alert__severity {
background-color: var(--ams-alert-warning-icon-background-color);
border-inline-end-color: var(--ams-alert-warning-border-color);
}
}
16 changes: 8 additions & 8 deletions packages/react/src/Alert/Alert.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import '@testing-library/jest-dom'

describe('Alert', () => {
it('renders', () => {
const { container } = render(<Alert />)
const { container } = render(<Alert heading="Let op!" />)

const component = container.querySelector(':only-child')
const icon = component?.querySelector('.ams-alert__icon')
const icon = component?.querySelector('.ams-alert__severity > .ams-icon')

expect(component).toBeInTheDocument()
expect(component).toBeVisible()
Expand All @@ -17,15 +17,15 @@ describe('Alert', () => {
})

it('renders a design system BEM class name', () => {
const { container } = render(<Alert />)
const { container } = render(<Alert heading="Let op!" />)

const component = container.querySelector(':only-child')

expect(component).toHaveClass('ams-alert')
})

it('renders an additional class name', () => {
const { container } = render(<Alert className="extra" />)
const { container } = render(<Alert className="extra" heading="Let op!" />)

const component = container.querySelector(':only-child')

Expand All @@ -35,7 +35,7 @@ describe('Alert', () => {
it('supports ForwardRef in React', () => {
const ref = createRef<HTMLDivElement>()

const { container } = render(<Alert ref={ref} />)
const { container } = render(<Alert heading="Let op!" ref={ref} />)

const component = container.querySelector(':only-child')

Expand All @@ -53,7 +53,7 @@ describe('Alert', () => {
})

it('renders the close button', () => {
const { container } = render(<Alert closeable={true} />)
const { container } = render(<Alert closeable heading="Let op!" />)

const component = container.querySelector(':only-child')
const closeButton = component?.querySelector('.ams-icon-button')
Expand All @@ -63,7 +63,7 @@ describe('Alert', () => {
})

it('renders the close button with a label', () => {
render(<Alert closeable={true} closeButtonLabel="Close" />)
render(<Alert closeable closeButtonLabel="Close" heading="Let op!" />)

const closeButton = screen.getByRole('button', { name: 'Close' })

Expand All @@ -72,7 +72,7 @@ describe('Alert', () => {

it('fires the onClose event when the close button is clicked', () => {
const onClose = jest.fn()
const { container } = render(<Alert closeable={true} onClose={onClose} />)
const { container } = render(<Alert closeable onClose={onClose} heading="Let op!" />)

const component = container.querySelector(':only-child')
const closeButton = component?.querySelector('.ams-icon-button')
Expand Down
31 changes: 16 additions & 15 deletions packages/react/src/Alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ import { Heading } from '../Heading'
import type { HeadingProps } from '../Heading'
import { Icon } from '../Icon'
import { IconButton } from '../IconButton'
import { Row } from '../Row'

type Severity = 'error' | 'success' | 'warning'

export type AlertProps = {
/** Whether the user can dismiss the Alert. Adds a button to its top right. */
closeable?: boolean
/** The label for the button that dismisses the Alert. */
closeButtonLabel?: string
/** The text for the Heading. */
heading?: string
heading: string
/**
* The hierarchical level of the Heading within the document.
* Note: this intentionally does not change the font size.
Expand All @@ -27,12 +30,11 @@ export type AlertProps = {
/** A function to run when dismissing. */
onClose?: () => void
/** The significance of the message conveyed. */
severity?: 'error' | 'info' | 'success' | 'warning'
severity?: Severity
} & PropsWithChildren<HTMLAttributes<HTMLDivElement>>

const iconSvgBySeverity = {
const iconSvgBySeverity: Record<Severity, Function> = {
error: AlertIcon,
info: InfoIcon,
success: CheckmarkIcon,
warning: AlertIcon,
}
Expand All @@ -47,29 +49,28 @@ export const Alert = forwardRef(
heading,
headingLevel = 2,
onClose,
severity = 'warning',
severity,
...restProps
}: AlertProps,
ref: ForwardedRef<HTMLDivElement>,
) => {
const alertSize = heading ? 'level-4' : 'level-5'
const Tag = heading ? 'section' : 'div'
const SeverityIcon = severity ? iconSvgBySeverity[severity] : InfoIcon

return (
<Tag {...restProps} ref={ref} className={clsx('ams-alert', severity && `ams-alert--${severity}`, className)}>
<div className="ams-alert__icon">
<Icon size={alertSize} svg={iconSvgBySeverity[severity]} />
<section {...restProps} ref={ref} className={clsx('ams-alert', severity && `ams-alert--${severity}`, className)}>
<div className="ams-alert__section ams-alert__severity">
alimpens marked this conversation as resolved.
Show resolved Hide resolved
<Icon inverseColor size="level-4" svg={SeverityIcon} />
</div>
<div className="ams-alert__content">
{heading && (
<div className="ams-alert__section ams-alert__content">
<Row align="between" alignVertical="start">
<Heading level={headingLevel} size="level-4">
{heading}
</Heading>
)}
{closeable && <IconButton label={closeButtonLabel} onClick={onClose} size="level-4" />}
</Row>
{children}
</div>
{closeable && <IconButton label={closeButtonLabel} size={alertSize} onClick={onClose} />}
</Tag>
</section>
)
},
)
Expand Down
39 changes: 26 additions & 13 deletions proprietary/tokens/src/components/ams/alert.tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,38 @@
"ams": {
"alert": {
"background-color": { "value": "{ams.color.primary-white}" },
"border-width": { "value": "{ams.border.width.xl}" },
"border-color": { "value": "{ams.color.blue}" },
"border-style": { "value": "solid" },
"gap": { "value": "{ams.space.sm}" },
"padding-block": { "value": "{ams.space.md}" },
"padding-inline": { "value": "{ams.space.lg}" },
"error": {
"border-color": { "value": "{ams.color.primary-red}" }
"border-width": { "value": "{ams.border.width.xl}" },
"severity": {
"padding-block": { "value": "{ams.space.md}" },
"padding-inline": { "value": "{ams.space.xs}" }
},
"content": {
"gap": { "value": "{ams.space.sm}" },
"padding-block": { "value": "{ams.space.md}" },
"padding-inline": { "value": "{ams.space.md}" }
},
"info": {
"border-color": { "value": "{ams.color.blue}" }
"icon": {
"background-color": { "value": "{ams.color.blue}" }
alimpens marked this conversation as resolved.
Show resolved Hide resolved
},
"error": {
"border-color": { "value": "{ams.color.primary-red}" },
"icon": {
"background-color": { "value": "{ams.color.primary-red}" }
}
},
"success": {
"border-color": { "value": "{ams.color.dark-green}" }
"border-color": { "value": "{ams.color.dark-green}" },
"icon": {
"background-color": { "value": "{ams.color.dark-green}" }
}
},
"warning": {
"border-color": { "value": "{ams.color.orange}" }
},
"content": {
"gap": { "value": "{ams.space.sm}" }
"border-color": { "value": "{ams.color.orange}" },
"icon": {
"background-color": { "value": "{ams.color.orange}" }
}
}
}
}
Expand Down
8 changes: 0 additions & 8 deletions storybook/src/components/Alert/Alert.docs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import README from "../../../../packages/css/src/components/alert/README.md?raw"
### Warning

Display a warning when user action is required.
This is the default severity.

<Canvas of={AlertStories.Warning} />

Expand Down Expand Up @@ -51,10 +50,3 @@ Include an inline link in the text to guide the user.
For clarification, formatted text can be included in the alert.

<Canvas of={AlertStories.WithList} />

### Without heading

Sometimes, a heading is unnecessary.
The icon automatically becomes slightly smaller.

<Canvas of={AlertStories.WithoutHeading} />
23 changes: 7 additions & 16 deletions storybook/src/components/Alert/Alert.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ export const Default: Story = {
args: {
alimpens marked this conversation as resolved.
Show resolved Hide resolved
children: (
<Paragraph>
Tijdens Koningsdag zijn alle Stadsloketten gesloten. Ook 14 020 en alle andere telefoonnummers van de gemeente
zijn niet bereikbaar.
Tijdens de hijswerkzaamheden geldt er een korte verkeersstop. We zetten verkeersregelaars in, volg hun
aanwijzingen op. De verkeersstop duurt ongeveer 10 minuten.
</Paragraph>
),
heading: 'Tijdelijk geen verkeer mogelijk',
},
}

export const Warning: Story = {
args: {
children: <Paragraph>U bent vergeten verplichte velden in te vullen.</Paragraph>,
children: <Paragraph>Sommige verplichte velden zijn nog niet ingevuld.</Paragraph>,
heading: 'Vul de gegevens aan',
severity: 'warning',
},
}

Expand Down Expand Up @@ -69,7 +71,6 @@ export const Info: Story = {
</Paragraph>
),
closeable: true,
severity: 'info',
},
}

Expand All @@ -83,6 +84,7 @@ export const WithList: Story = {
</UnorderedList>,
],
heading: 'Vul de gegevens aan',
severity: 'warning',
},
}

Expand All @@ -97,17 +99,6 @@ export const WithInlineLink: Story = {
gesloten. Ook 14 020 en alle andere telefoonnummers van de gemeente zijn niet bereikbaar.
</Paragraph>
),
severity: 'info',
},
}

export const WithoutHeading: Story = {
args: {
children: (
<Paragraph>
De geschatte wachttijd in de adreszoeker klopt momenteel niet altijd. We werken aan een oplossing.
</Paragraph>
),
heading: undefined,
severity: 'warning',
},
}
Loading