Skip to content

Commit

Permalink
feat(Button): rewise documented title prop with aria-label document…
Browse files Browse the repository at this point in the history
…ation (#3863)

* `aria-label` is automatically set to the same value as `title` if the
button has no content
* documentation updated to make it clear that `title` is not good enough
for accessibility
  • Loading branch information
snorrekim authored Sep 2, 2024
1 parent b082ce4 commit ea444c0
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ Large Signal button with medium sized icon. To import custom icons, use: `import

### Icon button

When the button has no text an `aria-label` attribute is required for accessibility. And a `title` attribute is recommended for mouse hover.

We automatically add an `aria-label` with the same value as `title` if `text` and `children` props are undefined. So in most cases you only have to set the `title` prop.

<ButtonIcon />

### Custom button content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ showTabs: true
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | _(optional)_ `button`, `reset` or `submit` for the `type` HTML attribute. Defaults to `button` for legacy reasons. |
| `text` or `children` | _(optional)_ the content of the button can be a string or a React Element. |
| `title` | _(optional)_ title of the button. Optional, but should always be included because of accessibility. |
| `aria-label` or `title` | _(optional)_ required if there is no text in the button. If `text` and `children` are undefined, setting the `title` prop will automatically set `aria-label` with the same value. |
| `variant` | _(optional)_ defines the kind of button. Possible values are `primary`, `secondary`, `tertiary` and `signal`. Defaults to `primary` (or `secondary` if icon only). |
| `size` | _(optional)_ the size of the button. For now there is `small`, `medium`, `default` and `large`. |
| `icon` | _(optional)_ to be included in the button. [Primary Icons](/icons/primary) can be set as a string (e.g. `icon="chevron_right"`), other icons should be set as React elements. |
Expand Down
7 changes: 5 additions & 2 deletions packages/dnb-eufemia/src/components/button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ export default class Button extends React.PureComponent {
if (Element !== Anchor && !params.type) {
params.type = params.type === '' ? undefined : 'button'
}
if (isIconOnly) {
params['aria-label'] = params['aria-label'] || title
}

skeletonDOMAttributes(params, skeleton, this.context)

Expand Down Expand Up @@ -279,7 +282,7 @@ export default class Button extends React.PureComponent {
Button.propTypes = {
text: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
type: PropTypes.string,
title: PropTypes.node,
title: PropTypes.string,
variant: buttonVariantPropType.variant,
size: PropTypes.oneOf(['default', 'small', 'medium', 'large']),
icon: PropTypes.oneOfType([
Expand Down Expand Up @@ -460,7 +463,7 @@ function Content({
}

Content.propTypes = {
title: PropTypes.node,
title: PropTypes.string,
custom_content: PropTypes.node,
content: PropTypes.oneOfType([
PropTypes.string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ describe('Button component', () => {
expect(button.getAttribute('title')).toBe(title)
})

it('icon button should set aria-label with title', () => {
const title = 'title'
render(<Button icon="bell" title={title} />)
const button = document.querySelector('button')

expect(button.getAttribute('title')).toBe(title)
expect(button.getAttribute('aria-label')).toBe(title)
})

it('icon only has to have some extra classes', () => {
render(<Button icon="question" />)
const button = document.querySelector('button')
Expand Down

0 comments on commit ea444c0

Please sign in to comment.