Skip to content

Commit

Permalink
feat(AriaLive): add new component
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Jan 16, 2024
1 parent 58c77cd commit 048f5e6
Show file tree
Hide file tree
Showing 19 changed files with 801 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
## January, 18. 2024

- New component: [AriaLive](/uilib/components/aria-live)

## May, 31. 2023

- [New major version 10](/uilib/about-the-lib/releases/eufemia/v10-info/)
- New components released:
- [SkipContent](/uilib/components/skip-content)
- New component: [SkipContent](/uilib/components/skip-content)
- [GlobalError](/uilib/components/global-error) got new styles (without illustrations).
- New [Icons](/icons/secondary):
- `handshake`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: 'AriaLive'
description: 'AriaLive is a React component and hook that helps make your web app more accessible by announcing dynamic changes to screen readers.'
showTabs: true
hideTabs:
- title: Events
theme: 'sbanken'
status: 'new'
---

import AriaLiveInfo from 'Docs/uilib/components/aria-live/info'
import AriaLiveDemos from 'Docs/uilib/components/aria-live/demos'

<AriaLiveInfo />
<AriaLiveDemos />
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* UI lib Component Example
*
*/

import React from 'react'
import { Field, FieldBlock, Form } from '@dnb/eufemia/src/extensions/forms'
import ComponentBox from '../../../../shared/tags/ComponentBox'
import { AriaLive, Button, Flex, P } from '@dnb/eufemia/src'

export const AriaLivePlayground = () => (
<ComponentBox hideCode>
{() => {
const priorities = ['low', 'high']
const contents = {
default: 'This is a default announcement',
second: 'And a second one',
third: 'A third one',
fourth: 'And a fourth one',
}
const priority: 'low' | 'high' = 'low'
const defaultData = {
enabled: false,
content: contents.default,
priority,
}

function AriaLiveExample() {
const { data } = Form.useData('aria-live-playground', defaultData)

return (
<Form.Handler id="aria-live-playground">
<Flex.Stack>
<Field.Boolean label="Enabled" path="/enabled" />
<Field.Selection
variant="button"
optionsLayout="horizontal"
label="Priority"
path="/priority"
>
{priorities.map((content) => {
return (
<Field.Option
key={content}
title={content}
value={content}
/>
)
})}
</Field.Selection>

<Field.Selection
optionsLayout="horizontal"
label="Content"
path="/content"
>
{Object.entries(contents).map(([key, value]) => {
return (
<Field.Option key={key} title={key} value={value} />
)
})}
</Field.Selection>

<Field.String
label="Content as freetext"
path="/content"
multiline
/>

<Flex.Item>
Output:{' '}
<AriaLive
delay={1000}
disabled={!data.enabled}
priority={data.priority}
showChildren
>
Message: {data.content}
</AriaLive>
</Flex.Item>
</Flex.Stack>
</Form.Handler>
)
}

return <AriaLiveExample />
}}
</ComponentBox>
)

