Components
Button
Button allows users to perform actions.
Unable to parse html
const PreviewEn = () => { return <Button>My button</Button>; }; render(<PreviewEn />)
Usage
The class name ds-button is set on <button>.
There are three data attributes you can use for customization:
data-icon- add if the button only has an icon.data-variant- sets the variant of the button (primary,secondary,tertiary).data-fullwidth- add if the button should be full width.
CSS variables and data attributes
Sizes are controlled with data-size and colors with data-color. The component will inherit the closest parent where these are set.
| Name | Value |
|---|---|
| data-fullwidth | |
| data-icon | |
| data-variant | secondary, tertiary |
| Name | Value |
|---|---|
| --dsc-button-background | var(--ds-color-base-default) |
| --dsc-button-background--active | var(--ds-color-base-active) |
| --dsc-button-background--hover | var(--ds-color-base-hover) |
| --dsc-button-border-color | transparent |
| --dsc-button-border-radius | var(--ds-border-radius-default) |
| --dsc-button-border-style | solid |
| --dsc-button-border-width | var(--ds-border-width-default) |
| --dsc-button-color | var(--ds-color-base-contrast-default) |
| --dsc-button-color--active | var(--dsc-button-color--hover) |
| --dsc-button-color--hover | var(--dsc-button-color) |
| --dsc-button-gap | var(--ds-size-2) |
| --dsc-button-padding | var(--ds-size-2) var(--ds-size-4) |
| --dsc-button-size | var(--ds-size-12) |
Example
Variants
variant is used to change the appearance of the button.
Unable to parse html
const Variants = () => { return ( <> <Button variant='primary'>Primary</Button> <Button variant='secondary'>Secondary</Button> <Button variant='tertiary'>Tertiary</Button> </> ); }; render(<Variants />)
Icon
If you only have an icon in the button, you can set data-icon="true" to make it square. If you have other content, such as text, the button will automatically get spacing around the icon.
Unable to parse html
const IconsEn = () => ( <> <Button icon aria-label='Icon only'> <PencilWritingIcon aria-hidden /> </Button> <Button> <PencilWritingIcon aria-hidden /> Edit </Button> </> ); render(<IconsEn />)
Buttons that load
If you want a button that loads, you have to add a loading indicator and aria-busy="true" yourself.
Note: aria-busy does not prevent the button from triggering interactions. It only affects appearance and accessibility, not functionality.
If the button should not be able to perform actions, you must add logic yourself to prevent the callback function from running.
Disabled buttons
As far as possible, you should avoid disabled buttons.
If you have a <button>, you can disable it with the disabled attribute. If you have an <a>, you can disable it with the aria-disabled="true" attribute.
Note: aria-disabled does not prevent the button from triggering interactions. It only affects appearance and accessibility, not functionality.
If the button should not be able to perform actions, you must add logic yourself to prevent the callback function from running.
React
In React, we also set type="button" by default, to avoid unexpected submits in forms.
Button
- variant
- Description
Specify which variant to use
- Type
"primary" | "secondary" | "tertiary"- Default
'primary'
- icon
- Description
Toggle icon only styling, pass icon as children When combined with loading, the loading-icon will be shown instead of the icon.
- Type
boolean- Default
false
- loading
- Description
Toggle loading state. Pass an element if you want to display a custom loader.
- Type
ReactNode- Default
false
- asChild
- Description
Change the default rendered element for the one passed as a child, merging their props and behavior.
- Type
boolean- Default
false
- type
- Description
Specify the type of button. Unset when `asChild` is true
- Type
"button" | "submit" | "reset"- Default
'button'
| Name | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "secondary" | "tertiary" | 'primary' | Specify which variant to use |
| icon | boolean | false | Toggle icon only styling, pass icon as children When combined with loading, the loading-icon will be shown instead of the icon. |
| loading | ReactNode | false | Toggle loading state. Pass an element if you want to display a custom loader. |
| asChild | boolean | false | Change the default rendered element for the one passed as a child, merging their props and behavior. |
| type | "button" | "submit" | "reset" | 'button' | Specify the type of button. Unset when `asChild` is true |
Extra logic for buttons that load
In React, we use loading={true} to show that the button is loading something. Here you can also pass in your own loading component if our Spinner does not fit.
Unable to parse html
const LoadingEn = () => ( <> <Button variant='primary' loading> Loading… </Button> <Button variant='secondary' loading> Loading… </Button> <Button variant='tertiary' loading> Loading… </Button> </> ); render(<LoadingEn />)
In the example above, aria-busy="true" is automatically set when loading={true}. This is the recommended way to show that a button is loading.
Button as link
Links can be styled to look like a button, but consider whether the Link component is a better choice first. To change the button to a link, use asChild. Read more about composition in Designsystemet.
Unable to parse html
const AsLinkEn = () => ( <Button asChild> <a target='_blank' rel='noreferrer' href='https://www.designsystemet.no'> Go to designsystemet.no </a> </Button> ); render(<AsLinkEn />)