Komponenter
Suggestion
Suggestion er en søkbar "select" med mulighet for å velge flere alternativer.
Suggestion er under utvikling. Finner du feil eller mangler, meld fra på Github eller Slack.
HTML
Unable to parse html
const Preview = () => { const DATA_PLACES = ['Sogndal', 'Oslo', 'Brønnøysund']; return ( <Field> <Label>Velg en destinasjon</Label> <EXPERIMENTAL_Suggestion> <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((place) => ( <EXPERIMENTAL_Suggestion.Option key={place} label={place} value={place} > {place} <div>Kommune</div> </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> ); }; render(<Preview />)
Bruk
Suggestion baserer seg på open-ui sitt combobox mønster (open-ui.org) og bruker u-combobox fra u-elements (github.io) for å oppfylle grunnleggende funksjonalitet fra combobox mønsteret.
Bruk klassen ds-suggestion på custom elementet <ds-suggestion>.
Legg til <input class="ds-input" /> og <u-datalist> med <u-option> som barn for å få en fungerende suggestion.
For et gyldig skjemaelement anbefaler vi å bruke <ds-suggestion> i <ds-field> sammen med en <label>.
CSS variabler og data-attributter
Størrelser styres med data-size og farger med data-color. Komponenten vil arve nærmeste forelder med disse satt.
Suggestion bruker elementer fra u-elements og har derfor mange av de samme custom elementer, data-attributter og CSS variabler.
Du kan lese mer om hvordan du bruker disse i u-elements sin u-combobox dokumentasjon.
| Navn | Verdi |
|---|---|
| --dsc-suggestion-option-background--hover | var(--ds-color-surface-hover) |
| --dsc-suggestion-option-background--selected | var(--ds-color-surface-active) |
| --dsc-suggestion-option-border-radius | var(--ds-border-radius-md) |
| --dsc-suggestion-option-checkmark-size | var(--ds-size-6) |
| --dsc-suggestion-option-checkmark-url | url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' fill='none' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M18.998 6.94a.75.75 0 0 1 .063 1.058l-8 9a.75.75 0 0 1-1.091.032l-5-5a.75.75 0 1 1 1.06-1.06l4.438 4.437 7.471-8.405A.75.75 0 0 1 19 6.939' clip-rule='evenodd'/%3E%3C/svg%3E") |
| --dsc-suggestion-option-padding | var(--ds-size-3) |
| --dsc-suggestion-option-gap | var(--ds-size-2) |
| --dsc-suggestion-option-checkmark-border | max(2px,0.125rem) |
| --dsc-suggestion-option-checkmark-border-color | var(--ds-color-neutral-border-default) |
| --dsc-suggestion-clear-gap | var(--ds-size-2) |
| --dsc-suggestion-clear-padding | var(--ds-size-1) |
| --dsc-suggestion-clear-size | var(--ds-size-9) |
| --dsc-suggestion-clear-icon-url | url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath fill='currentColor' d='M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94z'/%3E%3C/svg%3E") |
| --dsc-suggestion-clear-border-radius | var(--ds-border-radius-md) |
| --dsc-suggestion-clear-background--hover | var(--ds-color-surface-hover) |
| --dsc-suggestion-clear-background--active | var(--ds-color-surface-active) |
| --dsc-suggestion-list-background | var(--ds-color-neutral-surface-default) |
| --dsc-suggestion-list-border-radius | var(--ds-border-radius-md) |
| --dsc-suggestion-list-box-shadow | var(--ds-shadow-md) |
| --dsc-suggestion-list-color | var(--ds-color-text-default) |
| --dsc-suggestion-list-offset | var(--ds-size-1) |
| --dsc-suggestion-list-gap | var(--ds-size-1) |
| --dsc-suggestion-list-placement | bottom |
| --dsc-suggestion-list-padding | var(--ds-size-3) var(--ds-size-2) |
| --dsc-suggestion-border-width | var(--ds-border-width-default) |
| --dsc-suggestion-border-style | solid |
| --dsc-suggestion-border-color | var(--ds-color-neutral-border-subtle) |
| --dsc-suggestion-chip-gap | var(--ds-size-1) |
| --dsc-suggestion-chip-background | var(--ds-color-base-default) |
| --dsc-suggestion-chip-background--hover | var(--ds-color-base-hover) |
| --dsc-suggestion-chip-border-width | var(--ds-border-width-default) |
| --dsc-suggestion-chip-height | var(--ds-size-8) |
| --dsc-suggestion-chip-font-size | var(--ds-body-sm-font-size) |
| --dsc-suggestion-chip-border-style | solid |
| --dsc-suggestion-chip-border-color | transparent |
| --dsc-suggestion-chip-border-radius | var(--ds-border-radius-full) |
| --dsc-suggestion-chip-padding | 0 var(--ds-size-3) |
| --dsc-suggestion-chip-color | var(--ds-color-base-contrast-default) |
| --dsc-suggestion-chip-icon-url | url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' fill='none' viewBox='0 0 24 24'%3E%3Cpath fill='currentColor' d='M6.53 5.47a.75.75 0 0 0-1.06 1.06L10.94 12l-5.47 5.47a.75.75 0 1 0 1.06 1.06L12 13.06l5.47 5.47a.75.75 0 1 0 1.06-1.06L13.06 12l5.47-5.47a.75.75 0 0 0-1.06-1.06L12 10.94z'/%3E%3C/svg%3E") |
| --dsc-suggestion-chip-icon-size | var(--ds-size-7) |
| --dsc-suggestion-chip-input-size | var(--ds-size-5) |
| --dsc-suggestion-chip-spacing | calc((var(--dsc-suggestion-chip-height) - var(--dsc-suggestion-chip-input-size))/2) |
| --dsc-button-size | var(--dsc-suggestion-clear-size) |
| Navn | Verdi |
|---|---|
| data-multiple | false |
| data-is-floating | |
| data-overscroll | contain |
| data-floating | top, right, bottom, left |
| data-empty | |
| data-activedescendant |
Eksempel
Sjekk ut u-combobox sin dokumentasjon for flere eksempler på hvordan du kan bruke suggestion.
Flervalg
For å tillate at brukeren kan velge flere alternativer, bruk data-multiple på suggestion.
HTML
Unable to parse html
const Multiple = () => { const DATA_PLACES = [ 'Sogndal', 'Oslo', 'Brønnøysund', 'Stavanger', 'Trondheim', 'Bergen', 'Lillestrøm', ]; return ( <Field> <Label>Velg en destinasjon</Label> <EXPERIMENTAL_Suggestion multiple> <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((place) => ( <EXPERIMENTAL_Suggestion.Option key={place}> {place} </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> ); }; render(<Multiple />)
Legge til nye alternativer
Med data-creatable på suggestion kan en bruker opprette nye valgte alternativer ved å skrive inn tekst i input og trykke Enter.
HTML
Unable to parse html
const Creatable = () => { const DATA_PLACES = [ 'Sogndal', 'Oslo', 'Brønnøysund', 'Stavanger', 'Trondheim', 'Bergen', 'Lillestrøm', ]; return ( <Field> <Label>Velg destinasjon</Label> <EXPERIMENTAL_Suggestion creatable multiple> <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff, trykk enter for å legge til </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((place) => ( <EXPERIMENTAL_Suggestion.Option key={place}> {place} </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> ); }; render(<Creatable />)
Tøm valget
Legg til en knapp med type="reset" og aria-label for å la brukeren tømme valget.
HTML
Unable to parse html
const Preview = () => { const DATA_PLACES = ['Sogndal', 'Oslo', 'Brønnøysund']; return ( <Field> <Label>Velg en destinasjon</Label> <EXPERIMENTAL_Suggestion> <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((place) => ( <EXPERIMENTAL_Suggestion.Option key={place} label={place} value={place} > {place} <div>Kommune</div> </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> ); }; render(<Preview />)
React
- filter
- Description
Filter options; boolean or a custom callback. See {@link Filter} for the callback signature.
- Type
boolean | Filter- Default
true
- creatable
- Description
Allows the user to create new items
- Type
boolean- Default
false
- onBeforeMatch
- Description
Callback when matching input value against options
- Type
((event: EventBeforeMatch) => void)
- name
- Description
The name of the associated form control
- Type
string- Default
undefined
- renderSelected
- Description
Change how the selected options are rendered inside the `Chip`.
- Type
((args: { label: string; value: string; }) => ReactNode)- Default
({ label }) => label
- multiple
- Description
Allows the user to select multiple items
- Type
boolean- Default
false
- selected
- Description
The selected item of the Suggestion. If `label` and `value` are the same, each item can be a `string`. Otherwise, each item must be a `SuggestionItem`. Using this makes the component controlled and it must be used in combination with `onSelectedChange`.
- Type
string | SuggestionItem | (string | SuggestionItem)[] | null
- defaultSelected
- Description
Default selected item when uncontrolled
- Type
string | SuggestionItem | (string | SuggestionItem)[]
- onSelectedChange
- Description
Callback when selected items changes
- Type
((value: SuggestionItem | null) => void) | ((value: SuggestionItem[]) => void)
| Name | Type | Default | Description |
|---|---|---|---|
| filter | boolean | Filter | true | Filter options; boolean or a custom callback. See {@link Filter} for the callback signature. |
| creatable | boolean | false | Allows the user to create new items |
| onBeforeMatch | ((event: EventBeforeMatch) => void) | - | Callback when matching input value against options |
| name | string | undefined | The name of the associated form control |
| renderSelected | ((args: { label: string; value: string; }) => ReactNode) | ({ label }) => label | Change how the selected options are rendered inside the `Chip`. |
| multiple | boolean | false | Allows the user to select multiple items |
| selected | string | SuggestionItem | (string | SuggestionItem)[] | null | - | The selected item of the Suggestion. If `label` and `value` are the same, each item can be a `string`. Otherwise, each item must be a `SuggestionItem`. Using this makes the component controlled and it must be used in combination with `onSelectedChange`. |
| defaultSelected | string | SuggestionItem | (string | SuggestionItem)[] | - | Default selected item when uncontrolled |
| onSelectedChange | ((value: SuggestionItem | null) => void) | ((value: SuggestionItem[]) => void) | - | Callback when selected items changes |
SuggestionClear
- command
- Type
string
- commandfor
- Type
string
- aria-label
- Description
Aria label for the clear button
- Type
string- Default
Tøm
| Name | Type | Default | Description |
|---|---|---|---|
| command | string | - | - |
| commandfor | string | - | - |
| aria-label | string | Tøm | Aria label for the clear button |
SuggestionInput
- type
- Description
Supported `input` types
- Type
"number" | "hidden" | "color" | "checkbox" | "date" | "datetime-local" | "email" | "file" | "month" | "password" | "radio" | "search" | "tel" | "text" | "time" | "url" | "week"- Default
'text'
- disabled
- Description
Disables element @note Avoid using if possible for accessibility purposes
- Type
boolean
- readOnly
- Description
Toggle `readOnly`
- Type
boolean
- size
- Description
Defines the width of `Input` in count of characters.
- Type
number
| Name | Type | Default | Description |
|---|---|---|---|
| type | "number" | "hidden" | "color" | "checkbox" | "date" | "datetime-local" | "email" | "file" | "month" | "password" | "radio" | "search" | "tel" | "text" | "time" | "url" | "week" | 'text' | Supported `input` types |
| disabled | boolean | - | Disables element @note Avoid using if possible for accessibility purposes |
| readOnly | boolean | - | Toggle `readOnly` |
| size | number | - | Defines the width of `Input` in count of characters. |
SuggestionList
- singular
- Description
The screen reader announcement for singular Suggestion, where %d is the number of Suggestions
- Type
string- Default
%d forslag
- plural
- Description
The screen reader announcement for plural Suggestions, where %d is the number of Suggestions
- Type
string- Default
%d forslag
- autoPlacement
- Description
Whether to enable auto placement.
- Type
boolean- Default
true
| Name | Type | Default | Description |
|---|---|---|---|
| singular | string | %d forslag | The screen reader announcement for singular Suggestion, where %d is the number of Suggestions |
| plural | string | %d forslag | The screen reader announcement for plural Suggestions, where %d is the number of Suggestions |
| autoPlacement | boolean | true | Whether to enable auto placement. |
Eksempel på kontrollert flervalg
Har du behov for å kontrollere hvilke alternativer som er valgt, kan du bruke selected og onSelectedChange på Suggestion.
React
Unable to parse html
const ControlledMultiple = () => { const DATA_PLACES = [ 'Sogndal', 'Oslo', 'Brønnøysund', 'Stavanger', 'Trondheim', 'Bergen', 'Lillestrøm', ]; const [selected, setSelected] = useState<string[]>(['Oslo']); return ( <> <Field> <Label>Velg destinasjoner</Label> <EXPERIMENTAL_Suggestion multiple selected={selected} onSelectedChange={(items) => setSelected(items.map((item) => item.value)) } > <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((place) => ( <EXPERIMENTAL_Suggestion.Option key={place} label={place} value={place} > {place} <div>Kommune</div> </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> <Divider style={{ marginTop: 'var(--ds-size-4)' }} /> <Paragraph style={{ margin: 'var(--ds-size-2) 0' }}> Valgte reisemål: {selected.join(', ')} </Paragraph> <Button onClick={() => { setSelected(['Sogndal', 'Stavanger']); }} > Sett reisemål til Sogndal, Stavanger </Button> </> ); }; render(<ControlledMultiple />)
Filter
Filter er som standard på, og filteret ser etter teksten i input. Du kan sende inn ditt eget filter. Under vises et eksempel som skrur av filteret helt.
React
Unable to parse html
const Filter = () => { const DATA_PLACES = [ 'Sogndal', 'Oslo', 'Brønnøysund', 'Stavanger', 'Trondheim', 'Bergen', 'Lillestrøm', ]; return ( <Field> <Label>Skriv inn et tall mellom 1-6</Label> <EXPERIMENTAL_Suggestion filter={false}> <EXPERIMENTAL_Suggestion.Input /> <EXPERIMENTAL_Suggestion.Clear /> <EXPERIMENTAL_Suggestion.List> <EXPERIMENTAL_Suggestion.Empty> Ingen treff </EXPERIMENTAL_Suggestion.Empty> {DATA_PLACES.map((label) => ( <EXPERIMENTAL_Suggestion.Option key={label} value={label.toLowerCase()} > {label} </EXPERIMENTAL_Suggestion.Option> ))} </EXPERIMENTAL_Suggestion.List> </EXPERIMENTAL_Suggestion> </Field> ); }; render(<Filter />)