diff --git a/.changeset/breezy-queens-fetch.md b/.changeset/breezy-queens-fetch.md new file mode 100644 index 0000000000..fdbeabd6b0 --- /dev/null +++ b/.changeset/breezy-queens-fetch.md @@ -0,0 +1,10 @@ +--- +"@navikt/aksel-stylelint": minor +"@navikt/ds-css": minor +"@navikt/ds-react": minor +--- + +:tada: Oppdatert Chips + +- Toggle Chips har nå varianter: neutral og action +- Toggle Chips har nå en ny prop: `checkmark` som slår av/på checkmark ved selected-state diff --git a/.changeset/small-clouds-wash.md b/.changeset/small-clouds-wash.md index a016e5d141..4f674fc163 100644 --- a/.changeset/small-clouds-wash.md +++ b/.changeset/small-clouds-wash.md @@ -3,4 +3,4 @@ "@navikt/ds-react": patch --- -add indent prop to accordion +:sparkles: La til `indent`-prop på Accordion diff --git a/@navikt/aksel-stylelint/src/deprecations.ts b/@navikt/aksel-stylelint/src/deprecations.ts index 5c96b0d469..783168be5c 100644 --- a/@navikt/aksel-stylelint/src/deprecations.ts +++ b/@navikt/aksel-stylelint/src/deprecations.ts @@ -20,4 +20,9 @@ export const deprecations: DeprecatedList = [ "Class were moved to '@navikt/ds-css' and renamed with 'navds'-prefix in v4.0.0. Docs: https://aksel.nav.no/grunnleggende/kode/endringslogg#h728704adeb59.", deprecatePrefix: true, }, + { + classes: ["navds-chips--icon-left"], + message: + "In v4.1.0 Chips. Toggle no longer handles special alignment for checkmark-icon, thus removing this class", + }, ]; diff --git a/@navikt/core/css/chips.css b/@navikt/core/css/chips.css index eae4a00e24..dd4d30c49c 100644 --- a/@navikt/core/css/chips.css +++ b/@navikt/core/css/chips.css @@ -20,7 +20,7 @@ cursor: pointer; align-items: center; justify-content: center; - gap: var(--a-spacing-05); + gap: var(--a-spacing-1); margin: 0; padding: 0 var(--a-spacing-3); text-decoration: none; @@ -34,14 +34,14 @@ } .navds-chips__toggle { - box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border, var(--a-border-default)); - background-color: var(--ac-chip-toggle-bg, var(--a-surface-neutral-subtle)); + box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border, var(--a-border-subtle)); + background-color: var(--ac-chip-toggle-bg, var(--a-surface-action-subtle)); color: var(--ac-chip-toggle-text, var(--a-text-default)); } .navds-chips__toggle:hover { - box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-hover-border, var(--a-border-strong)); - background-color: var(--ac-chip-toggle-hover-bg, var(--a-surface-neutral-subtle-hover)); + box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-hover-border, var(--a-border-subtle-hover)); + background-color: var(--ac-chip-toggle-hover-bg, var(--a-surface-action-subtle-hover)); } .navds-chips__toggle[aria-pressed="true"] { @@ -54,6 +54,28 @@ background-color: var(--ac-chip-toggle-pressed-hover-bg, var(--a-surface-action-selected-hover)); } +/* Toggle variant neutral */ +.navds-chips__toggle--neutral { + box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-neutral-border, var(--a-border-subtle)); + background-color: var(--ac-chip-toggle-neutral-bg, var(--a-surface-neutral-subtle)); + color: var(--ac-chip-toggle-neutral-text, var(--a-text-default)); +} + +.navds-chips__toggle--neutral:hover { + box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-neutral-hover-border, var(--a-border-subtle-hover)); + background-color: var(--ac-chip-toggle-neutral-hover-bg, var(--a-surface-neutral-subtle-hover)); +} + +.navds-chips__toggle--neutral[aria-pressed="true"] { + box-shadow: none; + background-color: var(--ac-chip-toggle-neutral-pressed-bg, var(--a-surface-neutral-selected)); + color: var(--ac-chip-toggle-neutral-pressed-text, var(--a-text-on-neutral)); +} + +.navds-chips__toggle--neutral[aria-pressed="true"]:hover { + background-color: var(--ac-chip-toggle-neutral-pressed-hover-bg, var(--a-surface-neutral-selected)); +} + .navds-chips__toggle:focus-visible { box-shadow: 0 0 0 2px var(--ac-chip-toggle-focus, var(--a-border-focus)); } @@ -99,14 +121,6 @@ border-radius: var(--a-border-radius-full); } -.navds-chips__toggle-icon { - width: 1.5rem; - height: 1.5rem; - display: grid; - place-items: center; - border-radius: var(--a-border-radius-full); -} - .navds-chips--small .navds-chips__toggle-icon { width: 1.25rem; height: 1.25rem; @@ -161,7 +175,3 @@ .navds-chips--small .navds-chips--icon-right { padding-right: var(--a-spacing-05); } - -.navds-chips--small .navds-chips--icon-left { - padding-left: 0.375rem; -} diff --git a/@navikt/core/css/tokens.json b/@navikt/core/css/tokens.json index 9cb0c91f58..64bcd10170 100644 --- a/@navikt/core/css/tokens.json +++ b/@navikt/core/css/tokens.json @@ -86,14 +86,22 @@ "--ac-chat-top-text": "--a-text-default" }, "chips": { - "--ac-chip-toggle-border": "--a-border-default", - "--ac-chip-toggle-bg": "--a-surface-neutral-subtle", + "--ac-chip-toggle-border": "--a-border-subtle", + "--ac-chip-toggle-bg": "--a-surface-action-subtle", "--ac-chip-toggle-text": "--a-text-default", - "--ac-chip-toggle-hover-border": "--a-border-strong", - "--ac-chip-toggle-hover-bg": "--a-surface-neutral-subtle-hover", + "--ac-chip-toggle-hover-border": "--a-border-subtle-hover", + "--ac-chip-toggle-hover-bg": "--a-surface-action-subtle-hover", "--ac-chip-toggle-pressed-bg": "--a-surface-action-selected", "--ac-chip-toggle-pressed-text": "--a-text-on-action", "--ac-chip-toggle-pressed-hover-bg": "--a-surface-action-selected-hover", + "--ac-chip-toggle-neutral-border": "--a-border-subtle", + "--ac-chip-toggle-neutral-bg": "--a-surface-neutral-subtle", + "--ac-chip-toggle-neutral-text": "--a-text-default", + "--ac-chip-toggle-neutral-hover-border": "--a-border-subtle-hover", + "--ac-chip-toggle-neutral-hover-bg": "--a-surface-neutral-subtle-hover", + "--ac-chip-toggle-neutral-pressed-bg": "--a-surface-neutral-selected", + "--ac-chip-toggle-neutral-pressed-text": "--a-text-on-neutral", + "--ac-chip-toggle-neutral-pressed-hover-bg": "--a-surface-neutral-selected", "--ac-chip-toggle-focus": "--a-border-focus", "--ac-chip-removable-action-bg": "--a-surface-action-selected", "--ac-chip-removable-action-text": "--a-text-on-action", diff --git a/@navikt/core/react/src/chips/Toggle.tsx b/@navikt/core/react/src/chips/Toggle.tsx index 323cf44652..1ff829a298 100644 --- a/@navikt/core/react/src/chips/Toggle.tsx +++ b/@navikt/core/react/src/chips/Toggle.tsx @@ -1,4 +1,3 @@ -import { CheckmarkIcon } from "@navikt/aksel-icons"; import cl from "clsx"; import React, { forwardRef } from "react"; import { OverridableComponent } from "../util/OverridableComponent"; @@ -10,6 +9,16 @@ export interface ToggleChipsProps * Toggles aria-pressed and visual-changes */ selected?: boolean; + /** + * Chip-variants + * @default "action" + */ + variant?: "action" | "neutral"; + /** + * Toggles display of checkmark on selected + * @default true + */ + checkmark?: boolean; } export const ToggleChips: OverridableComponent< @@ -17,20 +26,47 @@ export const ToggleChips: OverridableComponent< HTMLButtonElement > = forwardRef( ( - { className, children, selected, as: Component = "button", ...rest }, + { + className, + children, + selected, + variant = "action", + checkmark = true, + as: Component = "button", + ...rest + }, ref ) => { return ( - {selected && ( - + {selected && checkmark && ( + + + )} {children} diff --git a/@navikt/core/react/src/chips/chips.stories.tsx b/@navikt/core/react/src/chips/chips.stories.tsx index 43a3581a25..d2515c5c95 100644 --- a/@navikt/core/react/src/chips/chips.stories.tsx +++ b/@navikt/core/react/src/chips/chips.stories.tsx @@ -66,25 +66,78 @@ export const Default = { }; export const Toggle = () => { - const [selected, setSelected] = useState([]); + const [selected, setSelected] = useState([2, 4]); + return ( +
+ + {options.map((c, y) => ( + + setSelected( + selected.includes(y) + ? selected.filter((x) => x !== y) + : [...selected, y] + ) + } + key={y} + > + {c} + + ))} + + + {options.map((c, y) => ( + + setSelected( + selected.includes(y) + ? selected.filter((x) => x !== y) + : [...selected, y] + ) + } + key={y} + > + {c} + + ))} + +
+ ); +}; + +export const ToggleNoCheckmark = () => { + const [selected, setSelected] = useState(2); return ( - - {options.map((c, y) => ( - - setSelected( - selected.includes(y) - ? selected.filter((x) => x !== y) - : [...selected, y] - ) - } - key={y} - > - {c} - - ))} - +
+ + {options.map((c, y) => ( + setSelected(y)} + key={y} + > + {c} + + ))} + + + {options.map((c, y) => ( + setSelected(y)} + key={y} + > + {c} + + ))} + +
); }; @@ -108,7 +161,7 @@ export const Removable = () => { }; export const Regular = () => { - const [selected, setSelected] = useState([]); + const [selected, setSelected] = useState([2]); return (
diff --git a/aksel.nav.no/website/pages/eksempler/chips/default.tsx b/aksel.nav.no/website/pages/eksempler/chips/default.tsx deleted file mode 100644 index fce2d15fe9..0000000000 --- a/aksel.nav.no/website/pages/eksempler/chips/default.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Chips } from "@navikt/ds-react"; -import { withDsExample } from "components/website-modules/examples/withDsExample"; -import { useState } from "react"; - -const Example = () => { - const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"]; - - const [selected, setSelected] = useState(["Dansk", "Svensk"]); - const [filter, setFilter] = useState(options); - - return ( -
- - {options.map((c) => ( - - setSelected( - selected.includes(c) - ? selected.filter((x) => x !== c) - : [...selected, c] - ) - } - > - {c} - - ))} - - - {filter.map((c) => ( - - setFilter((x) => - x.length === 1 ? options : x.filter((y) => y !== c) - ) - } - > - {c} - - ))} - -
- ); -}; - -export default withDsExample(Example); - -/* Storybook story */ -export const Demo = { - render: Example, -}; - -export const args = { - index: 0, -}; diff --git a/aksel.nav.no/website/pages/eksempler/chips/removable-neutral.tsx b/aksel.nav.no/website/pages/eksempler/chips/removable-neutral.tsx new file mode 100644 index 0000000000..9442333786 --- /dev/null +++ b/aksel.nav.no/website/pages/eksempler/chips/removable-neutral.tsx @@ -0,0 +1,47 @@ +import { Chips } from "@navikt/ds-react"; +import { withDsExample } from "components/website-modules/examples/withDsExample"; +import { useState } from "react"; + +const Example = () => { + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; + + const [filter, setFilter] = useState(options); + + return ( + + {filter.map((c) => ( + + setFilter((x) => + x.length === 1 ? options : x.filter((y) => y !== c) + ) + } + > + {c} + + ))} + + ); +}; + +export default withDsExample(Example); + +/* Storybook story */ +export const Demo = { + render: Example, +}; + +export const args = { + index: 5, +}; diff --git a/aksel.nav.no/website/pages/eksempler/chips/removable.tsx b/aksel.nav.no/website/pages/eksempler/chips/removable.tsx index 34d34b2738..874925bb34 100644 --- a/aksel.nav.no/website/pages/eksempler/chips/removable.tsx +++ b/aksel.nav.no/website/pages/eksempler/chips/removable.tsx @@ -3,7 +3,16 @@ import { withDsExample } from "components/website-modules/examples/withDsExample import { useState } from "react"; const Example = () => { - const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"]; + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; const [filter, setFilter] = useState(options); @@ -12,6 +21,7 @@ const Example = () => { {filter.map((c) => ( setFilter((x) => x.length === 1 ? options : x.filter((y) => y !== c) @@ -33,5 +43,5 @@ export const Demo = { }; export const args = { - index: 2, + index: 4, }; diff --git a/aksel.nav.no/website/pages/eksempler/chips/small.tsx b/aksel.nav.no/website/pages/eksempler/chips/small.tsx index d567817c1d..b6af75d9f0 100644 --- a/aksel.nav.no/website/pages/eksempler/chips/small.tsx +++ b/aksel.nav.no/website/pages/eksempler/chips/small.tsx @@ -3,9 +3,18 @@ import { withDsExample } from "components/website-modules/examples/withDsExample import { useState } from "react"; const Example = () => { - const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"]; + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; - const [selected, setSelected] = useState(["Dansk", "Svensk"]); + const [selected, setSelected] = useState(["Arendal", "Nittedal"]); const [filter, setFilter] = useState(options); return ( @@ -53,5 +62,5 @@ export const Demo = { }; export const args = { - index: 3, + index: 6, }; diff --git a/aksel.nav.no/website/pages/eksempler/chips/toggle-neutral.tsx b/aksel.nav.no/website/pages/eksempler/chips/toggle-neutral.tsx new file mode 100644 index 0000000000..e43eab9a2a --- /dev/null +++ b/aksel.nav.no/website/pages/eksempler/chips/toggle-neutral.tsx @@ -0,0 +1,50 @@ +import { Chips } from "@navikt/ds-react"; +import { withDsExample } from "components/website-modules/examples/withDsExample"; +import { useState } from "react"; + +const Example = () => { + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; + + const [selected, setSelected] = useState(["Gjøvik", "Hamar"]); + + return ( + + {options.map((c) => ( + + setSelected( + selected.includes(c) + ? selected.filter((x) => x !== c) + : [...selected, c] + ) + } + > + {c} + + ))} + + ); +}; + +export default withDsExample(Example); + +/* Storybook story */ +export const Demo = { + render: Example, +}; + +export const args = { + index: 2, +}; diff --git a/aksel.nav.no/website/pages/eksempler/chips/toggle-no-checkmark.tsx b/aksel.nav.no/website/pages/eksempler/chips/toggle-no-checkmark.tsx new file mode 100644 index 0000000000..8371b4d0dd --- /dev/null +++ b/aksel.nav.no/website/pages/eksempler/chips/toggle-no-checkmark.tsx @@ -0,0 +1,44 @@ +import { Chips } from "@navikt/ds-react"; +import { withDsExample } from "components/website-modules/examples/withDsExample"; +import { useState } from "react"; + +const Example = () => { + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; + + const [selected, setSelected] = useState(3); + + return ( + + {options.map((c, y) => ( + setSelected(y)} + > + {c} + + ))} + + ); +}; + +export default withDsExample(Example); + +/* Storybook story */ +export const Demo = { + render: Example, +}; + +export const args = { + index: 3, +}; diff --git a/aksel.nav.no/website/pages/eksempler/chips/toggle.tsx b/aksel.nav.no/website/pages/eksempler/chips/toggle.tsx index b01c5aed8d..8efc388736 100644 --- a/aksel.nav.no/website/pages/eksempler/chips/toggle.tsx +++ b/aksel.nav.no/website/pages/eksempler/chips/toggle.tsx @@ -3,9 +3,18 @@ import { withDsExample } from "components/website-modules/examples/withDsExample import { useState } from "react"; const Example = () => { - const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"]; + const options = [ + "Lillehammer", + "Nittedal", + "Enebakk", + "Hamar", + "Skedsmo", + "Arendal", + "Gjøvik", + "Vennesla", + ]; - const [selected, setSelected] = useState(["Dansk", "Svensk"]); + const [selected, setSelected] = useState(["Nittedal", "Arendal"]); return (