export const AriaLiveAdditions = () => (
<ComponentBox hideCode scope={{ FieldBlock }}>
{() => {
const defaultData = {
enabled: false,
content: [<P key="one">Line 1</P>],
}

function AriaLiveExample() {
const { data, update } = Form.useData(
'aria-live-additions',
defaultData,
)

return (
<Form.Handler id="aria-live-additions">
<Flex.Stack>
<Field.Boolean label="Enabled" path="/enabled" />

<FieldBlock label="Content">
<Form.ButtonRow>
<Button
text="Add more content"
variant="secondary"
icon="add"
icon_position="left"
on_click={() => {
update('/content', (content) => {
const c = content.length + 1
content.push(<P key={c}>Line {c}</P>)
return content
})
}}
/>
<Button
text="Remove content"
variant="tertiary"
icon="subtract"
icon_position="left"
on_click={() => {
update('/content', (content) => {
content.pop()
return content
})
}}
/>
</Form.ButtonRow>
</FieldBlock>

<Flex.Item>
Output:{' '}
<AriaLive variant="content" disabled={!data.enabled}>
Message: {data.content}
</AriaLive>
</Flex.Item>
</Flex.Stack>
</Form.Handler>
)
}

return <AriaLiveExample />
}}
</ComponentBox>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
showTabs: true
---

import * as Examples from './Examples'

## Demos

### Playground

<Examples.AriaLivePlayground />

### Additions

<Examples.AriaLiveAdditions />
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
showTabs: true
---

## Description

AriaLive is a React component and hook that helps make your web app more accessible by announcing dynamic changes to screen readers.

Use it to automatically inform users using a screen reader, about changes on the screen that they didn't initiate.

By default, the `AriaLive` component will announce changes to the screen reader in a polite manner. This means that the announcement will be made when the screen reader is idle. This is the recommended way to use the component.

## Usage

For text content:

```tsx
import { AriaLive } from '@dnb/eufemia'
render(<AriaLive>unvisible message to announce</AriaLive>)
```

For content that is not visible, but should be announced on changes:

```tsx
import { AriaLive } from '@dnb/eufemia'
render(
<AriaLive variant="content">
<ul>
<li>item one</li>
<li>item two</li>
{/* When item three appears, it will be announced */}
</ul>
</AriaLive>,
)
```

## Priority

The `priority` prop in the `AriaLive` component is used to control the urgency of the announcement. It can be set to `high` (defaults to `low`). This allows you to control how assertive the announcement should be, helping to create a better user experience for users who rely on screen readers.

## AriaLive Hook

The `useAriaLive` hook is a part of the `AriaLive` component. It can be used to make announcements in functional components. Here's an example of how to use it:

```tsx
import useAriaLive from '@dnb/eufemia/components/aria-live/useAriaLive'

function MyCustomAriaLive(props) {
const ariaAttributes = useAriaLive(props)
return <section {...ariaAttributes} />
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
showTabs: true
---

## Properties

| Properties | Types | Description |
| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `variant` | `string` | _(optional)_ Can be `text` for text messages or `content` for whole application content. Defaults to `text`. |
| `priority` | `string` | _(optional)_ Priority of the announcement. Can be `low` or `high`. Defaults to `low`. |
| `delay` | `number` | _(optional)_ Delay in milliseconds before the announcement is made. Defaults to `1000`. |
| `disabled` | `boolean` | _(optional)_ If `true`, the announcement will not be made. Defaults to `false`. |
| `atomic` | `boolean` | _(optional)_ If `true`, assistive technologies will present the entire region as a whole. If `false`, only additions will be announced. |
| `politeness` | `string` | _(optional)_ The politeness setting for the announcement. Can be `polite` or `assertive`. |
| `relevant` | `string` | _(optional)_ A space-separated list of the types of changes that should be announced. Can be `additions`, `removals`, `text`, or `all`. |
| `showChildren` | `boolean` | _(optional)_ Whether to show the children or not. |
| `children` | `ReactNode` | The content that will be announced to the user. |
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Eufemia includes a range of tools to help you make better accessible application
- [FieldBlock](!/uilib/extensions/forms/create-component/FieldBlock) handles `<fieldset>` and `<legend>`.
- [VisuallyHidden](!/uilib/components/visually-hidden) hides text visually, while makes it available for screen readers. Its based on the helper HTML class `dnb-sr-only`.
- [SkipContent](!/uilib/components/skip-content) similar to a skip link. It allows a user, while tabbing, to skip large parts of content, to reach quickly a save button etc.
- [AriaLive](/uilib/components/aria-live) is a component that makes it easy to announce messages to screen readers.

All form components includes a `label` property to bind automatically the FormLabel to the components (HTML element).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ description: 'Accessibility checklist to help you remember the most important ta
- [ ] Do never expose a form element as `disabled` to the user. Use good UX instead.
- [ ] Have a [Skip Link](/uilib/usage/accessibility/focus#skip-link) in place if the user has to tab many times to reach the main content.
- [ ] Use the [SkipContent](/uilib/components/skip-content/) helper to let the user skip large parts of content, while using keyboard navigation.
- [ ] Use the [AriaLive](/uilib/components/aria-live) component to automatically inform users using a screen reader, about changes on the screen that they didn't initiate.
- [ ] Make good use of [`aria-label`](/uilib/usage/accessibility/screenreader#usage-of-aria-label-aria-labelledby-and-aria-describedby) and `aria-hidden`, e.g. of [decorative content](/uilib/usage/accessibility/icons#decorative-icons).
- [ ] Make [images and illustrations](/uilib/usage/accessibility/screenreader#images-and-illustrations) accessible.
- [ ] Have `aria-live` in place for dynamic content, like updates coming from the server.
Expand Down
14 changes: 14 additions & 0 deletions packages/dnb-eufemia/src/components/AriaLive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* ATTENTION: This file is auto generated by using "prepareTemplates".
* Do not change the content!
*
*/

/**
* Library Index aria-live to autogenerate all the components and extensions
* Used by "prepareAriaLives"
*/

import AriaLive from './aria-live/AriaLive'
export * from './aria-live/AriaLive'
export default AriaLive
11 changes: 11 additions & 0 deletions packages/dnb-eufemia/src/components/aria-live/AriaLive.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'
import { AriaLiveAllProps } from './types'
import useAriaLive from './useAriaLive'

export default function AriaLive(props: AriaLiveAllProps) {
const ariaAttributes = useAriaLive(props)

return <section {...ariaAttributes} />
}

AriaLive._supportsSpacingProps = 'children'
Loading

0 comments on commit 048f5e6

Please sign in to comment.