Skip to content
Merged
19 changes: 15 additions & 4 deletions apps/www/app/_components/css-attributes/css-attributes.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Table } from '@digdir/designsystemet-react';
import { Paragraph, Table } from '@digdir/designsystemet-react';
import cl from 'clsx';
import { forwardRef } from 'react';
import { useTranslation } from 'react-i18next';

type CssAttributesProps = {
vars: {
Expand All @@ -10,7 +11,12 @@ type CssAttributesProps = {

export const CssAttributes = forwardRef<HTMLTableElement, CssAttributesProps>(
function CssAttributes({ vars, className, ...rest }, ref) {
if (Object.keys(vars).length === 0) return null;
const { t } = useTranslation();

if (Object.keys(vars).length === 0)
return (
<Paragraph>{t('components.no-relevant-data-attributes')}</Paragraph>
);
return (
<Table
className={cl('component-table', className)}
Expand All @@ -23,10 +29,15 @@ export const CssAttributes = forwardRef<HTMLTableElement, CssAttributesProps>(
{...rest}
ref={ref}
>
<caption>{t('components.data-attributes')}</caption>
<Table.Head>
<Table.Row>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Value(s)</Table.HeaderCell>
<Table.HeaderCell>
{t('components.css-variables.name')}
</Table.HeaderCell>
<Table.HeaderCell>
{t('components.css-variables.value')}
</Table.HeaderCell>
</Table.Row>
</Table.Head>
<Table.Body>
Expand Down
12 changes: 10 additions & 2 deletions apps/www/app/_components/css-variables/css-variables.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Table } from '@digdir/designsystemet-react';
import cl from 'clsx';
import { forwardRef } from 'react';
import { useTranslation } from 'react-i18next';

type CssVariablesProps = {
vars: {
Expand All @@ -10,6 +11,8 @@ type CssVariablesProps = {

export const CssVariables = forwardRef<HTMLTableElement, CssVariablesProps>(
function CssVariables({ vars, className, ...rest }, ref) {
const { t } = useTranslation();

return (
<Table
zebra
Expand All @@ -22,10 +25,15 @@ export const CssVariables = forwardRef<HTMLTableElement, CssVariablesProps>(
{...rest}
ref={ref}
>
<caption>{t('components.css-variables.caption')}</caption>
<Table.Head>
<Table.Row>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>Value</Table.HeaderCell>
<Table.HeaderCell>
{t('components.css-variables.name')}
</Table.HeaderCell>
<Table.HeaderCell>
{t('components.css-variables.value')}
</Table.HeaderCell>
</Table.Row>
</Table.Head>
<Table.Body>
Expand Down
53 changes: 52 additions & 1 deletion apps/www/app/content/components/alert/alert.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Alert, Heading, Link, Paragraph } from '@digdir/designsystemet-react';
import {
Alert,
Button,
Heading,
Link,
Paragraph,
} from '@digdir/designsystemet-react';
import { useState } from 'react';

export const Preview = () => {
return <Alert>En beskjed det er viktig at brukeren ser</Alert>;
Expand Down Expand Up @@ -118,3 +125,47 @@ export const MedLenke = () => (
</Paragraph>
</Alert>
);

export const CorrectLiveRegionReact = () => {
const [showAlert, setShowAlert] = useState(false);
return (
<>
<Button
data-size='sm'
variant='secondary'
onClick={() => setShowAlert((value) => !value)}
>
{showAlert ? 'Skjul varsel' : 'Handling som fører til varsel'}
</Button>
{/* Korrekt bruk: role="alert" ligger på elementet der varselet dukker opp */}
<div role='alert'>
{showAlert && (
<Alert data-color='warning'>
<Heading
level={2}
data-size='xs'
style={{
marginBottom: 'var(--ds-size-2)',
}}
>
Vi klarer ikke lagre skjemaet
</Heading>
<Paragraph>
Vi har mistet forbindelsen med serveren og får ikke lagret
skjemaet. Vent litt og prøv en gang til.
</Paragraph>
</Alert>
)}
</div>
</>
);
};

export const Variants = () => (
<>
<Alert data-color='info'>Dette er en info alert</Alert>
<Alert data-color='success'>Dette er en success alert</Alert>
<Alert data-color='warning'>Dette er en warning alert</Alert>
<Alert data-color='danger'>Dette er en danger alert</Alert>
</>
);
66 changes: 61 additions & 5 deletions apps/www/app/content/components/alert/en/code.mdx
Original file line number Diff line number Diff line change
@@ -1,17 +1,73 @@
<Story story="Preview" />

## Usage

## Use

```tsx
import { Button } from '@digdir/designsystemet-react';
import { Alert } from '@digdir/designsystemet-react';

<Button>Click me!</Button>;
<Alert>You are using the Alert component!</Alert>;
```

## Code Examples
### Props
<ReactComponentDocs />

## Code examples

### Variants
### Change alert

In code, you change the type of alert by changing `data-color`.
The icon is controlled via CSS.

<Story story="Variants" />

### Alert in live region

If you want the alert to be read dynamically, you must place `Alert` in a live region.
The region **should be around** the `Alert` component, not on it.

Out of the box, `Alert` is presented to screen reader users as regular static content. For alerts that occur dynamically, you can define a *live region* for screen readers, but be aware of the behavior this will cause.
You can read more about this in the [MDN documentation on ARIA live regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions).

Note in particular that the live region — that is, the element with the attribute `role="alert"`, `role="status"`, or `aria-live` with the value `"assertive"` or `"polite"` — must exist on the page **before** the alert that is to be spoken.

For dynamic notifications, it is most appropriate to use `role="alert"` for critical notifications or `role="status"` for less critical ones, as described in the [pattern for system notifications](https://designsystemet.no/no/patterns/systemnotifications). See also [alert role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alert_role) and [status role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/status_role) at MDN.

**Do not** combine `role="alert"` and `aria-live`, as [this causes the alert to be spoken twice in VoiceOver (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions#:~:text=adding%20both%20aria%2Dlive%20and%20role=%22alert%22%20causes%20double%20speaking%20issues%20in%20VoiceOver%20on%20iOS).

You **should** combine `role="status"` and `aria-live="polite"` [to maximize compatibility (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions#roles_with_implicit_live_region_attributes).

<Story story="CorrectLiveRegionReact" />

<Card data-color="info">
For status messages, implemented using markup language, the following applies:

**The result of an action shall be encoded with one of the following:**

- role="status"
- aria-live="polite"

**Waiting state shall be encoded with one of the following:**

- role="status"
- aria-live="polite"

**Error shall be encoded with one of the following:**

- role="alert"
- aria-live="polite"
- aria-live="assertive"

**The progress of a process shall be encoded with one of the following:**

- role="progressbar"
- the `<progress>` element
- role="log"
- role="status" and aria-atomic="false"
- aria-live="polite" and aria-atomic="false"

Source: [4.1.3 Status Messages (Level AA) (uutilsynet.no)](https://www.uutilsynet.no/wcag-standarden/413-statusbeskjeder-niva-aa/152)
</Card>

## CSS variables
<CssVariables />
82 changes: 73 additions & 9 deletions apps/www/app/content/components/alert/en/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,83 @@ Buttons let users perform actions.

<Story story="Preview" />

## Usage
## Examples

```tsx
import { Button } from '@digdir/designsystemet-react';
`Alert` can be used for four different messages: Information, success, warnings and error messages.

<Button>Click me!</Button>;
```
### Information

## Code Examples
Use `info` when you want to provide the user with neutral and useful information.

### Variants
<Story story="VariantInfo" />

Use `primary`, `secondary` or `tertiary` to weight the button correctly.
### Success

<Story story="Variants" />
Use `success` when you want to confirm that the user has completed a task, that the action was successful.

<Story story="VariantSuccess" />

### Warning

Use `warning` when you want the user to take a specific action or to warn them about something important.

<Story story="VariantWarning" />

### Error message

Use `danger` to inform about something that is critical or that prevents the user from moving forward.

<Story story="VariantDanger" />

### With and without heading

If the message is longer than a sentence, it can be useful to use a heading to highlight the most important thing. This can be done using the [Heading](/no/components/heading/overview) components. Remember to choose the correct heading level based on the space the alert has in the content structure of the page.

<Story story="WithHeading" />

If the title and description repeat the same thing, it is better to use a simple sentence without a heading.

<Story story="WithOnlyHeading" />

### With link

You can have a link in the `Alert` if it helps the user solve the task. But be aware that a link takes the user out of the service, so use links only when absolutely necessary, for example if you want the user to open a form or perform an important task.

<Story story="WithLink" />

## Guidelines
`Alert` is used to display important messages that require attention, but not necessarily action. It can be used to inform the user about the status, changes, or problems in a solution. The message is displayed clearly and visually distinguished from the rest of the content.

Use the component with caution. Users can confuse alerts with advertising, and thus ignore them. If we use alerts too often, we can exacerbate this problem.

Make sure that `Alert` has the same look and feel across all services and products. This component should be recognizable everywhere, so we should not adjust it.

**Suitable for**
- provide short and informative time-limited notifications
- inform about errors that only affect one part of the system or a minor function
- inform about connection problems or API errors that are likely to be resolved by reloading the page

**Not suitable for**
- validate individual form elements, instead use the component's own error message (See [`ValidationMessage`](/no/components/validation-message/overview))
- summarize multiple error messages in a form, instead use [`ErrorSummary`](/docs/komponenter-errorsummary--docs)
- display errors that prevent all further use of the service, instead use an error page
- display static information that should be displayed all the time, instead use [`Card`](/docs/komponenter-card--docs)

## Text

It is not always easy to understand the difference between the notifications, even though they have different icons and colors. Therefore, it is important that the text we write in the notification is clear and easy to understand.

If there is something users need to or can do to get through their task, the text should convey that. When the message is longer than a sentence, it may be a good idea to include a headline that highlights the most important points.

Here is a list of the types of information that a notification should contain:

- Tell them what happened
- Example: "Couldn't connect to account."
- Tell them why it happened
- Example: "We were unable to connect to your account due to technical issues on our end."
- Reassure the user
- Example: "Your changes have been saved."
- Give them a way out of the problem
- Example: "If this problem occurs again, contact customer service."
- Help them fix the problem themselves
- Example: "Please try again."
48 changes: 48 additions & 0 deletions apps/www/app/content/components/alert/no/accessibility.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,49 @@
## Tilgjengelighet

### Alert i live region

Dersom du vil at varselet skal bli lest opp dynamisk, må du legge `Alert` i en live region.
Regionen **skal være rundt** `Alert`-komponenten, ikke på den.

Ut av boksen blir `Alert` presentert for skjermleserbrukere som vanlig statisk innhold. For varsler som oppstår dynamisk kan du selv definere en *live region* for skjermlesere, men vær opperksom på hvilken oppførsel dette medfører.
Du kan lese mer om dette i [MDN sin dokumentasjon om ARIA live regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions).

Legg spesielt merke til at live-regionen — altså elementet med attributt `role="alert"`, `role="status"` eller `aria-live` med verdi `"assertive"` eller `"polite"` — må eksistere på siden **før** varselet som skal leses opp.

For dynamiske varsler er det mest aktuelt å bruke `role="alert"` for kritiske varsel eller `role="status"` for mindre kritiske vasel, som beskrevet i [mønsteret for systemvarsler](https://designsystemet.no/no/patterns/systemnotifications). Se også [alert role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alert_role) og [status role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/status_role) hos MDN.

**Ikke** kombiner `role="alert"` og `aria-live`, siden [dette fører at varselet leses opp dobbelt i VoiceOver (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions#:~:text=adding%20both%20aria%2Dlive%20and%20role=%22alert%22%20causes%20double%20speaking%20issues%20in%20VoiceOver%20on%20iOS).

Du **bør** kombinere `role="status"` og `aria-live="polite"` [for å maksimere kompatibilitet (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions#roles_with_implicit_live_region_attributes).

<Story story="CorrectLiveRegionReact" />

<Card data-color="info">
For statusbeskjeder, som implementeres ved hjelp av oppmerkingsspråk, gjelder følgende:

**Resultatet av en handling skal kodes med én av følgende:**

- role="status"
- aria-live="polite"

**Ventetilstand skal kodes med én av følgende:**

- role="status"
- aria-live="polite"

**Feil skal kodes med én av følgende:**

- role="alert"
- aria-live="polite"
- aria-live="assertive"

**Fremdriften i en prosess skal kodes med én av følgende:**

- role="progressbar"
- elementet `<progress>`
- role="log"
- role="status" og aria-atomic="false"
- aria-live="polite" og aria-atomic="false"

Kilde: [4.1.3 Statusbeskjeder (Nivå AA) (uutilsynet.no)](https://www.uutilsynet.no/wcag-standarden/413-statusbeskjeder-niva-aa/152)
</Card>
Loading
Loading