diff --git a/.changeset/bright-goats-cry.md b/.changeset/bright-goats-cry.md new file mode 100644 index 0000000000..6d25add601 --- /dev/null +++ b/.changeset/bright-goats-cry.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet-react": minor +--- + +Suggestion: Added `display` prop for multiple Suggestion. Set `display="count"` on a multiple Suggestion to show a count label instead of chips. diff --git a/.changeset/great-jeans-follow.md b/.changeset/great-jeans-follow.md new file mode 100644 index 0000000000..dbfc791bf7 --- /dev/null +++ b/.changeset/great-jeans-follow.md @@ -0,0 +1,5 @@ +--- +"@digdir/designsystemet-css": minor +--- + +Suggestion: Added count display mode for multiple Suggestion. Use `data-count` to hide chips and show a count label inside the input. Customize the label text with `--dsc-suggestion-count-label`. diff --git a/apps/www/app/content/components/suggestion/en/code.mdx b/apps/www/app/content/components/suggestion/en/code.mdx index 32ab2b3852..d84e3a4674 100644 --- a/apps/www/app/content/components/suggestion/en/code.mdx +++ b/apps/www/app/content/components/suggestion/en/code.mdx @@ -61,6 +61,13 @@ To allow users to select multiple options, use `data-multiple` on suggestion. +### Multiple choice with count tag + +Use `data-count` to hide chips and show the number of selected options in the input field. +Customize the tag text with the `--dsc-suggestion-count-label` CSS variable. + + + ### Adding new options With `data-creatable` on suggestion, a user can create new selected options by entering text in the input and pressing Enter. diff --git a/apps/www/app/content/components/suggestion/no/code.mdx b/apps/www/app/content/components/suggestion/no/code.mdx index bd736e3ddc..4e311aa935 100644 --- a/apps/www/app/content/components/suggestion/no/code.mdx +++ b/apps/www/app/content/components/suggestion/no/code.mdx @@ -61,6 +61,13 @@ For å tillate at brukeren kan velge flere alternativer, bruk `data-multiple` p +### Flervalg med tag for å vise antall valgt + +Bruk `data-count` for å skjule chips og vise antall valgte alternativer i inputfeltet. +Tilpass teksten med CSS-variabelen `--dsc-suggestion-count-label`. + + + ### 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. diff --git a/apps/www/app/content/components/suggestion/suggestion.stories.tsx b/apps/www/app/content/components/suggestion/suggestion.stories.tsx index 9644cf1e82..f4fdd19b29 100644 --- a/apps/www/app/content/components/suggestion/suggestion.stories.tsx +++ b/apps/www/app/content/components/suggestion/suggestion.stories.tsx @@ -308,6 +308,99 @@ export const Creatable = () => { ); }; +export const MultipleCount = () => { + const DATA_PLACES = [ + 'Sogndal', + 'Oslo', + 'Brønnøysund', + 'Stavanger', + 'Trondheim', + 'Bergen', + 'Lillestrøm', + ]; + const [selected, setSelected] = useState(['Sogndal']); + + return ( + + + + setSelected(items.map((item) => item.value)) + } + > + + + + + Ingen treff + + {DATA_PLACES.map((place) => ( + + {place} + + ))} + + + + ); +}; + +export const MultipleCountEn = () => { + const DATA_PLACES = [ + 'Sogndal', + 'Oslo', + 'Brønnøysund', + 'Stavanger', + 'Trondheim', + 'Bergen', + 'Lillestrøm', + ]; + const [selected, setSelected] = useState(['Sogndal']); + + return ( + + + + setSelected(items.map((item) => item.value)) + } + style={ + { + '--dsc-suggestion-count-label': '"selected"', + } as React.CSSProperties + } + > + + + + + No results found + + {DATA_PLACES.map((place) => ( + + {place} + + ))} + + + + ); +}; + export const CreatableEn = () => { const DATA_PLACES = [ 'Sogndal', diff --git a/packages/css/src/suggestion.css b/packages/css/src/suggestion.css index 6cb2bc2909..ab4ad346be 100644 --- a/packages/css/src/suggestion.css +++ b/packages/css/src/suggestion.css @@ -62,6 +62,37 @@ display: none; /* Hide data elements when not in multiple mode */ } + /* Count display mode: hide chips, show count label inside input */ + &[data-count] data { + display: none; + } + + /* NOTE: This styling should be reflected in tag.css */ + &[data-count]::before { + content: attr(data-count) ' ' var(--dsc-suggestion-count-label, 'valgt'); + position: absolute; + inset-inline-start: var(--ds-size-3); + top: 50%; + translate: 0 -50%; + pointer-events: none; + z-index: 1; + align-items: center; + background: var(--ds-color-surface-tinted); + border: solid transparent var(--ds-border-width-default); + border-radius: var(--ds-border-radius-sm); + box-sizing: border-box; + color: var(--ds-color-text-default); + font-size: var(--ds-body-sm-font-size); + line-height: var(--ds-line-height-sm); + min-height: var(--ds-size-8); + padding: 0 var(--ds-size-2); + display: inline-flex; + } + + &[data-count]:focus-within::before { + display: none; + } + /* NOTE: This styling should be reflected in chip.css */ & > data { align-items: center; diff --git a/packages/react/src/components/suggestion/suggestion.mdx b/packages/react/src/components/suggestion/suggestion.mdx index 50203adf17..949c89b847 100644 --- a/packages/react/src/components/suggestion/suggestion.mdx +++ b/packages/react/src/components/suggestion/suggestion.mdx @@ -10,6 +10,8 @@ import * as SuggestionStories from './suggestion.stories'; + + diff --git a/packages/react/src/components/suggestion/suggestion.stories.tsx b/packages/react/src/components/suggestion/suggestion.stories.tsx index 2cc45bcd63..1d2ef28715 100644 --- a/packages/react/src/components/suggestion/suggestion.stories.tsx +++ b/packages/react/src/components/suggestion/suggestion.stories.tsx @@ -507,6 +507,36 @@ Multiple.args = { multiple: true, }; +export const MultipleCount: StoryFn = (args) => { + const [selected, setSelected] = useState(['Sogndal']); + + return ( + + + + setSelected(items.map((item) => item.value)) + } + > + + + + Tomt + {DATA_PLACES.map((place) => ( + + {place} + + ))} + + + + ); +}; + export const InDetails: StoryFn = (args) => { return (
diff --git a/packages/react/src/components/suggestion/suggestion.tsx b/packages/react/src/components/suggestion/suggestion.tsx index cf78ba4fe2..78e427f9dc 100644 --- a/packages/react/src/components/suggestion/suggestion.tsx +++ b/packages/react/src/components/suggestion/suggestion.tsx @@ -92,6 +92,17 @@ type SuggestionBaseProps = { * @default ({ label }) => label */ renderSelected?: (args: { label: string; value: string }) => ReactNode; + /** + * How selected items are displayed when `multiple` is true. + * + * - `chips` renders removable chips for each selected item (default) + * - `count` hides chips and shows a count label (e.g. "2 valgt") + * + * Customize the label text with the `--dsc-suggestion-count-label` CSS variable. + * + * @default 'chips' + */ + display?: 'chips' | 'count'; } & Omit, 'defaultValue'>; type SuggestionValueProps = { @@ -169,6 +180,7 @@ export const Suggestion = forwardRef( className, creatable = false, defaultSelected, + display = 'chips', filter = true, multiple = false, name, @@ -266,6 +278,10 @@ export const Suggestion = forwardRef( adds attributes