@helsenorge/designsystem-react 12.10.0 → 12.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,43 @@
1
+ ## [12.11.1](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv12.11.0&targetVersion=GTv12.11.1) (2025-11-04)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **dropdown:** krymper med høyden igjen
6
+ ([07d9baf](https://github.com/helsenorge/designsystem/commit/07d9baf51824dff93a5c45766f59a2fdf9285caa)), closes
7
+ [#363493](https://github.com/helsenorge/designsystem/issues/363493)
8
+ - **dropdown:** listen flyttes ikke i y aksen av viewport
9
+ ([357ea4f](https://github.com/helsenorge/designsystem/commit/357ea4ff08fc405bc8004c83ab5c0f9cb2b56145)), closes
10
+ [#363493](https://github.com/helsenorge/designsystem/issues/363493)
11
+
12
+ ## [12.11.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv12.10.0&targetVersion=GTv12.11.0) (2025-11-03)
13
+
14
+ ### Features
15
+
16
+ - tydeligere focus state for noen komponenter
17
+ ([412e779](https://github.com/helsenorge/designsystem/commit/412e779f6e01a11fcc593ed57dbfd32168a3241e)), closes
18
+ [#357133](https://github.com/helsenorge/designsystem/issues/357133)
19
+
20
+ ### Bug Fixes
21
+
22
+ - **button:** align tekst til venstre ved flere linjer
23
+ ([b47f1e0](https://github.com/helsenorge/designsystem/commit/b47f1e0e137230a3c8017b07e7671d063e91d86a))
24
+ - **button:** fiks padding rundt tekst når den går over flere linjer
25
+ ([7ff8f63](https://github.com/helsenorge/designsystem/commit/7ff8f63f305291c56f77ec3a25334f74b2205dfb))
26
+ - **button:** oppdatert padding på borderless variant
27
+ ([be2b683](https://github.com/helsenorge/designsystem/commit/be2b6833591625a90b235e48e7682f6eb722bbf6))
28
+ - **dropdown:** aligner og krymper riktig ved mindre plass
29
+ ([4b28673](https://github.com/helsenorge/designsystem/commit/4b286731a9dae975e29e8d17c0c200099405e789)), closes
30
+ [#363493](https://github.com/helsenorge/designsystem/issues/363493)
31
+ - **toast:** fiks størrelse på ikon og plassering i grid
32
+ ([cf38ba8](https://github.com/helsenorge/designsystem/commit/cf38ba8c399bd66f2f24c7f64fa88688cc639656)), closes
33
+ [#357838](https://github.com/helsenorge/designsystem/issues/357838)
34
+ - **toast:** legg til litt spacing mellom innhold
35
+ ([1c900de](https://github.com/helsenorge/designsystem/commit/1c900de13b3c1d19d3326bf15ec7e0f34c2fc530)), closes
36
+ [#357838](https://github.com/helsenorge/designsystem/issues/357838)
37
+ - **toast:** liten justering av tekst
38
+ ([481834f](https://github.com/helsenorge/designsystem/commit/481834f15ed31e4eb02788db58f795079fd07877)), closes
39
+ [#357838](https://github.com/helsenorge/designsystem/issues/357838)
40
+
1
41
  ## [12.10.0](https://github.com/helsenorge/designsystem/branchCompare?baseVersion=GTv12.9.0&targetVersion=GTv12.10.0) (2025-10-30)
2
42
 
3
43
  ### Features
package/RadioButton.js CHANGED
@@ -64,6 +64,7 @@ const RadioButton = React__default.forwardRef((props, ref) => {
64
64
  [radioButtonStyles["radio-button-label--on-dark"]]: onDark,
65
65
  [radioButtonStyles["radio-button-label--invalid"]]: invalid,
66
66
  [radioButtonStyles["radio-button-label__large"]]: isLarge,
67
+ [radioButtonStyles["radio-button-label__large--focused"]]: isFocused,
67
68
  [radioButtonStyles["radio-button-label__large--disabled"]]: isLarge && disabled
68
69
  },
69
70
  labelClassNames
@@ -1 +1 @@
1
- {"version":3,"file":"RadioButton.js","sources":["../src/components/RadioButton/RadioButton.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, FormOnColor, FormSize } from '../../constants';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport { useUuid } from '../../hooks/useUuid';\nimport { getAriaDescribedBy } from '../../utils/accessibility';\nimport { isMutableRefObject, mergeRefs } from '../../utils/refs';\nimport { uuid } from '../../utils/uuid';\nimport ErrorWrapper, { ErrorWrapperClassNameProps } from '../ErrorWrapper';\nimport { getLabelText, renderLabelAsParent } from '../Label';\n\nimport radioButtonStyles from './styles.module.scss';\n\nexport interface RadioButtonProps\n extends ErrorWrapperClassNameProps,\n Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'aria-describedby' | 'name' | 'value' | 'disabled' | 'checked' | 'defaultChecked' | 'required' | 'onChange'\n > {\n /** Adds custom classes to the element. */\n className?: string;\n /** The <Label/> next to the radioButton - sublabels kan ikke kombineres med large variant */\n label: React.ReactNode;\n /** Adds custom classes to the label element. */\n labelClassNames?: string;\n /** input id of the radioButton */\n inputId?: string;\n /** Changes the visuals of the radioButton */\n onColor?: keyof typeof FormOnColor;\n /** Changes the visuals of the radioButton. Large version only works when used inside a FormGroup wrapper. */\n size?: keyof typeof FormSize;\n /** Activates Error style for the radioButton - This is can be true while errorText is empty, when in a FormGroup */\n error?: boolean;\n /** Error text to show above the component */\n errorText?: string;\n /** Error text id */\n errorTextId?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const getRadioLabelClasses = (\n radioId: string,\n onColor: FormOnColor,\n large: boolean,\n checkedRadioId?: string\n): string | undefined => {\n const onCherry = onColor === 'oninvalid';\n const checked = radioId === checkedRadioId;\n\n return classNames({\n [radioButtonStyles['radio-button-label__large--on-grey']]: large && onColor === 'ongrey' && !checked,\n [radioButtonStyles['radio-button-label__large--on-blueberry']]: onColor === 'onblueberry' && !checked && large,\n [radioButtonStyles['radio-button-label__large--selected']]: large && checked && !onCherry,\n [radioButtonStyles['radio-button-label__large--selected-invalid']]: large && checked && onCherry,\n });\n};\n\nexport const RadioButton = React.forwardRef((props: RadioButtonProps, ref: React.Ref<HTMLInputElement>) => {\n const {\n className,\n defaultChecked,\n onChange,\n disabled,\n label,\n inputId = uuid(),\n onColor = FormOnColor.onwhite,\n name = inputId,\n size,\n errorText,\n error = !!errorText,\n errorTextId,\n errorWrapperClassName,\n value = getLabelText(label),\n testId,\n required,\n labelClassNames,\n ...rest\n } = props;\n const invalid = error || onColor === FormOnColor.oninvalid;\n const onDark = onColor === FormOnColor.ondark;\n const onBlueberry = onColor === FormOnColor.onblueberry;\n const onCherry = onColor === FormOnColor.oninvalid;\n const isLarge = size === FormSize.large;\n const [checked, changeChecked] = useState<boolean>();\n const { refObject, isFocused } = usePseudoClasses<HTMLInputElement>(isMutableRefObject(ref) ? ref : null);\n const mergedRefs = mergeRefs([ref, refObject]);\n const errorTextUuid = useUuid(errorTextId);\n\n const radioButtonWrapperClasses = classNames(radioButtonStyles['radio-button-wrapper'], {\n [radioButtonStyles['radio-button-wrapper__large']]: isLarge,\n [radioButtonStyles['radio-button-wrapper__large--focused']]: isLarge && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--selected']]: isLarge && checked && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--invalid']]: isLarge && onCherry && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--on-blueberry']]: isLarge && onBlueberry && isFocused,\n });\n const radioButtonLabelClasses = classNames(\n radioButtonStyles['radio-button-label'],\n {\n [radioButtonStyles['radio-button-label--disabled']]: disabled,\n [radioButtonStyles['radio-button-label--on-dark']]: onDark,\n [radioButtonStyles['radio-button-label--invalid']]: invalid,\n [radioButtonStyles['radio-button-label__large']]: isLarge,\n [radioButtonStyles['radio-button-label__large--disabled']]: isLarge && disabled,\n },\n labelClassNames\n );\n const radioButtonClasses = classNames(\n radioButtonStyles['radio-button'],\n {\n [radioButtonStyles['radio-button--on-dark']]: onDark,\n [radioButtonStyles['radio-button--disabled']]: disabled,\n [radioButtonStyles['radio-button--on-blueberry']]: onBlueberry,\n [radioButtonStyles['radio-button--invalid']]: invalid,\n [radioButtonStyles['radio-button__large']]: isLarge,\n [radioButtonStyles['radio-button__large--disabled']]: isLarge && disabled,\n [radioButtonStyles['radio-button__large--invalid']]: isLarge && invalid,\n },\n className\n );\n\n const change = (e: React.ChangeEvent<HTMLInputElement>): void => {\n changeChecked(e.target.checked);\n if (onChange) onChange(e);\n };\n\n const getLabelContent = (): React.ReactNode => (\n <input\n {...rest}\n id={inputId}\n name={name}\n className={radioButtonClasses}\n type=\"radio\"\n disabled={disabled}\n value={value}\n ref={mergedRefs}\n defaultChecked={defaultChecked}\n aria-describedby={getAriaDescribedBy(props, errorTextUuid)}\n required={required}\n onChange={(e): void => change(e)}\n />\n );\n\n return (\n <ErrorWrapper className={errorWrapperClassName} errorText={errorText} errorTextId={errorTextUuid}>\n <div data-testid={testId} data-analyticsid={AnalyticsId.RadioButton} className={radioButtonWrapperClasses}>\n {renderLabelAsParent(\n label,\n getLabelContent(),\n inputId,\n onColor as FormOnColor,\n radioButtonLabelClasses,\n undefined,\n radioButtonStyles['radiobutton-sublabel-wrapper'],\n isLarge\n )}\n </div>\n </ErrorWrapper>\n );\n});\n\nRadioButton.displayName = 'RadioButton';\n\nexport default RadioButton;\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"RadioButton.js","sources":["../src/components/RadioButton/RadioButton.tsx"],"sourcesContent":["import React, { useState } from 'react';\n\nimport classNames from 'classnames';\n\nimport { AnalyticsId, FormOnColor, FormSize } from '../../constants';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport { useUuid } from '../../hooks/useUuid';\nimport { getAriaDescribedBy } from '../../utils/accessibility';\nimport { isMutableRefObject, mergeRefs } from '../../utils/refs';\nimport { uuid } from '../../utils/uuid';\nimport ErrorWrapper, { ErrorWrapperClassNameProps } from '../ErrorWrapper';\nimport { getLabelText, renderLabelAsParent } from '../Label';\n\nimport radioButtonStyles from './styles.module.scss';\n\nexport interface RadioButtonProps\n extends ErrorWrapperClassNameProps,\n Pick<\n React.InputHTMLAttributes<HTMLInputElement>,\n 'aria-describedby' | 'name' | 'value' | 'disabled' | 'checked' | 'defaultChecked' | 'required' | 'onChange'\n > {\n /** Adds custom classes to the element. */\n className?: string;\n /** The <Label/> next to the radioButton - sublabels kan ikke kombineres med large variant */\n label: React.ReactNode;\n /** Adds custom classes to the label element. */\n labelClassNames?: string;\n /** input id of the radioButton */\n inputId?: string;\n /** Changes the visuals of the radioButton */\n onColor?: keyof typeof FormOnColor;\n /** Changes the visuals of the radioButton. Large version only works when used inside a FormGroup wrapper. */\n size?: keyof typeof FormSize;\n /** Activates Error style for the radioButton - This is can be true while errorText is empty, when in a FormGroup */\n error?: boolean;\n /** Error text to show above the component */\n errorText?: string;\n /** Error text id */\n errorTextId?: string;\n /** Sets the data-testid attribute. */\n testId?: string;\n}\n\nexport const getRadioLabelClasses = (\n radioId: string,\n onColor: FormOnColor,\n large: boolean,\n checkedRadioId?: string\n): string | undefined => {\n const onCherry = onColor === 'oninvalid';\n const checked = radioId === checkedRadioId;\n\n return classNames({\n [radioButtonStyles['radio-button-label__large--on-grey']]: large && onColor === 'ongrey' && !checked,\n [radioButtonStyles['radio-button-label__large--on-blueberry']]: onColor === 'onblueberry' && !checked && large,\n [radioButtonStyles['radio-button-label__large--selected']]: large && checked && !onCherry,\n [radioButtonStyles['radio-button-label__large--selected-invalid']]: large && checked && onCherry,\n });\n};\n\nexport const RadioButton = React.forwardRef((props: RadioButtonProps, ref: React.Ref<HTMLInputElement>) => {\n const {\n className,\n defaultChecked,\n onChange,\n disabled,\n label,\n inputId = uuid(),\n onColor = FormOnColor.onwhite,\n name = inputId,\n size,\n errorText,\n error = !!errorText,\n errorTextId,\n errorWrapperClassName,\n value = getLabelText(label),\n testId,\n required,\n labelClassNames,\n ...rest\n } = props;\n const invalid = error || onColor === FormOnColor.oninvalid;\n const onDark = onColor === FormOnColor.ondark;\n const onBlueberry = onColor === FormOnColor.onblueberry;\n const onCherry = onColor === FormOnColor.oninvalid;\n const isLarge = size === FormSize.large;\n const [checked, changeChecked] = useState<boolean>();\n const { refObject, isFocused } = usePseudoClasses<HTMLInputElement>(isMutableRefObject(ref) ? ref : null);\n const mergedRefs = mergeRefs([ref, refObject]);\n const errorTextUuid = useUuid(errorTextId);\n\n const radioButtonWrapperClasses = classNames(radioButtonStyles['radio-button-wrapper'], {\n [radioButtonStyles['radio-button-wrapper__large']]: isLarge,\n [radioButtonStyles['radio-button-wrapper__large--focused']]: isLarge && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--selected']]: isLarge && checked && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--invalid']]: isLarge && onCherry && isFocused,\n [radioButtonStyles['radio-button-wrapper__large--on-blueberry']]: isLarge && onBlueberry && isFocused,\n });\n const radioButtonLabelClasses = classNames(\n radioButtonStyles['radio-button-label'],\n {\n [radioButtonStyles['radio-button-label--disabled']]: disabled,\n [radioButtonStyles['radio-button-label--on-dark']]: onDark,\n [radioButtonStyles['radio-button-label--invalid']]: invalid,\n [radioButtonStyles['radio-button-label__large']]: isLarge,\n [radioButtonStyles['radio-button-label__large--focused']]: isFocused,\n [radioButtonStyles['radio-button-label__large--disabled']]: isLarge && disabled,\n },\n labelClassNames\n );\n const radioButtonClasses = classNames(\n radioButtonStyles['radio-button'],\n {\n [radioButtonStyles['radio-button--on-dark']]: onDark,\n [radioButtonStyles['radio-button--disabled']]: disabled,\n [radioButtonStyles['radio-button--on-blueberry']]: onBlueberry,\n [radioButtonStyles['radio-button--invalid']]: invalid,\n [radioButtonStyles['radio-button__large']]: isLarge,\n [radioButtonStyles['radio-button__large--disabled']]: isLarge && disabled,\n [radioButtonStyles['radio-button__large--invalid']]: isLarge && invalid,\n },\n className\n );\n\n const change = (e: React.ChangeEvent<HTMLInputElement>): void => {\n changeChecked(e.target.checked);\n if (onChange) onChange(e);\n };\n\n const getLabelContent = (): React.ReactNode => (\n <input\n {...rest}\n id={inputId}\n name={name}\n className={radioButtonClasses}\n type=\"radio\"\n disabled={disabled}\n value={value}\n ref={mergedRefs}\n defaultChecked={defaultChecked}\n aria-describedby={getAriaDescribedBy(props, errorTextUuid)}\n required={required}\n onChange={(e): void => change(e)}\n />\n );\n\n return (\n <ErrorWrapper className={errorWrapperClassName} errorText={errorText} errorTextId={errorTextUuid}>\n <div data-testid={testId} data-analyticsid={AnalyticsId.RadioButton} className={radioButtonWrapperClasses}>\n {renderLabelAsParent(\n label,\n getLabelContent(),\n inputId,\n onColor as FormOnColor,\n radioButtonLabelClasses,\n undefined,\n radioButtonStyles['radiobutton-sublabel-wrapper'],\n isLarge\n )}\n </div>\n </ErrorWrapper>\n );\n});\n\nRadioButton.displayName = 'RadioButton';\n\nexport default RadioButton;\n"],"names":["React"],"mappings":"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"}
package/Toast.js CHANGED
@@ -1,21 +1,40 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
+ import classNames from "classnames";
3
+ import { useIsMobileBreakpoint } from "./hooks/useIsMobileBreakpoint.js";
2
4
  import { C as Close } from "./Close.js";
3
5
  import { I as Icon } from "./Icon.js";
6
+ import { IconSize } from "./constants.js";
4
7
  import CheckFill from "./components/Icons/CheckFill.js";
5
8
  import styles from "./components/Toast/styles.module.scss";
6
9
  const Toast = ({ testId, title, message, onClose }) => {
10
+ const isMobile = useIsMobileBreakpoint();
7
11
  const handleClose = () => {
8
12
  if (onClose) {
9
13
  onClose();
10
14
  }
11
15
  };
12
16
  return /* @__PURE__ */ jsxs("output", { className: styles["toast"], "data-testid": testId, children: [
13
- /* @__PURE__ */ jsx(Icon, { svgIcon: CheckFill, className: styles["toast__icon"] }),
17
+ /* @__PURE__ */ jsx(
18
+ Icon,
19
+ {
20
+ size: isMobile ? IconSize.XSmall : IconSize.Small,
21
+ svgIcon: CheckFill,
22
+ className: classNames(styles["toast__icon"], styles["toast__icon--check"])
23
+ }
24
+ ),
14
25
  /* @__PURE__ */ jsxs("div", { className: styles["toast__text-container"], children: [
15
26
  /* @__PURE__ */ jsx("span", { className: styles["toast__title"], children: title }),
16
27
  message && /* @__PURE__ */ jsx("span", { className: styles["toast__description"], children: message })
17
28
  ] }),
18
- /* @__PURE__ */ jsx(Close, { onClick: handleClose, color: "black", className: styles["toast__icon"], testId: `${testId}-close` })
29
+ /* @__PURE__ */ jsx(
30
+ Close,
31
+ {
32
+ onClick: handleClose,
33
+ color: "black",
34
+ className: classNames(styles["toast__icon"], styles["toast__icon--close"]),
35
+ testId: `${testId}-close`
36
+ }
37
+ )
19
38
  ] });
20
39
  };
21
40
  export {
package/Toast.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","sources":["../src/components/Toast/Toast.tsx"],"sourcesContent":["import React from 'react';\n\nimport Close from '../Close';\nimport Icon from '../Icon';\nimport CheckFill from '../Icons/CheckFill';\n\nimport styles from './styles.module.scss';\n\nexport interface ToastProps {\n /** Sets the data-testid attribute. */\n testId?: string;\n /** The title to display in the toast */\n title: string;\n /** The message to display in the toast */\n message?: string;\n /** Callback when toast is closed */\n onClose?: () => void;\n}\n\nconst Toast: React.FC<ToastProps> = ({ testId, title, message, onClose }) => {\n const handleClose = (): void => {\n if (onClose) {\n onClose();\n }\n };\n\n return (\n <output className={styles['toast']} data-testid={testId}>\n <Icon svgIcon={CheckFill} className={styles['toast__icon']} />\n <div className={styles['toast__text-container']}>\n <span className={styles['toast__title']}>{title}</span>\n {message && <span className={styles['toast__description']}>{message}</span>}\n </div>\n <Close onClick={handleClose} color=\"black\" className={styles['toast__icon']} testId={`${testId}-close`} />\n </output>\n );\n};\n\nexport default Toast;\n"],"names":[],"mappings":";;;;;AAmBA,MAAM,QAA8B,CAAC,EAAE,QAAQ,OAAO,SAAS,cAAc;AAC3E,QAAM,cAAc,MAAY;AAC9B,QAAI,SAAS;AACX,cAAA;AAAA,IACF;AAAA,EACF;AAEA,8BACG,UAAA,EAAO,WAAW,OAAO,OAAO,GAAG,eAAa,QAC/C,UAAA;AAAA,IAAA,oBAAC,QAAK,SAAS,WAAW,WAAW,OAAO,aAAa,GAAG;AAAA,IAC5D,qBAAC,OAAA,EAAI,WAAW,OAAO,uBAAuB,GAC5C,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAW,OAAO,cAAc,GAAI,UAAA,OAAM;AAAA,MAC/C,WAAW,oBAAC,QAAA,EAAK,WAAW,OAAO,oBAAoB,GAAI,UAAA,QAAA,CAAQ;AAAA,IAAA,GACtE;AAAA,IACA,oBAAC,OAAA,EAAM,SAAS,aAAa,OAAM,SAAQ,WAAW,OAAO,aAAa,GAAG,QAAQ,GAAG,MAAM,SAAA,CAAU;AAAA,EAAA,GAC1G;AAEJ;"}
1
+ {"version":3,"file":"Toast.js","sources":["../src/components/Toast/Toast.tsx"],"sourcesContent":["import React from 'react';\n\nimport classNames from 'classnames';\n\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport Close from '../Close';\nimport Icon, { IconSize } from '../Icon';\nimport CheckFill from '../Icons/CheckFill';\n\nimport styles from './styles.module.scss';\n\nexport interface ToastProps {\n /** Sets the data-testid attribute. */\n testId?: string;\n /** The title to display in the toast */\n title: string;\n /** The message to display in the toast */\n message?: string;\n /** Callback when toast is closed */\n onClose?: () => void;\n}\n\nconst Toast: React.FC<ToastProps> = ({ testId, title, message, onClose }) => {\n const isMobile = useIsMobileBreakpoint();\n\n const handleClose = (): void => {\n if (onClose) {\n onClose();\n }\n };\n\n return (\n <output className={styles['toast']} data-testid={testId}>\n <Icon\n size={isMobile ? IconSize.XSmall : IconSize.Small}\n svgIcon={CheckFill}\n className={classNames(styles['toast__icon'], styles['toast__icon--check'])}\n />\n <div className={styles['toast__text-container']}>\n <span className={styles['toast__title']}>{title}</span>\n {message && <span className={styles['toast__description']}>{message}</span>}\n </div>\n <Close\n onClick={handleClose}\n color=\"black\"\n className={classNames(styles['toast__icon'], styles['toast__icon--close'])}\n testId={`${testId}-close`}\n />\n </output>\n );\n};\n\nexport default Toast;\n"],"names":[],"mappings":";;;;;;;;AAsBA,MAAM,QAA8B,CAAC,EAAE,QAAQ,OAAO,SAAS,cAAc;AAC3E,QAAM,WAAW,sBAAA;AAEjB,QAAM,cAAc,MAAY;AAC9B,QAAI,SAAS;AACX,cAAA;AAAA,IACF;AAAA,EACF;AAEA,8BACG,UAAA,EAAO,WAAW,OAAO,OAAO,GAAG,eAAa,QAC/C,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM,WAAW,SAAS,SAAS,SAAS;AAAA,QAC5C,SAAS;AAAA,QACT,WAAW,WAAW,OAAO,aAAa,GAAG,OAAO,oBAAoB,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,IAE3E,qBAAC,OAAA,EAAI,WAAW,OAAO,uBAAuB,GAC5C,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAW,OAAO,cAAc,GAAI,UAAA,OAAM;AAAA,MAC/C,WAAW,oBAAC,QAAA,EAAK,WAAW,OAAO,oBAAoB,GAAI,UAAA,QAAA,CAAQ;AAAA,IAAA,GACtE;AAAA,IACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAAS;AAAA,QACT,OAAM;AAAA,QACN,WAAW,WAAW,OAAO,aAAa,GAAG,OAAO,oBAAoB,CAAC;AAAA,QACzE,QAAQ,GAAG,MAAM;AAAA,MAAA;AAAA,IAAA;AAAA,EACnB,GACF;AAEJ;"}
@@ -39,12 +39,24 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
39
39
  @include text-color(var(--color-action-text-onlight-hover), var(--color-action-text-onlight-hover));
40
40
  }
41
41
 
42
- @mixin focus-shadow {
42
+ @mixin focus-shadow($with-uu-border: true) {
43
43
  box-shadow: 0 0 0 spacers.getSpacer(3xs) palette.$black;
44
+
45
+ @if $with-uu-border {
46
+ border: 1px solid var(--color-action-border-ondark-focus);
47
+ } @else {
48
+ border: none;
49
+ }
44
50
  }
45
51
 
46
- @mixin focus-shadow-on-dark {
52
+ @mixin focus-shadow-on-dark($with-uu-border: true) {
47
53
  box-shadow: 0 0 0 spacers.getSpacer(3xs) palette.$white;
54
+
55
+ @if $with-uu-border {
56
+ border: 1px solid var(--color-action-border-onlight-focus);
57
+ } @else {
58
+ border: none;
59
+ }
48
60
  }
49
61
 
50
62
  @mixin outline-borderless-background($background-color, $hover-background-color) {
@@ -102,16 +114,6 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
102
114
  background-color: $background-color;
103
115
  }
104
116
 
105
- :focus > & {
106
- @include focus-shadow-on-dark;
107
-
108
- &:hover {
109
- @include focus-shadow-on-dark;
110
-
111
- background-color: palette.$white;
112
- }
113
- }
114
-
115
117
  /* stylelint-disable-next-line */
116
118
  :disabled > & {
117
119
  background-color: $dark-mode-disabled-transparrent;
@@ -129,6 +131,16 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
129
131
  @mixin on-dark {
130
132
  &--on-dark {
131
133
  @include fill-on-dark(var(--color-action-background-ondark-hover));
134
+
135
+ :focus > & {
136
+ @include focus-shadow-on-dark(true);
137
+
138
+ &:hover {
139
+ @include focus-shadow-on-dark(true);
140
+
141
+ background-color: palette.$white;
142
+ }
143
+ }
132
144
  }
133
145
  &--on-dark#{&}--destructive {
134
146
  @include fill-on-dark(palette.$cherry50);
@@ -139,8 +151,14 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
139
151
  &--on-dark#{&}--borderless#{&}--destructive {
140
152
  background-color: transparent;
141
153
 
142
- &:hover {
143
- background-color: palette.$inverted-hover;
154
+ :focus > & {
155
+ @include focus-shadow-on-dark(false);
156
+
157
+ &:hover {
158
+ @include focus-shadow-on-dark(false);
159
+
160
+ background-color: palette.$inverted-hover;
161
+ }
144
162
  }
145
163
  }
146
164
  &--on-dark#{&}--outline {
@@ -285,9 +303,25 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
285
303
  }
286
304
  }
287
305
 
306
+ :focus > & {
307
+ @include focus-shadow;
308
+
309
+ &:hover {
310
+ @include focus-shadow;
311
+ }
312
+ }
313
+
288
314
  &--outline,
289
315
  &--borderless {
290
316
  @include outline-borderless-background(transparent, var(--color-action-background-transparent-onlight-hover));
317
+
318
+ :focus > & {
319
+ @include focus-shadow(false);
320
+
321
+ &:hover {
322
+ @include focus-shadow(false);
323
+ }
324
+ }
291
325
  }
292
326
  &--outline#{&}--destructive,
293
327
  &--borderless#{&}--destructive {
@@ -301,12 +335,6 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
301
335
  @include outline(palette.$cherry700, palette.$cherry50);
302
336
  }
303
337
 
304
- /* stylelint-disable-next-line */
305
- &--borderless:not(.button--only-icon) {
306
- padding: 0 spacers.getSpacer(3xs);
307
- }
308
-
309
- /* stylelint-disable-next-line */
310
338
  &--borderless {
311
339
  border-radius: 0;
312
340
 
@@ -319,11 +347,15 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
319
347
  }
320
348
  }
321
349
 
322
- :focus > & {
323
- @include focus-shadow;
350
+ &--borderless:not(.button--only-icon) {
351
+ padding: 0 spacers.getSpacer(2xs);
324
352
 
325
- &:hover {
326
- @include focus-shadow;
353
+ &:has(.button__left-icon) {
354
+ padding-left: 0;
355
+ }
356
+
357
+ &:has(.button__right-icon) {
358
+ padding-right: 0;
327
359
  }
328
360
  }
329
361
 
@@ -335,9 +367,12 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
335
367
  display: flex;
336
368
  align-items: center;
337
369
  justify-content: center;
370
+ text-align: left;
371
+ padding: 0.4375rem 0;
338
372
 
339
373
  @media (min-width: map.get(breakpoints.$grid-breakpoints, md)) {
340
374
  margin: 0 auto 0 0;
375
+ padding: 0.625rem 0;
341
376
  }
342
377
 
343
378
  &--ellipsis {
@@ -410,8 +410,17 @@ $padding-clickable-area-left: 8px;
410
410
  box-shadow: 0 0 0 spacers.getSpacer(3xs);
411
411
  color: palette.$black;
412
412
 
413
+ &__regular--checked {
414
+ border: 1px solid var(--color-action-border-ondark-focus);
415
+
416
+ & + .checkbox__icon-wrapper__regular--on-dark {
417
+ border: 1px solid var(--color-action-border-onlight-focus);
418
+ }
419
+ }
420
+
413
421
  &--on-dark {
414
422
  color: palette.$white;
423
+ border: 1px solid var(--color-action-border-onlight-focus);
415
424
  }
416
425
 
417
426
  &--invalid {
@@ -423,11 +432,13 @@ $padding-clickable-area-left: 8px;
423
432
  background-color: palette.$blueberry200;
424
433
  box-shadow: 0 0 0 spacers.getSpacer(3xs);
425
434
  color: palette.$white;
435
+ border: 1px solid var(--color-action-border-onlight-focus);
426
436
 
427
437
  // komboklasser fungerer ikke i nested struktur
428
438
  &--invalid {
429
439
  background-color: palette.$cherry500;
430
440
  color: palette.$black;
441
+ border: 1px solid var(--color-action-border-ondark-focus);
431
442
  }
432
443
 
433
444
  &--disabled {
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import React__default, { useRef, useId, useEffect } from "react";
3
- import { u as useFloating, f as autoUpdate, o as offset, s as shift, j as size } from "../../floating-ui.react.js";
3
+ import { u as useFloating, f as autoUpdate, o as offset, g as flip, s as shift, j as size } from "../../floating-ui.react.js";
4
4
  import classNames from "classnames";
5
5
  import "../../theme/grid.js";
6
6
  import "../../hooks/useBreakpoint.js";
@@ -60,6 +60,7 @@ const DropdownBase = (props) => {
60
60
  const isMobile = useIsMobileBreakpoint();
61
61
  const triggerActualMinWidth = variant !== "borderless" && typeof triggerMinWidth != "undefined" ? `${triggerMinWidth}px` : "auto";
62
62
  const triggerMinWidthLimit = isMobile ? 96 : 112;
63
+ const dropdownFloatingPadding = 15;
63
64
  const maxWidth = isMobile ? 384 : 400;
64
65
  const toggleTextId = useId();
65
66
  const optionIdPrefix = useId();
@@ -90,18 +91,23 @@ const DropdownBase = (props) => {
90
91
  const contentClasses = classNames(styles.dropdown__content, isOpen && styles["dropdown__content--open"]);
91
92
  const listItemClasses = classNames(styles["dropdown__list-item"], { [styles["dropdown__list-item--single-select"]]: isSingleSelect });
92
93
  const { refs, floatingStyles } = useFloating({
93
- placement: "bottom",
94
+ strategy: "fixed",
95
+ placement: "bottom-start",
94
96
  middleware: [
95
97
  offset(8),
96
- shift({ padding: 8 }),
98
+ // Hvis det ikke er plass på høyre side flipper vi dropdownlisten fra bottom-start til bottom-end
99
+ flip({ mainAxis: false, fallbackPlacements: ["bottom-end"], padding: dropdownFloatingPadding }),
100
+ // Shift fungerer som en fallback for flip og unngår at availableWidth ikke oppdaterer seg ved skjermbreddeendring
101
+ shift({ padding: dropdownFloatingPadding }),
102
+ // Hvis det ikke er plass på noen av sidene krymper vi bredden på listen med size
97
103
  size({
104
+ padding: dropdownFloatingPadding,
98
105
  apply({ availableWidth, availableHeight, elements, rects }) {
99
106
  const triggerW = rects.reference.width;
100
107
  const minProp = typeof dropdownMinWidth !== "undefined" ? clamp(0, maxWidth, dropdownMinWidth) : 0;
101
108
  const targetW = Math.max(triggerW, minProp);
102
- const finalW = Math.min(availableWidth, targetW);
103
109
  Object.assign(elements.floating.style, {
104
- width: `${finalW}px`,
110
+ maxWidth: `${Math.min(targetW, availableWidth)}px`,
105
111
  maxHeight: `${availableHeight}px`,
106
112
  overflowY: "auto",
107
113
  overflowX: "hidden"
@@ -109,7 +115,7 @@ const DropdownBase = (props) => {
109
115
  }
110
116
  })
111
117
  ],
112
- whileElementsMounted: autoUpdate
118
+ whileElementsMounted: isOpen ? autoUpdate : void 0
113
119
  });
114
120
  const handleOpen = (isKeyboard) => {
115
121
  openedByKeyboard.current = isKeyboard;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/Dropdown/resourceHelper.ts","../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["import { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Dropdown.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Dropdown.nb-NO.json';\nimport { HNDesignsystemDropdown } from '../../resources/Resources';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemDropdown => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import React, { useEffect, useRef, useId, ComponentType } from 'react';\n\nimport { autoUpdate, offset, shift, size, useFloating } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport { clamp } from 'motion/react';\n\nimport {\n AnalyticsId,\n IconSize,\n KeyboardEventKey,\n LanguageLocales,\n ZIndex,\n usePseudoClasses,\n useKeyboardEvent,\n useOutsideEvent,\n useToggle,\n} from '../..';\nimport { getResources } from './resourceHelper';\nimport { SingleSelectItem, SingleSelectItemProps } from './SingleSelect/SingleSelectItem';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { HNDesignsystemDropdown } from '../../resources/Resources';\nimport { isComponent } from '../../utils/component';\nimport { useLanguage } from '../../utils/language';\nimport { mergeRefs } from '../../utils/refs';\nimport Button from '../Button';\nimport Checkbox, { CheckboxProps } from '../Checkbox';\nimport Icon, { SvgIcon } from '../Icon';\nimport ChevronDown from '../Icons/ChevronDown';\nimport ChevronUp from '../Icons/ChevronUp';\nimport { IconName } from '../Icons/IconNames';\nimport PlusSmall from '../Icons/PlusSmall';\nimport Label, { LabelProps } from '../Label';\nimport LazyIcon from '../LazyIcon';\nimport { SingleSelect } from './SingleSelect/SingleSelect';\n\nimport styles from './styles.module.scss';\n\ntype DropdownVariants = 'fill' | 'transparent' | 'borderless';\n\nexport interface DropdownProps {\n /** Text on the trigger button that opens the dropdown */\n triggerText: string;\n /** Sets the dropdown content */\n children: React.ReactNode;\n /** Minimum width for the dropdown in pixels. Does not affect trigger button. */\n dropdownMinWidth?: number;\n /** Minimum width for the trigger in pixels. Does not apply for borderless variant */\n triggerMinWidth?: number;\n /** Disables rendring of the close button in the list */\n noCloseButton?: boolean;\n /** Called when dropdown is open/closed */\n onToggle?: (isOpen: boolean) => void;\n /** Whether the dropdown is open or not */\n open?: boolean;\n /** Makes the dropdown disabled */\n disabled?: boolean;\n /** Sets the data-testid attribute on the dropdown button */\n testId?: string;\n /** Overrides the default z-index of the DropDownContent */\n zIndex?: number;\n /** Resources for component */\n resources?: Partial<HNDesignsystemDropdown>;\n /** Adds an icon to the trigger */\n svgIcon?: SvgIcon | IconName;\n /** Sets the visual variant of the Dropdown */\n variant?: DropdownVariants;\n}\n\nexport const DropdownBase: React.FC<DropdownProps> = props => {\n const {\n triggerText,\n noCloseButton = false,\n onToggle,\n dropdownMinWidth,\n triggerMinWidth,\n open = false,\n children,\n testId,\n disabled,\n zIndex = ZIndex.PopOver,\n resources,\n svgIcon,\n variant = 'fill',\n } = props;\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n const optionsRef = useRef<HTMLUListElement>(null);\n const childrenRefList = useRef(React.Children.map(children, () => React.createRef<HTMLElement>()));\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const { isHovered } = usePseudoClasses<HTMLButtonElement>(buttonRef);\n const openedByKeyboard = useRef<boolean>(false);\n const { value: isOpen, toggleValue: toggleIsOpen } = useToggle(!disabled && open, onToggle);\n const isMobile = useIsMobileBreakpoint();\n const triggerActualMinWidth = variant !== 'borderless' && typeof triggerMinWidth != 'undefined' ? `${triggerMinWidth}px` : 'auto';\n const triggerMinWidthLimit = isMobile ? 96 : 112;\n const maxWidth = isMobile ? 384 : 400;\n const toggleTextId = useId();\n const optionIdPrefix = useId();\n const contentId = useId();\n const leftIconProps = {\n className: styles['dropdown__left-icon'],\n size: IconSize.XSmall,\n isHovered: !disabled && isHovered,\n };\n\n const isSingleSelect = React.Children.toArray(children).every(\n child => React.isValidElement(child) && isComponent<SingleSelectItemProps>(child, SingleSelectItem)\n );\n const isMultiSelect = React.Children.toArray(children).every(\n child => React.isValidElement(child) && isComponent<CheckboxProps>(child, Checkbox)\n );\n\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n const mergedResources: HNDesignsystemDropdown = {\n ...defaultResources,\n ...resources,\n };\n\n const toggleClasses = classNames(styles.dropdown__toggle, {\n [styles['dropdown__toggle--open']]: isOpen && !disabled,\n [styles['dropdown__toggle--with-icon']]: typeof svgIcon !== 'undefined',\n [styles['dropdown__toggle--transparent']]: variant === 'transparent',\n [styles['dropdown__toggle--borderless']]: variant === 'borderless',\n });\n const contentClasses = classNames(styles.dropdown__content, isOpen && styles['dropdown__content--open']);\n const listItemClasses = classNames(styles['dropdown__list-item'], { [styles['dropdown__list-item--single-select']]: isSingleSelect });\n\n const { refs, floatingStyles } = useFloating({\n placement: 'bottom',\n middleware: [\n offset(8),\n shift({ padding: 8 }),\n size({\n apply({ availableWidth, availableHeight, elements, rects }) {\n const triggerW = rects.reference.width;\n const minProp = typeof dropdownMinWidth !== 'undefined' ? clamp(0, maxWidth, dropdownMinWidth) : 0;\n const targetW = Math.max(triggerW, minProp);\n const finalW = Math.min(availableWidth, targetW);\n\n Object.assign(elements.floating.style, {\n width: `${finalW}px`,\n maxHeight: `${availableHeight}px`,\n overflowY: 'auto',\n overflowX: 'hidden',\n });\n },\n }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const handleOpen = (isKeyboard: boolean): void => {\n openedByKeyboard.current = isKeyboard;\n toggleIsOpen();\n };\n\n const handleClose = (): void => {\n if (!isOpen) return;\n\n toggleIsOpen();\n buttonRef.current?.focus();\n };\n\n useEffect(() => {\n if (isOpen && openedByKeyboard.current) {\n const firstEnabled = childrenRefList.current?.find(r => r.current && !r.current.hasAttribute('disabled'));\n firstEnabled?.current?.focus();\n openedByKeyboard.current = false;\n }\n }, [isOpen]);\n\n const focusByIndex = (nextIndex: number): void => {\n childrenRefList.current?.[nextIndex]?.current?.focus();\n };\n\n const isListNavKey = (key: string): boolean =>\n key === KeyboardEventKey.ArrowDown || key === KeyboardEventKey.ArrowUp || key === KeyboardEventKey.Home || key === KeyboardEventKey.End;\n\n const handleKeyboardNavigation = (event: KeyboardEvent): void => {\n if (!childrenRefList.current) return;\n\n const key = event.key as KeyboardEventKey;\n\n if (key === KeyboardEventKey.Escape) {\n if (isOpen) {\n event.preventDefault();\n handleClose();\n }\n return;\n }\n\n if (!isOpen) {\n if (isListNavKey(key)) {\n event.preventDefault();\n handleOpen(true);\n }\n return;\n }\n\n if (!isListNavKey(key)) {\n return;\n }\n\n const index = childrenRefList.current.findIndex(x => x.current === (event.target as HTMLElement));\n let nextIndex = index;\n\n if (key === KeyboardEventKey.Home) {\n nextIndex = 0;\n } else if (key === KeyboardEventKey.End) {\n nextIndex = childrenRefList.current.length - 1;\n } else if (key === KeyboardEventKey.ArrowDown && index < childrenRefList.current.length - 1) {\n nextIndex = index + 1;\n } else if (key === KeyboardEventKey.ArrowUp && index > 0) {\n nextIndex = index - 1;\n }\n\n if (nextIndex !== -1) {\n event.preventDefault();\n focusByIndex(nextIndex);\n }\n };\n\n useKeyboardEvent(dropdownRef, handleKeyboardNavigation, [\n KeyboardEventKey.ArrowDown,\n KeyboardEventKey.ArrowUp,\n KeyboardEventKey.End,\n KeyboardEventKey.Enter,\n KeyboardEventKey.Escape,\n KeyboardEventKey.Home,\n KeyboardEventKey.Space,\n ]);\n\n useOutsideEvent(dropdownRef, () => isOpen && handleClose());\n\n const renderChildren = React.Children.map(children, (child, index) => {\n return (\n <li className={listItemClasses} id={`${optionIdPrefix}-${index}`}>\n {React.isValidElement(child) && childrenRefList.current && childrenRefList.current[index]\n ? ((): React.ReactElement => {\n const baseProps: { ref: React.Ref<HTMLElement> } = {\n ref: mergeRefs([child.props.ref, childrenRefList.current[index]]),\n };\n\n if (isMultiSelect) {\n const label = (child.props as CheckboxProps).label as React.ReactNode;\n if (React.isValidElement(label) && isComponent<LabelProps>(label, Label)) {\n return React.cloneElement(child as React.ReactElement<CheckboxProps>, {\n ...baseProps,\n label: React.cloneElement(label, {\n labelClassName: classNames((label.props as LabelProps)?.labelClassName, styles['dropdown__multiselect-item']),\n }),\n });\n }\n }\n\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, baseProps);\n })()\n : child}\n </li>\n );\n });\n\n return (\n <div className={styles.dropdown} ref={dropdownRef}>\n <button\n type=\"button\"\n onClick={(): false | void => handleOpen(false)}\n className={toggleClasses}\n ref={mergeRefs([buttonRef, refs.setReference])}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Dropdown}\n disabled={disabled}\n aria-labelledby={toggleTextId}\n aria-haspopup={true}\n aria-controls={contentId}\n aria-expanded={isOpen}\n style={{\n width: triggerActualMinWidth,\n maxWidth: '100%',\n minWidth: `${triggerMinWidthLimit}px`,\n }}\n >\n {svgIcon && (\n <>\n {typeof svgIcon === 'string' ? (\n <LazyIcon {...leftIconProps} iconName={svgIcon} />\n ) : (\n <Icon {...leftIconProps} svgIcon={svgIcon} />\n )}\n </>\n )}\n <span id={toggleTextId} className={styles.dropdown__toggle__text}>\n {triggerText}\n </span>\n <Icon\n svgIcon={!isSingleSelect ? PlusSmall : isOpen ? ChevronUp : ChevronDown}\n className={styles['dropdown__right-icon']}\n isHovered={!disabled && isHovered}\n size={IconSize.XSmall}\n />\n </button>\n <div\n key={dropdownMinWidth ?? 'auto'}\n id={contentId}\n className={contentClasses}\n ref={refs.setFloating}\n style={{\n ...floatingStyles,\n zIndex: zIndex,\n }}\n >\n <ul className={styles.dropdown__options} role=\"group\" aria-labelledby={toggleTextId} tabIndex={-1} ref={optionsRef}>\n {isSingleSelect && <SingleSelect onValueChange={() => handleClose()}>{renderChildren}</SingleSelect>}\n {isMultiSelect && renderChildren}\n </ul>\n {!isSingleSelect && !noCloseButton && (\n <div className={styles.dropdown__close}>\n <Button onClick={handleClose}>{mergedResources.closeText}</Button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport interface DropdownCompound extends React.FC<DropdownProps> {\n SingleSelectItem: ComponentType<SingleSelectItemProps>;\n}\nconst Dropdown = DropdownBase as DropdownCompound;\nDropdown.SingleSelectItem = SingleSelectItem;\nDropdownBase.displayName = 'Dropdown';\n\nexport default Dropdown;\n"],"names":["React"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/Dropdown/resourceHelper.ts","../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["import { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Dropdown.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Dropdown.nb-NO.json';\nimport { HNDesignsystemDropdown } from '../../resources/Resources';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemDropdown => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import React, { useEffect, useRef, useId, ComponentType } from 'react';\n\nimport { autoUpdate, offset, shift, size, useFloating, flip } from '@floating-ui/react';\nimport classNames from 'classnames';\nimport { clamp } from 'motion/react';\n\nimport {\n AnalyticsId,\n IconSize,\n KeyboardEventKey,\n LanguageLocales,\n ZIndex,\n usePseudoClasses,\n useKeyboardEvent,\n useOutsideEvent,\n useToggle,\n} from '../..';\nimport { getResources } from './resourceHelper';\nimport { SingleSelectItem, SingleSelectItemProps } from './SingleSelect/SingleSelectItem';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { HNDesignsystemDropdown } from '../../resources/Resources';\nimport { isComponent } from '../../utils/component';\nimport { useLanguage } from '../../utils/language';\nimport { mergeRefs } from '../../utils/refs';\nimport Button from '../Button';\nimport Checkbox, { CheckboxProps } from '../Checkbox';\nimport Icon, { SvgIcon } from '../Icon';\nimport ChevronDown from '../Icons/ChevronDown';\nimport ChevronUp from '../Icons/ChevronUp';\nimport { IconName } from '../Icons/IconNames';\nimport PlusSmall from '../Icons/PlusSmall';\nimport Label, { LabelProps } from '../Label';\nimport LazyIcon from '../LazyIcon';\nimport { SingleSelect } from './SingleSelect/SingleSelect';\n\nimport styles from './styles.module.scss';\n\ntype DropdownVariants = 'fill' | 'transparent' | 'borderless';\n\nexport interface DropdownProps {\n /** Text on the trigger button that opens the dropdown */\n triggerText: string;\n /** Sets the dropdown content */\n children: React.ReactNode;\n /** Minimum width for the dropdown in pixels. Does not affect trigger button. */\n dropdownMinWidth?: number;\n /** Minimum width for the trigger in pixels. Does not apply for borderless variant */\n triggerMinWidth?: number;\n /** Disables rendring of the close button in the list */\n noCloseButton?: boolean;\n /** Called when dropdown is open/closed */\n onToggle?: (isOpen: boolean) => void;\n /** Whether the dropdown is open or not */\n open?: boolean;\n /** Makes the dropdown disabled */\n disabled?: boolean;\n /** Sets the data-testid attribute on the dropdown button */\n testId?: string;\n /** Overrides the default z-index of the DropDownContent */\n zIndex?: number;\n /** Resources for component */\n resources?: Partial<HNDesignsystemDropdown>;\n /** Adds an icon to the trigger */\n svgIcon?: SvgIcon | IconName;\n /** Sets the visual variant of the Dropdown */\n variant?: DropdownVariants;\n}\n\nexport const DropdownBase: React.FC<DropdownProps> = props => {\n const {\n triggerText,\n noCloseButton = false,\n onToggle,\n dropdownMinWidth,\n triggerMinWidth,\n open = false,\n children,\n testId,\n disabled,\n zIndex = ZIndex.PopOver,\n resources,\n svgIcon,\n variant = 'fill',\n } = props;\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n const optionsRef = useRef<HTMLUListElement>(null);\n const childrenRefList = useRef(React.Children.map(children, () => React.createRef<HTMLElement>()));\n const buttonRef = React.useRef<HTMLButtonElement>(null);\n const { isHovered } = usePseudoClasses<HTMLButtonElement>(buttonRef);\n const openedByKeyboard = useRef<boolean>(false);\n const { value: isOpen, toggleValue: toggleIsOpen } = useToggle(!disabled && open, onToggle);\n const isMobile = useIsMobileBreakpoint();\n const triggerActualMinWidth = variant !== 'borderless' && typeof triggerMinWidth != 'undefined' ? `${triggerMinWidth}px` : 'auto';\n const triggerMinWidthLimit = isMobile ? 96 : 112;\n const dropdownFloatingPadding = 15;\n const maxWidth = isMobile ? 384 : 400;\n const toggleTextId = useId();\n const optionIdPrefix = useId();\n const contentId = useId();\n const leftIconProps = {\n className: styles['dropdown__left-icon'],\n size: IconSize.XSmall,\n isHovered: !disabled && isHovered,\n };\n\n const isSingleSelect = React.Children.toArray(children).every(\n child => React.isValidElement(child) && isComponent<SingleSelectItemProps>(child, SingleSelectItem)\n );\n const isMultiSelect = React.Children.toArray(children).every(\n child => React.isValidElement(child) && isComponent<CheckboxProps>(child, Checkbox)\n );\n\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n const mergedResources: HNDesignsystemDropdown = {\n ...defaultResources,\n ...resources,\n };\n\n const toggleClasses = classNames(styles.dropdown__toggle, {\n [styles['dropdown__toggle--open']]: isOpen && !disabled,\n [styles['dropdown__toggle--with-icon']]: typeof svgIcon !== 'undefined',\n [styles['dropdown__toggle--transparent']]: variant === 'transparent',\n [styles['dropdown__toggle--borderless']]: variant === 'borderless',\n });\n const contentClasses = classNames(styles.dropdown__content, isOpen && styles['dropdown__content--open']);\n const listItemClasses = classNames(styles['dropdown__list-item'], { [styles['dropdown__list-item--single-select']]: isSingleSelect });\n\n const { refs, floatingStyles } = useFloating({\n strategy: 'fixed',\n placement: 'bottom-start',\n middleware: [\n offset(8),\n // Hvis det ikke er plass på høyre side flipper vi dropdownlisten fra bottom-start til bottom-end\n flip({ mainAxis: false, fallbackPlacements: ['bottom-end'], padding: dropdownFloatingPadding }),\n // Shift fungerer som en fallback for flip og unngår at availableWidth ikke oppdaterer seg ved skjermbreddeendring\n shift({ padding: dropdownFloatingPadding }),\n // Hvis det ikke er plass på noen av sidene krymper vi bredden på listen med size\n size({\n padding: dropdownFloatingPadding,\n apply({ availableWidth, availableHeight, elements, rects }) {\n const triggerW = rects.reference.width;\n const minProp = typeof dropdownMinWidth !== 'undefined' ? clamp(0, maxWidth, dropdownMinWidth) : 0;\n const targetW = Math.max(triggerW, minProp);\n\n Object.assign(elements.floating.style, {\n maxWidth: `${Math.min(targetW, availableWidth)}px`,\n maxHeight: `${availableHeight}px`,\n overflowY: 'auto',\n overflowX: 'hidden',\n });\n },\n }),\n ],\n whileElementsMounted: isOpen ? autoUpdate : undefined,\n });\n\n const handleOpen = (isKeyboard: boolean): void => {\n openedByKeyboard.current = isKeyboard;\n toggleIsOpen();\n };\n\n const handleClose = (): void => {\n if (!isOpen) return;\n\n toggleIsOpen();\n buttonRef.current?.focus();\n };\n\n useEffect(() => {\n if (isOpen && openedByKeyboard.current) {\n const firstEnabled = childrenRefList.current?.find(r => r.current && !r.current.hasAttribute('disabled'));\n firstEnabled?.current?.focus();\n openedByKeyboard.current = false;\n }\n }, [isOpen]);\n\n const focusByIndex = (nextIndex: number): void => {\n childrenRefList.current?.[nextIndex]?.current?.focus();\n };\n\n const isListNavKey = (key: string): boolean =>\n key === KeyboardEventKey.ArrowDown || key === KeyboardEventKey.ArrowUp || key === KeyboardEventKey.Home || key === KeyboardEventKey.End;\n\n const handleKeyboardNavigation = (event: KeyboardEvent): void => {\n if (!childrenRefList.current) return;\n\n const key = event.key as KeyboardEventKey;\n\n if (key === KeyboardEventKey.Escape) {\n if (isOpen) {\n event.preventDefault();\n handleClose();\n }\n return;\n }\n\n if (!isOpen) {\n if (isListNavKey(key)) {\n event.preventDefault();\n handleOpen(true);\n }\n return;\n }\n\n if (!isListNavKey(key)) {\n return;\n }\n\n const index = childrenRefList.current.findIndex(x => x.current === (event.target as HTMLElement));\n let nextIndex = index;\n\n if (key === KeyboardEventKey.Home) {\n nextIndex = 0;\n } else if (key === KeyboardEventKey.End) {\n nextIndex = childrenRefList.current.length - 1;\n } else if (key === KeyboardEventKey.ArrowDown && index < childrenRefList.current.length - 1) {\n nextIndex = index + 1;\n } else if (key === KeyboardEventKey.ArrowUp && index > 0) {\n nextIndex = index - 1;\n }\n\n if (nextIndex !== -1) {\n event.preventDefault();\n focusByIndex(nextIndex);\n }\n };\n\n useKeyboardEvent(dropdownRef, handleKeyboardNavigation, [\n KeyboardEventKey.ArrowDown,\n KeyboardEventKey.ArrowUp,\n KeyboardEventKey.End,\n KeyboardEventKey.Enter,\n KeyboardEventKey.Escape,\n KeyboardEventKey.Home,\n KeyboardEventKey.Space,\n ]);\n\n useOutsideEvent(dropdownRef, () => isOpen && handleClose());\n\n const renderChildren = React.Children.map(children, (child, index) => {\n return (\n <li className={listItemClasses} id={`${optionIdPrefix}-${index}`}>\n {React.isValidElement(child) && childrenRefList.current && childrenRefList.current[index]\n ? ((): React.ReactElement => {\n const baseProps: { ref: React.Ref<HTMLElement> } = {\n ref: mergeRefs([child.props.ref, childrenRefList.current[index]]),\n };\n\n if (isMultiSelect) {\n const label = (child.props as CheckboxProps).label as React.ReactNode;\n if (React.isValidElement(label) && isComponent<LabelProps>(label, Label)) {\n return React.cloneElement(child as React.ReactElement<CheckboxProps>, {\n ...baseProps,\n label: React.cloneElement(label, {\n labelClassName: classNames((label.props as LabelProps)?.labelClassName, styles['dropdown__multiselect-item']),\n }),\n });\n }\n }\n\n return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, baseProps);\n })()\n : child}\n </li>\n );\n });\n\n return (\n <div className={styles.dropdown} ref={dropdownRef}>\n <button\n type=\"button\"\n onClick={(): false | void => handleOpen(false)}\n className={toggleClasses}\n ref={mergeRefs([buttonRef, refs.setReference])}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Dropdown}\n disabled={disabled}\n aria-labelledby={toggleTextId}\n aria-haspopup={true}\n aria-controls={contentId}\n aria-expanded={isOpen}\n style={{\n width: triggerActualMinWidth,\n maxWidth: '100%',\n minWidth: `${triggerMinWidthLimit}px`,\n }}\n >\n {svgIcon && (\n <>\n {typeof svgIcon === 'string' ? (\n <LazyIcon {...leftIconProps} iconName={svgIcon} />\n ) : (\n <Icon {...leftIconProps} svgIcon={svgIcon} />\n )}\n </>\n )}\n <span id={toggleTextId} className={styles.dropdown__toggle__text}>\n {triggerText}\n </span>\n <Icon\n svgIcon={!isSingleSelect ? PlusSmall : isOpen ? ChevronUp : ChevronDown}\n className={styles['dropdown__right-icon']}\n isHovered={!disabled && isHovered}\n size={IconSize.XSmall}\n />\n </button>\n <div\n key={dropdownMinWidth ?? 'auto'}\n id={contentId}\n className={contentClasses}\n ref={refs.setFloating}\n style={{\n ...floatingStyles,\n zIndex: zIndex,\n }}\n >\n <ul className={styles.dropdown__options} role=\"group\" aria-labelledby={toggleTextId} tabIndex={-1} ref={optionsRef}>\n {isSingleSelect && <SingleSelect onValueChange={() => handleClose()}>{renderChildren}</SingleSelect>}\n {isMultiSelect && renderChildren}\n </ul>\n {!isSingleSelect && !noCloseButton && (\n <div className={styles.dropdown__close}>\n <Button onClick={handleClose}>{mergedResources.closeText}</Button>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport interface DropdownCompound extends React.FC<DropdownProps> {\n SingleSelectItem: ComponentType<SingleSelectItemProps>;\n}\nconst Dropdown = DropdownBase as DropdownCompound;\nDropdown.SingleSelectItem = SingleSelectItem;\nDropdownBase.displayName = 'Dropdown';\n\nexport default Dropdown;\n"],"names":["React"],"mappings":"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"}
@@ -6,7 +6,8 @@
6
6
 
7
7
  .dropdown {
8
8
  position: relative;
9
- max-width: fit-content;
9
+ max-width: 100%;
10
+ flex: 0 1 auto;
10
11
 
11
12
  &__toggle {
12
13
  display: flex;
@@ -98,6 +98,10 @@ $padding-clickable-area-left: 8px;
98
98
  background-color: palette.$neutral100;
99
99
  }
100
100
 
101
+ &--focused {
102
+ border: 1px solid var(--color-action-border-ondark-focus);
103
+ }
104
+
101
105
  &--on-blueberry {
102
106
  background-color: palette.$white;
103
107
 
@@ -11,6 +11,7 @@ export type Styles = {
11
11
  'radio-button-label': string;
12
12
  'radio-button-label__large': string;
13
13
  'radio-button-label__large--disabled': string;
14
+ 'radio-button-label__large--focused': string;
14
15
  'radio-button-label__large--on-blueberry': string;
15
16
  'radio-button-label__large--on-grey': string;
16
17
  'radio-button-label__large--selected': string;
@@ -11,24 +11,42 @@
11
11
  border-radius: 0.25rem;
12
12
  background-color: var(--core-color-kiwi-50);
13
13
  border: 2px solid var(--core-color-kiwi-900);
14
- display: flex;
15
- flex-direction: row;
16
- align-items: center;
17
- gap: 0.25rem;
18
14
  pointer-events: auto;
15
+ display: grid;
16
+ grid-template:
17
+ 'check text close' 2.375rem
18
+ '. text .' auto /
19
+ calc(38px + 4px) auto calc(38px + 10px);
20
+
21
+ @media (min-width: map.get(breakpoints.$grid-breakpoints, md)) {
22
+ grid-template:
23
+ 'check text close' 2.75rem
24
+ '. text .' auto /
25
+ calc(48px + 4px) auto calc(48px + 9px);
26
+ }
19
27
 
20
28
  &__icon {
21
- align-self: flex-start;
22
29
  fill: var(--core-color-kiwi-900);
30
+ align-self: center;
31
+
32
+ &--check {
33
+ grid-area: check;
34
+ }
35
+
36
+ &--close {
37
+ grid-area: close;
38
+ justify-self: end;
39
+ }
23
40
  }
24
41
 
25
42
  &__text-container {
26
43
  --margin-top: 0;
27
44
 
28
- flex-grow: 1;
45
+ grid-area: text;
29
46
  display: flex;
30
47
  flex-direction: column;
31
48
  gap: 0.25rem;
49
+ align-self: center;
32
50
  margin-top: var(--margin-top);
33
51
 
34
52
  &:has(.toast__description) {
@@ -42,6 +60,8 @@
42
60
 
43
61
  &__title {
44
62
  @include fonts.title6;
63
+
64
+ padding-top: 0.125rem;
45
65
  }
46
66
 
47
67
  &__description {
@@ -147,6 +147,15 @@
147
147
  &:focus-visible + .toggle-container__toggle {
148
148
  border-color: var(--color-action-border-onlight-focus);
149
149
  outline: 2px solid var(--color-action-border-onlight-focus);
150
+
151
+ &::after {
152
+ content: '';
153
+ display: block;
154
+ width: 100%;
155
+ height: 100%;
156
+ border-radius: 60px;
157
+ border: 1px solid var(--color-action-border-ondark-focus);
158
+ }
150
159
  }
151
160
  }
152
161
  }
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ interface TokensExampleProps {
3
+ colorName?: string;
4
+ color?: string;
5
+ }
6
+ declare function TokensExample(props: TokensExampleProps): React.JSX.Element;
7
+ export default TokensExample;
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "url": "git+https://github.com/helsenorge/designsystem.git"
8
8
  },
9
9
  "homepage": "https://helsenorge.design",
10
- "version": "12.10.0",
10
+ "version": "12.11.1",
11
11
  "author": "Helsenorge",
12
12
  "license": "MIT",
13
13
  "dependencies": {