@helsenorge/designsystem-react 15.0.0 → 15.1.0

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/lib/Button.js CHANGED
@@ -17,8 +17,8 @@ var getIconColor = (fill, borderless, disabled, concept, ondark, mobile) => {
17
17
  if (fill && !ondark || !fill && ondark) return "white";
18
18
  return concept === "normal" ? getColor("blueberry", 600) : getColor("cherry", 500);
19
19
  };
20
- var getLargeIconSize = (large, mobile) => {
21
- if (mobile && large) return IconSize.Small;
20
+ var getIconSize = (large, mobile, isBorderless) => {
21
+ if (isBorderless && large || mobile && large) return IconSize.Small;
22
22
  if (large) return IconSize.Medium;
23
23
  return IconSize.XSmall;
24
24
  };
@@ -39,14 +39,16 @@ var Button = (props) => {
39
39
  const borderlessVariant = variant === "borderless";
40
40
  const iconColor = getIconColor(variant === "fill", borderlessVariant, disabled, concept, onDark, isMobile);
41
41
  const hasArrow = arrow === "icon" && !borderlessVariant;
42
- const large = size === "large" && !destructive && !borderlessVariant;
42
+ const large = size === "large" && !destructive;
43
+ const largeBorderless = large && borderlessVariant;
43
44
  const hasUURightArrow = arrow === "accessibility-character" && !fluid && !leftIcon && !rightIcon && !hasArrow && borderlessVariant;
44
45
  const rest = { ...restProps };
45
46
  const buttonWrapperClasses = classNames(buttonStyles["button-wrapper"], { [buttonStyles["button-wrapper--fluid"]]: fluid || ellipsis }, wrapperClassName);
46
47
  const buttonClasses = classNames(buttonStyles.button, {
47
48
  [buttonStyles["button--destructive"]]: destructive,
48
- [buttonStyles["button--normal"]]: !large,
49
- [buttonStyles["button--large"]]: large,
49
+ [buttonStyles["button--medium"]]: !large,
50
+ [buttonStyles["button--large-non-borderless"]]: large && !largeBorderless,
51
+ [buttonStyles["button--large-borderless"]]: largeBorderless,
50
52
  [buttonStyles["button--outline"]]: outlineVariant,
51
53
  [buttonStyles["button--borderless"]]: borderlessVariant,
52
54
  [buttonStyles["button--left-icon"]]: leftIcon && !onlyIcon,
@@ -82,20 +84,23 @@ var Button = (props) => {
82
84
  }), /* @__PURE__ */ jsx("span", { children: onlyIcon ? ariaLabel : restChildren })]
83
85
  });
84
86
  };
85
- const renderbuttonContentWrapper = () => /* @__PURE__ */ jsxs("span", {
86
- className: buttonClasses,
87
- children: [
88
- renderIcon(leftIcon, getLargeIconSize(large, isMobile), !onlyIcon ? buttonStyles["button__left-icon"] : void 0),
89
- renderButtonContent(),
90
- hasArrow ? renderIcon(/* @__PURE__ */ jsx(Icon_default, { svgIcon: ArrowRight }), getLargeIconSize(large, isMobile), classNames(buttonStyles["button__arrow"], { [buttonStyles["button__arrow--both-icons"]]: bothIcons })) : renderIcon(rightIcon, getLargeIconSize(large, isMobile), buttonStyles["button__right-icon"]),
91
- hasUURightArrow && /* @__PURE__ */ jsx("span", {
92
- style: { color: iconColor },
93
- className: buttonStyles["button__right-unicode-arrow"],
94
- "aria-hidden": true,
95
- children: ""
96
- })
97
- ]
98
- });
87
+ const renderbuttonContentWrapper = () => {
88
+ const iconSize = getIconSize(large, isMobile, borderlessVariant);
89
+ return /* @__PURE__ */ jsxs("span", {
90
+ className: buttonClasses,
91
+ children: [
92
+ renderIcon(leftIcon, iconSize, !onlyIcon ? buttonStyles["button__left-icon"] : void 0),
93
+ renderButtonContent(),
94
+ hasArrow ? renderIcon(/* @__PURE__ */ jsx(Icon_default, { svgIcon: ArrowRight }), iconSize, classNames(buttonStyles["button__arrow"], { [buttonStyles["button__arrow--both-icons"]]: bothIcons })) : renderIcon(rightIcon, iconSize, buttonStyles["button__right-icon"]),
95
+ hasUURightArrow && /* @__PURE__ */ jsx("span", {
96
+ style: { color: iconColor },
97
+ className: buttonStyles["button__right-unicode-arrow"],
98
+ "aria-hidden": true,
99
+ children: " →"
100
+ })
101
+ ]
102
+ });
103
+ };
99
104
  return /* @__PURE__ */ jsxs(Fragment, { children: [htmlMarkup === "button" && /* @__PURE__ */ jsx("button", {
100
105
  id,
101
106
  onBlur,
package/lib/Button.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","names":[],"sources":["../src/components/Button/Button.tsx","../src/components/Button/index.ts"],"sourcesContent":["import React, { type AriaAttributes, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Icon, { IconSize } from './../Icon';\nimport { type HTMLButtonProps, type HTMLAnchorProps, AnalyticsId } from '../../constants';\nimport { type BaseIconElement, useIcons } from '../../hooks/useIcons';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport { getColor } from '../../theme/currys/color';\nimport { isTest, isProd } from '../../utils/environment';\nimport ArrowRight from '../Icons/ArrowRight';\n\nimport buttonStyles from './styles.module.scss';\n\nexport type ButtonConcept = 'normal' | 'destructive';\nexport type ButtonVariant = 'fill' | 'outline' | 'borderless';\nexport type ButtonSize = 'medium' | 'large';\nexport type ButtonOnColor = 'onlight' | 'ondark';\nexport type ButtonTags = 'button' | 'a';\nexport type ButtonArrows = 'icon' | 'accessibility-character';\nexport type ButtonTextPosition = 'left' | 'centered';\n\nexport interface ButtonProps extends Omit<HTMLButtonProps, 'onClick' | 'type'>, Omit<HTMLAnchorProps, 'onClick'>, AriaAttributes {\n /** Sets the aria-label of the button, use when the button only includes an icon */\n ariaLabel?: string;\n /** Gives a unique id to the button */\n id?: string;\n /** Sets the content of the button. */\n children: React.ReactNode;\n /** Adds custom classes to the wrapper element. */\n wrapperClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Enables an arrow icon to the right inside the button (Not available in borderless variant) */\n arrow?: ButtonArrows;\n /** Changes the intent of the button. Mostly changes the color profile. */\n concept?: ButtonConcept;\n /** Disables text wrapping and enables ellipsis. */\n ellipsis?: boolean;\n /** Makes the button scale to full width of its parent element. */\n fluid?: boolean;\n /** Changes the underlying element of the button. */\n htmlMarkup?: ButtonTags;\n /** Changes the button colors for different backgrounds. */\n onColor?: ButtonOnColor;\n /** Function that is called when the Button loses focus */\n onBlur?: () => void;\n /** Function that is called when clicked */\n onClick?: (\n e?: React.MouseEvent<HTMLElement, MouseEvent> | React.FormEvent<unknown> | React.KeyboardEvent<HTMLUListElement> | null\n ) => void;\n /** Changes the button colors for different backgrounds. (Large not available in borderless variant) */\n size?: ButtonSize;\n /** Changes the visual representation of the button. */\n variant?: ButtonVariant;\n /** Specifies the focus order relative to the other buttons or controls on the page */\n tabIndex?: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Adds custom classes to the text */\n textClassName?: string;\n /** Sets the position of the text in the button - only applies when button is fluid */\n textPosition?: ButtonTextPosition;\n /** Button type. Default: button */\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n /** Ref that is passed to the component */\n ref?: React.RefObject<HTMLButtonElement | HTMLAnchorElement | null>;\n}\n\nconst getIconColor = (\n fill: boolean,\n borderless: boolean,\n disabled: boolean,\n concept: ButtonConcept,\n ondark: boolean,\n mobile: boolean\n): string => {\n if (mobile && disabled) {\n return !ondark || fill ? getColor('neutral', !borderless ? 700 : 500) : getColor('white');\n }\n if (disabled) {\n return !ondark || fill ? getColor('neutral', 500) : `${getColor('white')}b3`;\n }\n if ((fill && !ondark) || (!fill && ondark)) {\n return 'white';\n }\n\n return concept === 'normal' ? getColor('blueberry', 600) : getColor('cherry', 500);\n};\nconst getLargeIconSize = (large: boolean, mobile: boolean): IconSize => {\n if (mobile && large) return IconSize.Small;\n if (large) return IconSize.Medium;\n return IconSize.XSmall;\n};\n\nconst checkOnlyIconAria = (onlyIcon: boolean, ariaLabel: string | undefined, devEnv: boolean): void => {\n if (devEnv && onlyIcon && (ariaLabel === undefined || ariaLabel === '')) {\n throw new Error('Fyll inn ariaLabel prop på Button uten tekst for å opprettholde UU krav');\n }\n};\n\nconst Button: React.FC<ButtonProps> = props => {\n const {\n ariaLabel,\n id,\n children,\n wrapperClassName,\n className,\n arrow,\n concept = 'normal',\n disabled = false,\n ellipsis = false,\n fluid = false,\n htmlMarkup = 'button',\n onColor = 'onlight',\n onBlur,\n onClick,\n size = 'medium',\n variant = 'fill',\n href,\n tabIndex,\n testId,\n target,\n type = 'button',\n textClassName,\n textPosition = 'left',\n ref,\n ...restProps\n } = props;\n const [leftIcon, rightIcon, restChildren] = useIcons(React.Children.toArray(children));\n const { refObject, isHovered } = usePseudoClasses<HTMLButtonElement | HTMLAnchorElement | null>(ref);\n const buttonContentRef = useRef<HTMLDivElement>(null);\n const onlyIcon = !!(leftIcon || rightIcon) && !restChildren;\n const bothIcons = leftIcon && (rightIcon || arrow) && !onlyIcon;\n const onDark = onColor === 'ondark';\n const isMobile = useIsMobileBreakpoint();\n const destructive = concept === 'destructive' && !disabled;\n const outlineVariant = variant === 'outline';\n const borderlessVariant = variant === 'borderless';\n const iconColor = getIconColor(variant === 'fill', borderlessVariant, disabled, concept, onDark, isMobile);\n const hasArrow = arrow === 'icon' && !borderlessVariant;\n const large = size === 'large' && !destructive && !borderlessVariant;\n const hasUURightArrow = arrow === 'accessibility-character' && !fluid && !leftIcon && !rightIcon && !hasArrow && borderlessVariant;\n const rest = { ...restProps };\n\n const buttonWrapperClasses = classNames(\n buttonStyles['button-wrapper'],\n { [buttonStyles['button-wrapper--fluid']]: fluid || ellipsis },\n wrapperClassName\n );\n const buttonClasses = classNames(\n buttonStyles.button,\n {\n [buttonStyles['button--destructive']]: destructive,\n [buttonStyles['button--normal']]: !large,\n [buttonStyles['button--large']]: large,\n [buttonStyles['button--outline']]: outlineVariant,\n [buttonStyles['button--borderless']]: borderlessVariant,\n [buttonStyles['button--left-icon']]: leftIcon && !onlyIcon,\n [buttonStyles['button--right-icon']]: rightIcon && !onlyIcon,\n [buttonStyles['button--both-icons']]: bothIcons,\n [buttonStyles['button--only-icon']]: onlyIcon,\n [buttonStyles['button--arrow']]: hasArrow,\n [buttonStyles['button--on-dark']]: onDark,\n },\n className\n );\n const buttonTextClasses = classNames(\n buttonStyles['button__text'],\n {\n [buttonStyles['button__text--ellipsis']]: ellipsis,\n [buttonStyles['button__text--centered']]: fluid && textPosition === 'centered',\n },\n textClassName\n );\n const diagonalClasses = classNames(buttonStyles['diagonal'], {\n [buttonStyles['diagonal--on-dark']]: onDark,\n });\n\n useEffect(() => {\n checkOnlyIconAria(onlyIcon, ariaLabel, !isTest() && !isProd());\n }, []);\n\n const renderIcon = (iconElement: BaseIconElement | null, iconSize: number, iconClassName?: string): BaseIconElement | null => {\n return iconElement\n ? React.cloneElement(iconElement, {\n size: iconSize,\n color: iconElement?.props.color && !disabled ? iconElement.props.color : iconColor,\n isHovered: iconElement.props.isHovered === undefined ? !disabled && isHovered : iconElement.props.isHovered,\n className: iconClassName,\n })\n : null;\n };\n\n const renderButtonContent = (): React.ReactNode => {\n return (\n <span className={buttonTextClasses} ref={buttonContentRef}>\n {disabled && borderlessVariant && (\n <span className={diagonalClasses}>\n <span className={buttonStyles['diagonal__line']} />\n </span>\n )}\n <span>{onlyIcon ? ariaLabel : restChildren}</span>\n </span>\n );\n };\n\n const renderbuttonContentWrapper = (): React.ReactNode => (\n <span className={buttonClasses}>\n {renderIcon(leftIcon, getLargeIconSize(large, isMobile), !onlyIcon ? buttonStyles['button__left-icon'] : undefined)}\n {renderButtonContent()}\n {hasArrow\n ? renderIcon(\n <Icon svgIcon={ArrowRight} />,\n getLargeIconSize(large, isMobile),\n classNames(buttonStyles['button__arrow'], { [buttonStyles['button__arrow--both-icons']]: bothIcons })\n )\n : renderIcon(rightIcon, getLargeIconSize(large, isMobile), buttonStyles['button__right-icon'])}\n {hasUURightArrow && (\n <span style={{ color: iconColor }} className={buttonStyles['button__right-unicode-arrow']} aria-hidden>\n {' →'}\n </span>\n )}\n </span>\n );\n\n return (\n <>\n {htmlMarkup === 'button' && (\n <button\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n ref={refObject as React.RefObject<HTMLButtonElement>}\n tabIndex={tabIndex}\n type={type}\n {...rest}\n >\n {renderbuttonContentWrapper()}\n </button>\n )}\n {htmlMarkup === 'a' && (\n <a\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n href={href}\n target={target}\n rel={target === '_blank' ? 'noopener noreferrer' : props.rel}\n ref={refObject as React.RefObject<HTMLAnchorElement>}\n tabIndex={tabIndex}\n {...restProps}\n >\n {renderbuttonContentWrapper()}\n </a>\n )}\n </>\n );\n};\n\nexport default Button;\n","import Button from './Button';\nexport * from './Button';\nexport default Button;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Button.js","names":[],"sources":["../src/components/Button/Button.tsx","../src/components/Button/index.ts"],"sourcesContent":["import React, { type AriaAttributes, useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport Icon, { IconSize } from './../Icon';\nimport { type HTMLButtonProps, type HTMLAnchorProps, AnalyticsId } from '../../constants';\nimport { type BaseIconElement, useIcons } from '../../hooks/useIcons';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport { getColor } from '../../theme/currys/color';\nimport { isTest, isProd } from '../../utils/environment';\nimport ArrowRight from '../Icons/ArrowRight';\n\nimport buttonStyles from './styles.module.scss';\n\nexport type ButtonConcept = 'normal' | 'destructive';\nexport type ButtonVariant = 'fill' | 'outline' | 'borderless';\nexport type ButtonSize = 'medium' | 'large';\nexport type ButtonOnColor = 'onlight' | 'ondark';\nexport type ButtonTags = 'button' | 'a';\nexport type ButtonArrows = 'icon' | 'accessibility-character';\nexport type ButtonTextPosition = 'left' | 'centered';\n\nexport interface ButtonProps extends Omit<HTMLButtonProps, 'onClick' | 'type'>, Omit<HTMLAnchorProps, 'onClick'>, AriaAttributes {\n /** Sets the aria-label of the button, use when the button only includes an icon */\n ariaLabel?: string;\n /** Gives a unique id to the button */\n id?: string;\n /** Sets the content of the button. */\n children: React.ReactNode;\n /** Adds custom classes to the wrapper element. */\n wrapperClassName?: string;\n /** Adds custom classes to the element. */\n className?: string;\n /** Enables an arrow icon to the right inside the button (Not available in borderless variant) */\n arrow?: ButtonArrows;\n /** Changes the intent of the button. Mostly changes the color profile. */\n concept?: ButtonConcept;\n /** Disables text wrapping and enables ellipsis. */\n ellipsis?: boolean;\n /** Makes the button scale to full width of its parent element. */\n fluid?: boolean;\n /** Changes the underlying element of the button. */\n htmlMarkup?: ButtonTags;\n /** Changes the button colors for different backgrounds. */\n onColor?: ButtonOnColor;\n /** Function that is called when the Button loses focus */\n onBlur?: () => void;\n /** Function that is called when clicked */\n onClick?: (\n e?: React.MouseEvent<HTMLElement, MouseEvent> | React.FormEvent<unknown> | React.KeyboardEvent<HTMLUListElement> | null\n ) => void;\n /** Changes the button colors for different backgrounds. (Large not available in borderless variant) */\n size?: ButtonSize;\n /** Changes the visual representation of the button. */\n variant?: ButtonVariant;\n /** Specifies the focus order relative to the other buttons or controls on the page */\n tabIndex?: number;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Adds custom classes to the text */\n textClassName?: string;\n /** Sets the position of the text in the button - only applies when button is fluid */\n textPosition?: ButtonTextPosition;\n /** Button type. Default: button */\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n /** Ref that is passed to the component */\n ref?: React.RefObject<HTMLButtonElement | HTMLAnchorElement | null>;\n}\n\nconst getIconColor = (\n fill: boolean,\n borderless: boolean,\n disabled: boolean,\n concept: ButtonConcept,\n ondark: boolean,\n mobile: boolean\n): string => {\n if (mobile && disabled) {\n return !ondark || fill ? getColor('neutral', !borderless ? 700 : 500) : getColor('white');\n }\n if (disabled) {\n return !ondark || fill ? getColor('neutral', 500) : `${getColor('white')}b3`;\n }\n if ((fill && !ondark) || (!fill && ondark)) {\n return 'white';\n }\n\n return concept === 'normal' ? getColor('blueberry', 600) : getColor('cherry', 500);\n};\nconst getIconSize = (large: boolean, mobile: boolean, isBorderless: boolean): IconSize => {\n if ((isBorderless && large) || (mobile && large)) {\n return IconSize.Small;\n }\n\n if (large) {\n return IconSize.Medium;\n }\n\n return IconSize.XSmall;\n};\n\nconst checkOnlyIconAria = (onlyIcon: boolean, ariaLabel: string | undefined, devEnv: boolean): void => {\n if (devEnv && onlyIcon && (ariaLabel === undefined || ariaLabel === '')) {\n throw new Error('Fyll inn ariaLabel prop på Button uten tekst for å opprettholde UU krav');\n }\n};\n\nconst Button: React.FC<ButtonProps> = props => {\n const {\n ariaLabel,\n id,\n children,\n wrapperClassName,\n className,\n arrow,\n concept = 'normal',\n disabled = false,\n ellipsis = false,\n fluid = false,\n htmlMarkup = 'button',\n onColor = 'onlight',\n onBlur,\n onClick,\n size = 'medium',\n variant = 'fill',\n href,\n tabIndex,\n testId,\n target,\n type = 'button',\n textClassName,\n textPosition = 'left',\n ref,\n ...restProps\n } = props;\n const [leftIcon, rightIcon, restChildren] = useIcons(React.Children.toArray(children));\n const { refObject, isHovered } = usePseudoClasses<HTMLButtonElement | HTMLAnchorElement | null>(ref);\n const buttonContentRef = useRef<HTMLDivElement>(null);\n const onlyIcon = !!(leftIcon || rightIcon) && !restChildren;\n const bothIcons = leftIcon && (rightIcon || arrow) && !onlyIcon;\n const onDark = onColor === 'ondark';\n const isMobile = useIsMobileBreakpoint();\n const destructive = concept === 'destructive' && !disabled;\n const outlineVariant = variant === 'outline';\n const borderlessVariant = variant === 'borderless';\n const iconColor = getIconColor(variant === 'fill', borderlessVariant, disabled, concept, onDark, isMobile);\n const hasArrow = arrow === 'icon' && !borderlessVariant;\n const large = size === 'large' && !destructive;\n const largeBorderless = large && borderlessVariant;\n const hasUURightArrow = arrow === 'accessibility-character' && !fluid && !leftIcon && !rightIcon && !hasArrow && borderlessVariant;\n const rest = { ...restProps };\n\n const buttonWrapperClasses = classNames(\n buttonStyles['button-wrapper'],\n { [buttonStyles['button-wrapper--fluid']]: fluid || ellipsis },\n wrapperClassName\n );\n const buttonClasses = classNames(\n buttonStyles.button,\n {\n [buttonStyles['button--destructive']]: destructive,\n [buttonStyles['button--medium']]: !large,\n [buttonStyles['button--large-non-borderless']]: large && !largeBorderless,\n [buttonStyles['button--large-borderless']]: largeBorderless,\n [buttonStyles['button--outline']]: outlineVariant,\n [buttonStyles['button--borderless']]: borderlessVariant,\n [buttonStyles['button--left-icon']]: leftIcon && !onlyIcon,\n [buttonStyles['button--right-icon']]: rightIcon && !onlyIcon,\n [buttonStyles['button--both-icons']]: bothIcons,\n [buttonStyles['button--only-icon']]: onlyIcon,\n [buttonStyles['button--arrow']]: hasArrow,\n [buttonStyles['button--on-dark']]: onDark,\n },\n className\n );\n const buttonTextClasses = classNames(\n buttonStyles['button__text'],\n {\n [buttonStyles['button__text--ellipsis']]: ellipsis,\n [buttonStyles['button__text--centered']]: fluid && textPosition === 'centered',\n },\n textClassName\n );\n const diagonalClasses = classNames(buttonStyles['diagonal'], {\n [buttonStyles['diagonal--on-dark']]: onDark,\n });\n\n useEffect(() => {\n checkOnlyIconAria(onlyIcon, ariaLabel, !isTest() && !isProd());\n }, []);\n\n const renderIcon = (iconElement: BaseIconElement | null, iconSize: number, iconClassName?: string): BaseIconElement | null => {\n return iconElement\n ? React.cloneElement(iconElement, {\n size: iconSize,\n color: iconElement?.props.color && !disabled ? iconElement.props.color : iconColor,\n isHovered: iconElement.props.isHovered === undefined ? !disabled && isHovered : iconElement.props.isHovered,\n className: iconClassName,\n })\n : null;\n };\n\n const renderButtonContent = (): React.ReactNode => {\n return (\n <span className={buttonTextClasses} ref={buttonContentRef}>\n {disabled && borderlessVariant && (\n <span className={diagonalClasses}>\n <span className={buttonStyles['diagonal__line']} />\n </span>\n )}\n <span>{onlyIcon ? ariaLabel : restChildren}</span>\n </span>\n );\n };\n\n const renderbuttonContentWrapper = (): React.ReactNode => {\n const iconSize = getIconSize(large, isMobile, borderlessVariant);\n\n return (\n <span className={buttonClasses}>\n {renderIcon(leftIcon, iconSize, !onlyIcon ? buttonStyles['button__left-icon'] : undefined)}\n {renderButtonContent()}\n {hasArrow\n ? renderIcon(\n <Icon svgIcon={ArrowRight} />,\n iconSize,\n classNames(buttonStyles['button__arrow'], { [buttonStyles['button__arrow--both-icons']]: bothIcons })\n )\n : renderIcon(rightIcon, iconSize, buttonStyles['button__right-icon'])}\n {hasUURightArrow && (\n <span style={{ color: iconColor }} className={buttonStyles['button__right-unicode-arrow']} aria-hidden>\n {' →'}\n </span>\n )}\n </span>\n );\n };\n\n return (\n <>\n {htmlMarkup === 'button' && (\n <button\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n ref={refObject as React.RefObject<HTMLButtonElement>}\n tabIndex={tabIndex}\n type={type}\n {...rest}\n >\n {renderbuttonContentWrapper()}\n </button>\n )}\n {htmlMarkup === 'a' && (\n <a\n id={id}\n onBlur={onBlur}\n onClick={onClick}\n data-testid={testId}\n data-analyticsid={AnalyticsId.Button}\n className={buttonWrapperClasses}\n href={href}\n target={target}\n rel={target === '_blank' ? 'noopener noreferrer' : props.rel}\n ref={refObject as React.RefObject<HTMLAnchorElement>}\n tabIndex={tabIndex}\n {...restProps}\n >\n {renderbuttonContentWrapper()}\n </a>\n )}\n </>\n );\n};\n\nexport default Button;\n","import Button from './Button';\nexport * from './Button';\nexport default Button;\n"],"mappings":"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"}
package/lib/CHANGELOG.md CHANGED
@@ -1,4 +1,17 @@
1
1
 
2
+ ## [15.1.0](https://github.com/helsenorge/designsystem/compare/v15.0.0...v15.1.0) (2026-06-16)
3
+
4
+ ### Features
5
+
6
+ * legg til flere språk for default tekster for filter og datepicker ([e23c5d9](https://github.com/helsenorge/designsystem/commit/e23c5d913bc4f1deaad21ebe7744ff82ed47a8f2)), closes [#376074](https://github.com/helsenorge/designsystem/issues/376074)
7
+ * **button:** borderless variant kan ha size large ([dc68e4f](https://github.com/helsenorge/designsystem/commit/dc68e4f18a773aca05ac399a3eea140d3b93c720)), closes [#377363](https://github.com/helsenorge/designsystem/issues/377363)
8
+ * **daterangeselector:** value og onchange forenklet for letter bruk med filter ([a31ce8a](https://github.com/helsenorge/designsystem/commit/a31ce8a2229577a59eadd3179f6831c48d7f9c50)), closes [#378862](https://github.com/helsenorge/designsystem/issues/378862)
9
+ * **drawer:** lag egen komponent for tilbakeknapp som er lik close ([89966d7](https://github.com/helsenorge/designsystem/commit/89966d745d1e7b4836c9767ae9ed2b255a3b6650)), closes [#379768](https://github.com/helsenorge/designsystem/issues/379768)
10
+
11
+ ### Bug Fixes
12
+
13
+ * scss partials blir ikke eksportert med vite 8 ([9b9cdc4](https://github.com/helsenorge/designsystem/commit/9b9cdc49ba3f2ba38deef25fdc18cfea1a6ce1f8)), closes [#380701](https://github.com/helsenorge/designsystem/issues/380701)
14
+
2
15
  ## [15.0.0](https://github.com/helsenorge/designsystem/compare/v14.11.1...v15.0.0) (2026-06-04)
3
16
 
4
17
  ### Features
package/lib/Drawer.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as uuid } from "./uuid.js";
2
2
  import { AnalyticsId, KeyboardEventKey, LanguageLocales, ZIndex } from "./constants.js";
3
+ import { usePseudoClasses } from "./hooks/usePseudoClasses.js";
3
4
  import { t as Icon_default } from "./Icon.js";
4
5
  import { useLanguage } from "./hooks/useLanguage.js";
5
6
  import { useIsMobileBreakpoint } from "./hooks/useIsMobileBreakpoint.js";
@@ -12,13 +13,14 @@ import { useOutsideEvent } from "./hooks/useOutsideEvent.js";
12
13
  import { t as Close_default } from "./Close.js";
13
14
  import { useReturnFocusOnUnmount } from "./hooks/useReturnFocusOnUnmount.js";
14
15
  import { disableBodyScroll, enableBodyScroll } from "./utils/scroll.js";
15
- import ChevronLeft from "./components/Icons/ChevronLeft.js";
16
16
  import Title_default from "./components/Title/index.js";
17
+ import ChevronLeft from "./components/Icons/ChevronLeft.js";
17
18
  import classNames from "classnames";
18
19
  import React, { useEffect, useRef } from "react";
19
20
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
20
21
  import { AnimatePresence, useAnimate, usePresence } from "motion/react";
21
- import styles from "./components/Drawer/styles.module.scss";
22
+ import styles from "./components/Drawer/DrawerBackButton.module.scss";
23
+ import styles$1 from "./components/Drawer/styles.module.scss";
22
24
  var HN_Designsystem_Drawer_en_GB_default = {
23
25
  ariaLabelCloseBtn: "Close",
24
26
  ariaLabelBackButton: "Go back"
@@ -31,17 +33,45 @@ var HN_Designsystem_Drawer_nn_NO_default = {
31
33
  ariaLabelCloseBtn: "Lukk",
32
34
  ariaLabelBackButton: "Gå tilbake"
33
35
  };
36
+ var HN_Designsystem_Drawer_se_NO_default = {
37
+ ariaLabelCloseBtn: "Gidde",
38
+ ariaLabelBackButton: "Mana ruovttoluotta"
39
+ };
34
40
  //#endregion
35
41
  //#region src/components/Drawer/resourceHelper.ts
36
42
  var getResources = (language) => {
37
43
  switch (language) {
38
44
  case LanguageLocales.ENGLISH: return HN_Designsystem_Drawer_en_GB_default;
39
45
  case LanguageLocales.NORWEGIAN_NYNORSK: return HN_Designsystem_Drawer_nn_NO_default;
46
+ case LanguageLocales.SAMI_NORTHERN: return HN_Designsystem_Drawer_se_NO_default;
40
47
  case LanguageLocales.NORWEGIAN:
41
48
  default: return HN_Designsystem_Drawer_nb_NO_default;
42
49
  }
43
50
  };
44
51
  //#endregion
52
+ //#region src/components/Drawer/DrawerBackButton.tsx
53
+ var DrawerBackButton = (props) => {
54
+ const { ariaLabel = "Tilbake", onClick, className } = props;
55
+ const { refObject, isHovered } = usePseudoClasses();
56
+ const iconSize = useIsMobileBreakpoint() ? 38 : 48;
57
+ return /* @__PURE__ */ jsx("button", {
58
+ ref: refObject,
59
+ className: classNames(styles["back-button"], className),
60
+ "aria-label": ariaLabel,
61
+ onClick,
62
+ type: "button",
63
+ children: /* @__PURE__ */ jsx("span", {
64
+ className: classNames(styles["back-button__inner-container"]),
65
+ children: /* @__PURE__ */ jsx(Icon_default, {
66
+ svgIcon: ChevronLeft,
67
+ color: "var(--color-action-graphics-onlight",
68
+ size: iconSize,
69
+ isHovered
70
+ })
71
+ })
72
+ });
73
+ };
74
+ //#endregion
45
75
  //#region src/components/Drawer/Drawer.tsx
46
76
  var Drawer = (props) => {
47
77
  const { isOpen, ...rest } = props;
@@ -78,7 +108,7 @@ var InnerDrawer = (props) => {
78
108
  ...resources
79
109
  };
80
110
  const contentIsScrollable = contentRef.current && contentRef.current.scrollHeight > contentRef.current.clientHeight;
81
- const headerStyling = classNames(styles.drawer__header, headerClasses);
111
+ const headerStyling = classNames(styles$1.drawer__header, headerClasses);
82
112
  const hasFooterContent = typeof footerContent !== "undefined" && footerContent || onPrimaryAction || onSecondaryAction;
83
113
  useFocusTrap(containerRef, true);
84
114
  useReturnFocusOnUnmount(containerRef);
@@ -159,23 +189,23 @@ var InnerDrawer = (props) => {
159
189
  titleRef.current?.focus();
160
190
  }, [title]);
161
191
  return /* @__PURE__ */ jsxs("div", {
162
- className: styles.drawer,
192
+ className: styles$1.drawer,
163
193
  ref: scope,
164
194
  style: { zIndex },
165
195
  "data-analyticsid": AnalyticsId.Drawer,
166
196
  children: [/* @__PURE__ */ jsx("div", {
167
- className: styles.drawer__overlay,
197
+ className: styles$1.drawer__overlay,
168
198
  ref: overlayRef,
169
199
  "aria-hidden": "true"
170
200
  }), /* @__PURE__ */ jsxs("div", {
171
- className: classNames(styles.drawer__container, { [styles["drawer__container--right"]]: desktopDirection === "right" }),
201
+ className: classNames(styles$1.drawer__container, { [styles$1["drawer__container--right"]]: desktopDirection === "right" }),
172
202
  ref: containerRef,
173
203
  role: "dialog",
174
204
  "aria-modal": "true",
175
205
  tabIndex: -1,
176
206
  ...ariaLabelAttributes,
177
207
  children: [/* @__PURE__ */ jsxs("div", {
178
- className: styles.drawer__container__inner,
208
+ className: styles$1.drawer__container__inner,
179
209
  children: [
180
210
  /* @__PURE__ */ jsxs("div", {
181
211
  className: headerStyling,
@@ -183,37 +213,35 @@ var InnerDrawer = (props) => {
183
213
  children: [
184
214
  /* @__PURE__ */ jsx(Title_default, {
185
215
  id: ariaLabelAttributes?.["aria-labelledby"],
186
- className: styles["drawer__header__title"],
216
+ className: styles$1["drawer__header__title"],
187
217
  htmlMarkup: titleHtmlMarkup,
188
218
  appearance: "title3",
189
219
  ref: titleRef,
190
220
  tabIndex: -1,
191
221
  children: title
192
222
  }),
193
- withBackButton && onRequestBack !== void 0 && /* @__PURE__ */ jsx(Button_default, {
223
+ withBackButton && onRequestBack !== void 0 && /* @__PURE__ */ jsx(DrawerBackButton, {
194
224
  ariaLabel: mergedResources.ariaLabelBackButton,
195
225
  onClick: onRequestBack,
196
- variant: "borderless",
197
- wrapperClassName: styles["drawer__header__back-button"],
198
- children: /* @__PURE__ */ jsx(Icon_default, { svgIcon: ChevronLeft })
226
+ className: styles$1["drawer__header__back-button"]
199
227
  }),
200
228
  !noCloseButton && onRequestClose != void 0 && /* @__PURE__ */ jsx(Close_default, {
201
229
  ariaLabel: mergedResources.ariaLabelCloseBtn,
202
230
  color: closeColor,
203
231
  onClick: onRequestClose,
204
- className: styles["drawer__header__close-button"]
232
+ className: styles$1["drawer__header__close-button"]
205
233
  })
206
234
  ]
207
235
  }),
208
236
  /* @__PURE__ */ jsx("div", {
209
- className: classNames(styles["drawer__content__shadow"], styles["drawer__content__shadow--top"]),
237
+ className: classNames(styles$1["drawer__content__shadow"], styles$1["drawer__content__shadow--top"]),
210
238
  style: {
211
239
  opacity: !topContentVisible && contentIsScrollable ? 1 : 0,
212
240
  top: headerHeight
213
241
  }
214
242
  }),
215
243
  /* @__PURE__ */ jsxs("div", {
216
- className: classNames(styles.drawer__content, contentClassName),
244
+ className: classNames(styles$1.drawer__content, contentClassName),
217
245
  tabIndex: contentIsScrollable ? 0 : void 0,
218
246
  role: contentIsScrollable ? "region" : void 0,
219
247
  ...contentIsScrollable ? ariaLabelAttributes : {},
@@ -221,7 +249,7 @@ var InnerDrawer = (props) => {
221
249
  children: [
222
250
  /* @__PURE__ */ jsx("div", { ref: topContent }),
223
251
  /* @__PURE__ */ jsx("div", {
224
- className: styles["drawer__content__children"],
252
+ className: styles$1["drawer__content__children"],
225
253
  children
226
254
  }),
227
255
  /* @__PURE__ */ jsx("div", {
@@ -231,7 +259,7 @@ var InnerDrawer = (props) => {
231
259
  ]
232
260
  }),
233
261
  /* @__PURE__ */ jsx("div", {
234
- className: classNames(styles["drawer__content__shadow"], styles["drawer__content__shadow--bottom"]),
262
+ className: classNames(styles$1["drawer__content__shadow"], styles$1["drawer__content__shadow--bottom"]),
235
263
  style: {
236
264
  opacity: !bottomContentVisible && contentIsScrollable ? 1 : 0,
237
265
  bottom: hasFooterContent ? footerHeight : 0
@@ -239,7 +267,7 @@ var InnerDrawer = (props) => {
239
267
  })
240
268
  ]
241
269
  }), hasFooterContent && /* @__PURE__ */ jsx("div", {
242
- className: styles.drawer__footer,
270
+ className: styles$1.drawer__footer,
243
271
  ref: footerRef,
244
272
  children: footerContent ? footerContent : /* @__PURE__ */ jsxs(Fragment, { children: [onPrimaryAction && /* @__PURE__ */ jsx(Button_default, {
245
273
  onClick: () => handleCTA(onPrimaryAction),
package/lib/Drawer.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","names":[],"sources":["../src/resources/HN.Designsystem.Drawer.en-GB.json","../src/resources/HN.Designsystem.Drawer.nb-NO.json","../src/resources/HN.Designsystem.Drawer.nn-NO.json","../src/components/Drawer/resourceHelper.ts","../src/components/Drawer/Drawer.tsx","../src/components/Drawer/index.ts"],"sourcesContent":["{\n \"ariaLabelCloseBtn\": \"Close\",\n \"ariaLabelBackButton\": \"Go back\"\n}\n","{\n \"ariaLabelBackButton\": \"Gå tilbake\",\n \"ariaLabelCloseBtn\": \"Lukk\"\n}\n","{\n \"ariaLabelCloseBtn\": \"Lukk\",\n \"ariaLabelBackButton\": \"Gå tilbake\"\n}\n","import type { HNDesignsystemDrawer } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Drawer.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Drawer.nb-NO.json';\nimport nnNO from '../../resources/HN.Designsystem.Drawer.nn-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemDrawer => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN_NYNORSK:\n return nnNO;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import React, { useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\nimport { AnimatePresence, useAnimate, usePresence } from 'motion/react';\n\nimport type { HNDesignsystemDrawer } from '../../resources/Resources';\nimport type { TitleTags } from '../Title';\n\nimport { getResources } from './resourceHelper';\nimport { AnalyticsId, KeyboardEventKey, LanguageLocales, ZIndex } from '../../constants';\nimport useFocusTrap from '../../hooks/useFocusTrap';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useKeyboardEvent } from '../../hooks/useKeyboardEvent';\nimport { useLanguage } from '../../hooks/useLanguage';\nimport { useOutsideEvent } from '../../hooks/useOutsideEvent';\nimport { useReturnFocusOnUnmount } from '../../hooks/useReturnFocusOnUnmount';\nimport { getAriaLabelAttributes } from '../../utils/accessibility';\nimport { disableBodyScroll, enableBodyScroll } from '../../utils/scroll';\nimport uuid from '../../utils/uuid';\nimport Button from '../Button';\nimport Close from '../Close';\nimport Icon from '../Icon';\nimport ChevronLeft from '../Icons/ChevronLeft';\nimport Title from '../Title';\n\nimport styles from './styles.module.scss';\n\ntype DesktopDirections = 'left' | 'right';\n\nexport interface DrawerProps extends InnerDrawerProps {\n /** Opens and closes the drawer */\n isOpen: boolean;\n}\n\nexport interface InnerDrawerProps {\n /** Sets the aria-label of the drawer */\n ariaLabel?: string;\n /** Sets the aria-labelledby of the drawer */\n ariaLabelledBy?: string;\n /** Sets the style of the Drawer Close button. Meant for use by HelpDrawer */\n closeColor?: 'blueberry' | 'plum';\n /** Direction of the drawer on desktop. Default: left */\n desktopDirection?: DesktopDirections;\n /** Sets the style of the Drawer header */\n headerClasses?: string;\n /** Title to display in the header of the drawer */\n title: string;\n /** id of the drawer title */\n titleId?: string;\n /** Changes the underlying element of the title. Default: h3 */\n titleHtmlMarkup?: TitleTags;\n /** Callback that triggers when clicking on close button or outside the drawer, update isOpen state when this triggers */\n onRequestClose?: () => void;\n /** Optional footer content that can be rendered instead of default CTA(s) */\n footerContent?: React.ReactNode;\n /** Main content of the drawer */\n children?: React.ReactNode;\n /** Hides the close button */\n noCloseButton?: boolean;\n /** Primary CTA callback */\n onPrimaryAction?: () => void;\n /** Text for primary CTA button if you want a default CTA button rendered (instead of `footerContent`) */\n primaryActionText?: string;\n /** Text for secondary CTA button if you want a default CTA button rendered (instead of `footerContent`) */\n secondaryActionText?: string;\n /** Secondary CTA callback */\n onSecondaryAction?: () => void;\n /** Customize the z-index of the drawer */\n zIndex?: number;\n /** Resources for component */\n resources?: Partial<HNDesignsystemDrawer>;\n /** Sets mobile styling and animation from outer level Drawer */\n isMobile?: boolean;\n /** Shows a back button to the left of title */\n withBackButton?: boolean;\n /** Callback for the back button */\n onRequestBack?: () => void;\n /** Sets classname for content part in Drawer */\n contentClassName?: string;\n}\n\nconst Drawer: React.FC<DrawerProps> = props => {\n const { isOpen, ...rest } = props;\n const isMobile = useIsMobileBreakpoint();\n\n return <AnimatePresence>{isOpen && <InnerDrawer {...rest} isMobile={isMobile} />}</AnimatePresence>;\n};\n\nconst InnerDrawer: React.FC<InnerDrawerProps> = props => {\n const {\n ariaLabel,\n ariaLabelledBy,\n children,\n closeColor = 'blueberry',\n desktopDirection = 'left',\n footerContent,\n headerClasses,\n noCloseButton = false,\n onPrimaryAction,\n onRequestClose,\n onSecondaryAction,\n primaryActionText,\n secondaryActionText,\n title,\n titleHtmlMarkup = 'h3',\n titleId = uuid(),\n zIndex = ZIndex.OverlayScreen,\n resources,\n isMobile,\n withBackButton,\n onRequestBack,\n contentClassName,\n } = props;\n\n const ariaLabelAttributes = getAriaLabelAttributes({ label: ariaLabel, id: ariaLabelledBy, fallbackId: titleId });\n const overlayRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n // topContent and bottomContent are used to detect scroll position for shadow effects\n const topContent = useRef<HTMLDivElement>(null);\n const bottomContent = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n const titleRef = useRef<HTMLHeadingElement>(null);\n const [scope, animate] = useAnimate();\n const [isPresent, safeToRemove] = usePresence();\n const [headerHeight, setHeaderHeight] = React.useState(0);\n const [footerHeight, setFooterHeight] = React.useState(0);\n const topContentVisible = useIsVisible(topContent);\n const bottomContentVisible = useIsVisible(bottomContent, 0);\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n\n const mergedResources: HNDesignsystemDrawer = {\n ...defaultResources,\n ...resources,\n };\n\n // eslint-disable-next-line react-hooks/refs\n const contentIsScrollable = contentRef.current && contentRef.current.scrollHeight > contentRef.current.clientHeight;\n const headerStyling = classNames(styles.drawer__header, headerClasses);\n const hasFooterContent = (typeof footerContent !== 'undefined' && footerContent) || onPrimaryAction || onSecondaryAction;\n\n useFocusTrap(containerRef, true);\n useReturnFocusOnUnmount(containerRef);\n useOutsideEvent(containerRef, () => {\n if (onRequestClose) onRequestClose();\n });\n useKeyboardEvent(containerRef, () => onRequestClose && onRequestClose(), [KeyboardEventKey.Escape]);\n\n // Close animasjon, vi kaller `onClose()` til slutt\n const closeDrawer = (): void => {\n if (!overlayRef.current || !containerRef.current) return;\n\n animate(overlayRef.current, { opacity: 0, pointerEvents: 'none' }, { duration: 0.3, ease: 'easeInOut' });\n\n if (isMobile) {\n animate(\n containerRef.current,\n { y: '100%' },\n {\n duration: 0.3,\n ease: 'easeInOut',\n onComplete: () => {\n if (safeToRemove) safeToRemove();\n },\n }\n );\n } else {\n animate(\n containerRef.current,\n { x: desktopDirection === 'left' ? '-100%' : '100%' },\n {\n duration: 0.3,\n ease: 'easeInOut',\n onComplete: () => {\n if (safeToRemove) safeToRemove();\n },\n }\n );\n }\n };\n\n useEffect(() => {\n containerRef.current?.focus();\n disableBodyScroll();\n\n return (): void => {\n enableBodyScroll();\n };\n }, []);\n\n // Measure header and footer heights\n useEffect(() => {\n const updateHeights = (): void => {\n if (headerRef.current) {\n setHeaderHeight(headerRef.current.offsetHeight);\n }\n if (footerRef.current) {\n setFooterHeight(footerRef.current.offsetHeight);\n }\n };\n\n updateHeights();\n\n // Update heights when content changes\n const resizeObserver = new ResizeObserver(updateHeights);\n if (headerRef.current) {\n resizeObserver.observe(headerRef.current);\n }\n if (footerRef.current) {\n resizeObserver.observe(footerRef.current);\n }\n\n return (): void => {\n resizeObserver.disconnect();\n };\n }, [hasFooterContent]);\n\n // Open animation.\n useEffect(() => {\n if (!overlayRef.current || !containerRef.current) return;\n\n if (!isPresent) {\n closeDrawer();\n return;\n }\n\n if (isMobile) {\n animate(containerRef.current, { y: '0' }, { duration: 0.3, ease: 'easeInOut' });\n } else {\n animate(containerRef.current, { x: '0' }, { duration: 0.3, ease: 'easeInOut' });\n }\n\n animate(overlayRef.current, { opacity: 1, pointerEvents: 'auto' }, { duration: 0.3, ease: 'easeInOut' });\n }, [isPresent]);\n\n const handleCTA = (callback?: () => void): void => {\n if (callback) {\n callback();\n }\n };\n\n useEffect(() => {\n titleRef.current?.focus();\n }, [title]);\n\n return (\n <div className={styles.drawer} ref={scope} style={{ zIndex }} data-analyticsid={AnalyticsId.Drawer}>\n <div className={styles.drawer__overlay} ref={overlayRef} aria-hidden=\"true\" />\n <div\n className={classNames(styles.drawer__container, {\n [styles['drawer__container--right']]: desktopDirection === 'right',\n })}\n ref={containerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n {...ariaLabelAttributes}\n >\n <div className={styles.drawer__container__inner}>\n <div className={headerStyling} ref={headerRef}>\n <Title\n id={ariaLabelAttributes?.['aria-labelledby']}\n className={styles['drawer__header__title']}\n htmlMarkup={titleHtmlMarkup}\n appearance=\"title3\"\n ref={titleRef}\n tabIndex={-1}\n >\n {title}\n </Title>\n {withBackButton && onRequestBack !== undefined && (\n <Button\n ariaLabel={mergedResources.ariaLabelBackButton}\n onClick={onRequestBack}\n variant=\"borderless\"\n wrapperClassName={styles['drawer__header__back-button']}\n >\n <Icon svgIcon={ChevronLeft} />\n </Button>\n )}\n {!noCloseButton && onRequestClose != undefined && (\n <Close\n ariaLabel={mergedResources.ariaLabelCloseBtn}\n color={closeColor}\n onClick={onRequestClose}\n className={styles['drawer__header__close-button']}\n />\n )}\n </div>\n <div\n className={classNames(styles['drawer__content__shadow'], styles['drawer__content__shadow--top'])}\n style={{\n opacity: !topContentVisible && contentIsScrollable ? 1 : 0,\n top: headerHeight,\n }}\n />\n <div\n className={classNames(styles.drawer__content, contentClassName)}\n tabIndex={contentIsScrollable ? 0 : undefined}\n role={contentIsScrollable ? 'region' : undefined}\n {...(contentIsScrollable ? ariaLabelAttributes : {})}\n ref={contentRef}\n >\n <div ref={topContent} />\n <div className={styles['drawer__content__children']}>{children}</div>\n <div ref={bottomContent} style={{ height: '1px' }} />\n </div>\n <div\n className={classNames(styles['drawer__content__shadow'], styles['drawer__content__shadow--bottom'])}\n style={{\n opacity: !bottomContentVisible && contentIsScrollable ? 1 : 0,\n bottom: hasFooterContent ? footerHeight : 0,\n }}\n />\n </div>\n {hasFooterContent && (\n <div className={styles.drawer__footer} ref={footerRef}>\n {footerContent ? (\n footerContent\n ) : (\n <>\n {onPrimaryAction && <Button onClick={() => handleCTA(onPrimaryAction)}>{primaryActionText}</Button>}\n {onSecondaryAction && (\n <Button variant=\"borderless\" onClick={() => handleCTA(onSecondaryAction)}>\n {secondaryActionText}\n </Button>\n )}\n </>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default Drawer;\n","import Drawer from './Drawer';\nexport * from './Drawer';\nexport default Drawer;\n"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.js","names":[],"sources":["../src/resources/HN.Designsystem.Drawer.en-GB.json","../src/resources/HN.Designsystem.Drawer.nb-NO.json","../src/resources/HN.Designsystem.Drawer.nn-NO.json","../src/resources/HN.Designsystem.Drawer.se-NO.json","../src/components/Drawer/resourceHelper.ts","../src/components/Drawer/DrawerBackButton.tsx","../src/components/Drawer/Drawer.tsx","../src/components/Drawer/index.ts"],"sourcesContent":["{\n \"ariaLabelCloseBtn\": \"Close\",\n \"ariaLabelBackButton\": \"Go back\"\n}\n","{\n \"ariaLabelBackButton\": \"Gå tilbake\",\n \"ariaLabelCloseBtn\": \"Lukk\"\n}\n","{\n \"ariaLabelCloseBtn\": \"Lukk\",\n \"ariaLabelBackButton\": \"Gå tilbake\"\n}\n","{\n \"ariaLabelCloseBtn\": \"Gidde\",\n \"ariaLabelBackButton\": \"Mana ruovttoluotta\"\n}\n","import type { HNDesignsystemDrawer } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Drawer.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Drawer.nb-NO.json';\nimport nnNO from '../../resources/HN.Designsystem.Drawer.nn-NO.json';\nimport seNO from '../../resources/HN.Designsystem.Drawer.se-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemDrawer => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN_NYNORSK:\n return nnNO;\n case LanguageLocales.SAMI_NORTHERN:\n return seNO;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import classNames from 'classnames';\n\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { usePseudoClasses } from '../../hooks/usePseudoClasses';\nimport Icon from '../Icon';\nimport ChevronLeft from '../Icons/ChevronLeft';\n\nimport styles from './DrawerBackButton.module.scss';\n\nexport interface DrawerBackButtonProps {\n /** Function is called when user clicks the button */\n onClick?: (e?: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n /** Sets the aria-label of the button */\n ariaLabel?: string;\n /** Adds custom classes to the element. */\n className?: string;\n}\n\nconst DrawerBackButton: React.FC<DrawerBackButtonProps> = props => {\n const { ariaLabel = 'Tilbake', onClick, className } = props;\n const { refObject, isHovered } = usePseudoClasses<HTMLButtonElement>();\n\n const iconSize = useIsMobileBreakpoint() ? 38 : 48;\n\n return (\n <button ref={refObject} className={classNames(styles['back-button'], className)} aria-label={ariaLabel} onClick={onClick} type=\"button\">\n <span className={classNames(styles['back-button__inner-container'])}>\n <Icon svgIcon={ChevronLeft} color={'var(--color-action-graphics-onlight'} size={iconSize} isHovered={isHovered} />\n </span>\n </button>\n );\n};\n\nexport default DrawerBackButton;\n","import React, { useEffect, useRef } from 'react';\n\nimport classNames from 'classnames';\nimport { AnimatePresence, useAnimate, usePresence } from 'motion/react';\n\nimport type { HNDesignsystemDrawer } from '../../resources/Resources';\nimport type { TitleTags } from '../Title';\n\nimport { getResources } from './resourceHelper';\nimport { AnalyticsId, KeyboardEventKey, LanguageLocales, ZIndex } from '../../constants';\nimport useFocusTrap from '../../hooks/useFocusTrap';\nimport { useIsMobileBreakpoint } from '../../hooks/useIsMobileBreakpoint';\nimport { useIsVisible } from '../../hooks/useIsVisible';\nimport { useKeyboardEvent } from '../../hooks/useKeyboardEvent';\nimport { useLanguage } from '../../hooks/useLanguage';\nimport { useOutsideEvent } from '../../hooks/useOutsideEvent';\nimport { useReturnFocusOnUnmount } from '../../hooks/useReturnFocusOnUnmount';\nimport { getAriaLabelAttributes } from '../../utils/accessibility';\nimport { disableBodyScroll, enableBodyScroll } from '../../utils/scroll';\nimport uuid from '../../utils/uuid';\nimport Button from '../Button';\nimport Close from '../Close';\nimport Title from '../Title';\nimport DrawerBackButton from './DrawerBackButton';\n\nimport styles from './styles.module.scss';\n\ntype DesktopDirections = 'left' | 'right';\n\nexport interface DrawerProps extends InnerDrawerProps {\n /** Opens and closes the drawer */\n isOpen: boolean;\n}\n\nexport interface InnerDrawerProps {\n /** Sets the aria-label of the drawer */\n ariaLabel?: string;\n /** Sets the aria-labelledby of the drawer */\n ariaLabelledBy?: string;\n /** Sets the style of the Drawer Close button. Meant for use by HelpDrawer */\n closeColor?: 'blueberry' | 'plum';\n /** Direction of the drawer on desktop. Default: left */\n desktopDirection?: DesktopDirections;\n /** Sets the style of the Drawer header */\n headerClasses?: string;\n /** Title to display in the header of the drawer */\n title: string;\n /** id of the drawer title */\n titleId?: string;\n /** Changes the underlying element of the title. Default: h3 */\n titleHtmlMarkup?: TitleTags;\n /** Callback that triggers when clicking on close button or outside the drawer, update isOpen state when this triggers */\n onRequestClose?: () => void;\n /** Optional footer content that can be rendered instead of default CTA(s) */\n footerContent?: React.ReactNode;\n /** Main content of the drawer */\n children?: React.ReactNode;\n /** Hides the close button */\n noCloseButton?: boolean;\n /** Primary CTA callback */\n onPrimaryAction?: () => void;\n /** Text for primary CTA button if you want a default CTA button rendered (instead of `footerContent`) */\n primaryActionText?: string;\n /** Text for secondary CTA button if you want a default CTA button rendered (instead of `footerContent`) */\n secondaryActionText?: string;\n /** Secondary CTA callback */\n onSecondaryAction?: () => void;\n /** Customize the z-index of the drawer */\n zIndex?: number;\n /** Resources for component */\n resources?: Partial<HNDesignsystemDrawer>;\n /** Sets mobile styling and animation from outer level Drawer */\n isMobile?: boolean;\n /** Shows a back button to the left of title */\n withBackButton?: boolean;\n /** Callback for the back button */\n onRequestBack?: () => void;\n /** Sets classname for content part in Drawer */\n contentClassName?: string;\n}\n\nconst Drawer: React.FC<DrawerProps> = props => {\n const { isOpen, ...rest } = props;\n const isMobile = useIsMobileBreakpoint();\n\n return <AnimatePresence>{isOpen && <InnerDrawer {...rest} isMobile={isMobile} />}</AnimatePresence>;\n};\n\nconst InnerDrawer: React.FC<InnerDrawerProps> = props => {\n const {\n ariaLabel,\n ariaLabelledBy,\n children,\n closeColor = 'blueberry',\n desktopDirection = 'left',\n footerContent,\n headerClasses,\n noCloseButton = false,\n onPrimaryAction,\n onRequestClose,\n onSecondaryAction,\n primaryActionText,\n secondaryActionText,\n title,\n titleHtmlMarkup = 'h3',\n titleId = uuid(),\n zIndex = ZIndex.OverlayScreen,\n resources,\n isMobile,\n withBackButton,\n onRequestBack,\n contentClassName,\n } = props;\n\n const ariaLabelAttributes = getAriaLabelAttributes({ label: ariaLabel, id: ariaLabelledBy, fallbackId: titleId });\n const overlayRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n // topContent and bottomContent are used to detect scroll position for shadow effects\n const topContent = useRef<HTMLDivElement>(null);\n const bottomContent = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n const titleRef = useRef<HTMLHeadingElement>(null);\n const [scope, animate] = useAnimate();\n const [isPresent, safeToRemove] = usePresence();\n const [headerHeight, setHeaderHeight] = React.useState(0);\n const [footerHeight, setFooterHeight] = React.useState(0);\n const topContentVisible = useIsVisible(topContent);\n const bottomContentVisible = useIsVisible(bottomContent, 0);\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n\n const mergedResources: HNDesignsystemDrawer = {\n ...defaultResources,\n ...resources,\n };\n\n // eslint-disable-next-line react-hooks/refs\n const contentIsScrollable = contentRef.current && contentRef.current.scrollHeight > contentRef.current.clientHeight;\n const headerStyling = classNames(styles.drawer__header, headerClasses);\n const hasFooterContent = (typeof footerContent !== 'undefined' && footerContent) || onPrimaryAction || onSecondaryAction;\n\n useFocusTrap(containerRef, true);\n useReturnFocusOnUnmount(containerRef);\n useOutsideEvent(containerRef, () => {\n if (onRequestClose) onRequestClose();\n });\n useKeyboardEvent(containerRef, () => onRequestClose && onRequestClose(), [KeyboardEventKey.Escape]);\n\n // Close animasjon, vi kaller `onClose()` til slutt\n const closeDrawer = (): void => {\n if (!overlayRef.current || !containerRef.current) return;\n\n animate(overlayRef.current, { opacity: 0, pointerEvents: 'none' }, { duration: 0.3, ease: 'easeInOut' });\n\n if (isMobile) {\n animate(\n containerRef.current,\n { y: '100%' },\n {\n duration: 0.3,\n ease: 'easeInOut',\n onComplete: () => {\n if (safeToRemove) safeToRemove();\n },\n }\n );\n } else {\n animate(\n containerRef.current,\n { x: desktopDirection === 'left' ? '-100%' : '100%' },\n {\n duration: 0.3,\n ease: 'easeInOut',\n onComplete: () => {\n if (safeToRemove) safeToRemove();\n },\n }\n );\n }\n };\n\n useEffect(() => {\n containerRef.current?.focus();\n disableBodyScroll();\n\n return (): void => {\n enableBodyScroll();\n };\n }, []);\n\n // Measure header and footer heights\n useEffect(() => {\n const updateHeights = (): void => {\n if (headerRef.current) {\n setHeaderHeight(headerRef.current.offsetHeight);\n }\n if (footerRef.current) {\n setFooterHeight(footerRef.current.offsetHeight);\n }\n };\n\n updateHeights();\n\n // Update heights when content changes\n const resizeObserver = new ResizeObserver(updateHeights);\n if (headerRef.current) {\n resizeObserver.observe(headerRef.current);\n }\n if (footerRef.current) {\n resizeObserver.observe(footerRef.current);\n }\n\n return (): void => {\n resizeObserver.disconnect();\n };\n }, [hasFooterContent]);\n\n // Open animation.\n useEffect(() => {\n if (!overlayRef.current || !containerRef.current) return;\n\n if (!isPresent) {\n closeDrawer();\n return;\n }\n\n if (isMobile) {\n animate(containerRef.current, { y: '0' }, { duration: 0.3, ease: 'easeInOut' });\n } else {\n animate(containerRef.current, { x: '0' }, { duration: 0.3, ease: 'easeInOut' });\n }\n\n animate(overlayRef.current, { opacity: 1, pointerEvents: 'auto' }, { duration: 0.3, ease: 'easeInOut' });\n }, [isPresent]);\n\n const handleCTA = (callback?: () => void): void => {\n if (callback) {\n callback();\n }\n };\n\n useEffect(() => {\n titleRef.current?.focus();\n }, [title]);\n\n return (\n <div className={styles.drawer} ref={scope} style={{ zIndex }} data-analyticsid={AnalyticsId.Drawer}>\n <div className={styles.drawer__overlay} ref={overlayRef} aria-hidden=\"true\" />\n <div\n className={classNames(styles.drawer__container, {\n [styles['drawer__container--right']]: desktopDirection === 'right',\n })}\n ref={containerRef}\n role=\"dialog\"\n aria-modal=\"true\"\n tabIndex={-1}\n {...ariaLabelAttributes}\n >\n <div className={styles.drawer__container__inner}>\n <div className={headerStyling} ref={headerRef}>\n <Title\n id={ariaLabelAttributes?.['aria-labelledby']}\n className={styles['drawer__header__title']}\n htmlMarkup={titleHtmlMarkup}\n appearance=\"title3\"\n ref={titleRef}\n tabIndex={-1}\n >\n {title}\n </Title>\n {withBackButton && onRequestBack !== undefined && (\n <DrawerBackButton\n ariaLabel={mergedResources.ariaLabelBackButton}\n onClick={onRequestBack}\n className={styles['drawer__header__back-button']}\n />\n )}\n {!noCloseButton && onRequestClose != undefined && (\n <Close\n ariaLabel={mergedResources.ariaLabelCloseBtn}\n color={closeColor}\n onClick={onRequestClose}\n className={styles['drawer__header__close-button']}\n />\n )}\n </div>\n <div\n className={classNames(styles['drawer__content__shadow'], styles['drawer__content__shadow--top'])}\n style={{\n opacity: !topContentVisible && contentIsScrollable ? 1 : 0,\n top: headerHeight,\n }}\n />\n <div\n className={classNames(styles.drawer__content, contentClassName)}\n tabIndex={contentIsScrollable ? 0 : undefined}\n role={contentIsScrollable ? 'region' : undefined}\n {...(contentIsScrollable ? ariaLabelAttributes : {})}\n ref={contentRef}\n >\n <div ref={topContent} />\n <div className={styles['drawer__content__children']}>{children}</div>\n <div ref={bottomContent} style={{ height: '1px' }} />\n </div>\n <div\n className={classNames(styles['drawer__content__shadow'], styles['drawer__content__shadow--bottom'])}\n style={{\n opacity: !bottomContentVisible && contentIsScrollable ? 1 : 0,\n bottom: hasFooterContent ? footerHeight : 0,\n }}\n />\n </div>\n {hasFooterContent && (\n <div className={styles.drawer__footer} ref={footerRef}>\n {footerContent ? (\n footerContent\n ) : (\n <>\n {onPrimaryAction && <Button onClick={() => handleCTA(onPrimaryAction)}>{primaryActionText}</Button>}\n {onSecondaryAction && (\n <Button variant=\"borderless\" onClick={() => handleCTA(onSecondaryAction)}>\n {secondaryActionText}\n </Button>\n )}\n </>\n )}\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default Drawer;\n","import Drawer from './Drawer';\nexport * from './Drawer';\nexport default Drawer;\n"],"mappings":"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"}
@@ -8,24 +8,29 @@
8
8
 
9
9
  $dark-mode-disabled-transparrent: #ffffffb3;
10
10
  $with-icons: // icon-class, size-class, padding-left, padding-right, padding-left desktop, padding-right desktop, svg-margin-left, svg-margin-right, svg-margin-left desktop, svg-margin-right desktop
11
- 'left-icon' 'normal' spacers.getSpacer(xs) spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) 0 spacers.getSpacer(3xs) 0
11
+ 'left-icon' 'medium' spacers.getSpacer(xs) spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) 0 spacers.getSpacer(3xs) 0
12
12
  spacers.getSpacer(2xs),
13
- 'right-icon' 'normal' spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(3xs) 0
13
+ 'right-icon' 'medium' spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(3xs) 0
14
14
  spacers.getSpacer(2xs) 0,
15
- 'left-icon' 'large' spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(s) spacers.getSpacer(l) 0 spacers.getSpacer(2xs) 0
16
- spacers.getSpacer(xs),
17
- 'right-icon' 'large' spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(l) spacers.getSpacer(s) spacers.getSpacer(2xs) 0
18
- spacers.getSpacer(xs) 0,
19
- 'arrow' 'normal' spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(m) 0
15
+ 'left-icon' 'large-non-borderless' spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(s) spacers.getSpacer(l) 0
16
+ spacers.getSpacer(2xs) 0 spacers.getSpacer(xs),
17
+ 'right-icon' 'large-non-borderless' spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(l) spacers.getSpacer(s)
18
+ spacers.getSpacer(2xs) 0 spacers.getSpacer(xs) 0,
19
+ 'arrow' 'medium' spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(m) 0
20
20
  spacers.getSpacer(l) 0,
21
- 'arrow' 'large' spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(l) spacers.getSpacer(xs) spacers.getSpacer(l) 0
22
- spacers.getSpacer(xl) 0,
23
- 'arrow--both-icons' 'normal' 0 0 0 0 spacers.getSpacer(s) 0 spacers.getSpacer(m) 0,
24
- 'arrow--both-icons' 'large' 0 0 0 0 spacers.getSpacer(m) 0 spacers.getSpacer(l) 0,
25
- 'only-icon' 'normal' 0.062rem 0.062rem 0.375rem 0.375rem 0 0 0 0,
26
- 'only-icon' 'large' 0.312rem 0.312rem spacers.getSpacer(3xs) spacers.getSpacer(3xs) 0 0 0 0,
27
- 'both-icons' 'normal' spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) 0 0 0 0,
28
- 'both-icons' 'large' spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) 0 0 0 0;
21
+ 'arrow' 'large-non-borderless' spacers.getSpacer(m) spacers.getSpacer(xs) spacers.getSpacer(l) spacers.getSpacer(xs) spacers.getSpacer(l)
22
+ 0 spacers.getSpacer(xl) 0,
23
+ 'arrow--both-icons' 'medium' 0 0 0 0 spacers.getSpacer(s) 0 spacers.getSpacer(m) 0,
24
+ 'arrow--both-icons' 'large-non-borderless' 0 0 0 0 spacers.getSpacer(m) 0 spacers.getSpacer(l) 0,
25
+ 'only-icon' 'medium' 0.0625rem 0.0625rem 0.375rem 0.375rem 0 0 0 0,
26
+ 'only-icon' 'large-non-borderless' 0.312rem 0.312rem spacers.getSpacer(3xs) spacers.getSpacer(3xs) 0 0 0 0,
27
+ 'both-icons' 'medium' spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) 0 0 0 0,
28
+ 'both-icons' 'large-non-borderless' spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) spacers.getSpacer(xs) 0 0 0 0,
29
+ 'left-icon' 'large-borderless' spacers.getSpacer(xs) spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) 0
30
+ spacers.getSpacer(3xs) 0 spacers.getSpacer(3xs),
31
+ 'right-icon' 'large-borderless' spacers.getSpacer(s) spacers.getSpacer(xs) spacers.getSpacer(m) spacers.getSpacer(xs)
32
+ spacers.getSpacer(3xs) 0 spacers.getSpacer(3xs) 0,
33
+ 'only-icon' 'large-borderless' 0 0 0.0625rem 0.0625rem 0 0 0 0;
29
34
 
30
35
  // Brukes til å aktivere hover styling uten at button hovres
31
36
  @mixin outline-borderless-hover {
@@ -44,6 +49,8 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
44
49
 
45
50
  @if $with-uu-border {
46
51
  border: 1px solid var(--color-action-border-ondark-focus);
52
+ } @else {
53
+ border: none;
47
54
  }
48
55
  }
49
56
 
@@ -259,7 +266,7 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
259
266
  line-height: 1.5rem;
260
267
  }
261
268
 
262
- &--large {
269
+ &--large-non-borderless {
263
270
  min-height: 3.5rem;
264
271
  padding: 0 spacers.getSpacer(l);
265
272
  font-size: 1.3125rem;
@@ -272,6 +279,16 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
272
279
  }
273
280
  }
274
281
 
282
+ // Medium box sizing with large font-size, used for borderless + large
283
+ &--large-borderless {
284
+ font-size: 1.3125rem;
285
+
286
+ @media (min-width: map.get(breakpoints.$grid-breakpoints, md)) {
287
+ font-size: font-settings.$font-size-lg;
288
+ line-height: 1.5rem;
289
+ }
290
+ }
291
+
275
292
  @each $icon-class, $size-class, $pl, $pr, $pld, $prd, $svgml, $svgmr, $svgmld, $svgmrd in $with-icons {
276
293
  &--#{$icon-class}#{&}--#{$size-class} {
277
294
  padding-left: $pl;
@@ -320,6 +337,8 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
320
337
  &--borderless {
321
338
  @include outline-borderless-background(transparent, var(--color-action-background-transparent-onlight-hover));
322
339
 
340
+ border: none;
341
+
323
342
  :focus > & {
324
343
  @include focus-shadow(false);
325
344
 
@@ -408,6 +427,10 @@ $with-icons: // icon-class, size-class, padding-left, padding-right, padding-lef
408
427
  @include text-color(palette.$cherry600, palette.$cherry700);
409
428
  }
410
429
 
430
+ &--only-icon {
431
+ justify-content: center;
432
+ }
433
+
411
434
  /* stylelint-disable-next-line */
412
435
  &--only-icon &__text {
413
436
  @include sr-only;
@@ -15,9 +15,10 @@ export type Styles = {
15
15
  'button--borderless': string;
16
16
  'button--both-icons': string;
17
17
  'button--destructive': string;
18
- 'button--large': string;
18
+ 'button--large-borderless': string;
19
+ 'button--large-non-borderless': string;
19
20
  'button--left-icon': string;
20
- 'button--normal': string;
21
+ 'button--medium': string;
21
22
  'button--on-dark': string;
22
23
  'button--only-icon': string;
23
24
  'button--outline': string;
@@ -0,0 +1,10 @@
1
+ export interface DrawerBackButtonProps {
2
+ /** Function is called when user clicks the button */
3
+ onClick?: (e?: React.MouseEvent<HTMLElement, MouseEvent>) => void;
4
+ /** Sets the aria-label of the button */
5
+ ariaLabel?: string;
6
+ /** Adds custom classes to the element. */
7
+ className?: string;
8
+ }
9
+ declare const DrawerBackButton: React.FC<DrawerBackButtonProps>;
10
+ export default DrawerBackButton;
@@ -0,0 +1,52 @@
1
+ @use 'sass:map';
2
+ @use '../../scss/breakpoints' as breakpoints;
3
+ @import '../../scss/supernova/styles/colors.css';
4
+
5
+ $desktop-size: 3rem;
6
+ $mobile-inner-size: 2.375rem;
7
+ $mobile-outer-size: 2.75rem;
8
+
9
+ .back-button {
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ height: $mobile-outer-size;
14
+ width: $mobile-outer-size;
15
+ padding: 0;
16
+ border: 0;
17
+ background-color: transparent;
18
+ cursor: pointer;
19
+
20
+ &:focus-visible {
21
+ outline: none;
22
+ }
23
+
24
+ @media (min-width: map.get(breakpoints.$grid-breakpoints, md)) {
25
+ height: $desktop-size;
26
+ width: $desktop-size;
27
+ }
28
+
29
+ &__inner-container {
30
+ width: $mobile-inner-size;
31
+ height: $mobile-inner-size;
32
+
33
+ @media (min-width: map.get(breakpoints.$grid-breakpoints, md)) {
34
+ height: $desktop-size;
35
+ width: $desktop-size;
36
+ }
37
+
38
+ :hover > & {
39
+ background-color: var(--color-action-background-transparent-onlight-hover);
40
+ }
41
+
42
+ :active > & {
43
+ background-color: var(--color-action-background-transparent-onlight-active);
44
+ }
45
+
46
+ :focus-visible > & {
47
+ outline: 3px solid var(--color-action-border-onlight-focus);
48
+ border-radius: 0;
49
+ border: 0;
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,10 @@
1
+ export type Styles = {
2
+ 'back-button': string;
3
+ 'back-button__inner-container': string;
4
+ };
5
+
6
+ export type ClassNames = keyof Styles;
7
+
8
+ declare const styles: Styles;
9
+
10
+ export default styles;
@@ -98,15 +98,6 @@
98
98
  &__back-button {
99
99
  // Moves the button visually to the left but keeps it in the DOM order for screen readers and keyboard navigation
100
100
  order: -1;
101
-
102
- // Temporary fix for the back button, until we decide if we want to implement this more properly
103
- width: 48px;
104
- height: 48px;
105
-
106
- svg {
107
- width: 48px;
108
- height: 48px;
109
- }
110
101
  }
111
102
  }
112
103
 
@@ -15,9 +15,10 @@ export type Styles = {
15
15
  'button--borderless': string;
16
16
  'button--both-icons': string;
17
17
  'button--destructive': string;
18
- 'button--large': string;
18
+ 'button--large-borderless': string;
19
+ 'button--large-non-borderless': string;
19
20
  'button--left-icon': string;
20
- 'button--normal': string;
21
+ 'button--medium': string;
21
22
  'button--on-dark': string;
22
23
  'button--only-icon': string;
23
24
  'button--outline': string;
@@ -15,9 +15,10 @@ export type Styles = {
15
15
  'button--borderless': string;
16
16
  'button--both-icons': string;
17
17
  'button--destructive': string;
18
- 'button--large': string;
18
+ 'button--large-borderless': string;
19
+ 'button--large-non-borderless': string;
19
20
  'button--left-icon': string;
20
- 'button--normal': string;
21
+ 'button--medium': string;
21
22
  'button--on-dark': string;
22
23
  'button--only-icon': string;
23
24
  'button--outline': string;
@@ -15,11 +15,16 @@ var HN_Designsystem_Tabs_nb_NO_default = {
15
15
  ariaLabelRightButton: "Scroll til høyre",
16
16
  ariaLabelLeftButton: "Scroll til venstre"
17
17
  };
18
+ var HN_Designsystem_Tabs_se_NO_default = {
19
+ ariaLabelRightButton: "Sirdde olgeš guvlui",
20
+ ariaLabelLeftButton: "Sirdde gurut guvlui"
21
+ };
18
22
  //#endregion
19
23
  //#region src/components/Tabs/resourceHelper.ts
20
24
  var getResources = (language) => {
21
25
  switch (language) {
22
26
  case LanguageLocales.ENGLISH: return HN_Designsystem_Tabs_en_GB_default;
27
+ case LanguageLocales.SAMI_NORTHERN: return HN_Designsystem_Tabs_se_NO_default;
23
28
  case LanguageLocales.NORWEGIAN:
24
29
  default: return HN_Designsystem_Tabs_nb_NO_default;
25
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/resources/HN.Designsystem.Tabs.en-GB.json","../../../src/resources/HN.Designsystem.Tabs.nb-NO.json","../../../src/components/Tabs/resourceHelper.ts","../../../src/components/Tabs/Tabs.tsx","../../../src/components/Tabs/index.ts"],"sourcesContent":["{\n \"ariaLabelRightButton\": \"Scroll right\",\n \"ariaLabelLeftButton\": \"Scroll left\"\n}\n","{\n \"ariaLabelRightButton\": \"Scroll til høyre\",\n \"ariaLabelLeftButton\": \"Scroll til venstre\"\n}\n","import type { HNDesignsystemTabs } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Tabs.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Tabs.nb-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemTabs => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import React, { useState, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport type { HNDesignsystemTabs } from '../../resources/Resources';\nimport type { PaletteNames } from '../../theme/palette';\n\nimport { getResources } from './resourceHelper';\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport { LanguageLocales } from '../../constants';\nimport { useLanguage } from '../../hooks/useLanguage';\nimport designsystemlayout from '../../scss/layout.module.scss';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsOnColor = 'onblueberry' | 'onneutral' | 'onwhite';\n\nexport interface TabsProps {\n children?: React.ReactNode;\n /** Controlled state for Tabs component */\n activeTab?: number;\n /** Adds custom classes to the element. */\n className?: string;\n /** Sets the color of the tabs. Default: white */\n color?: TabsColors;\n /** Sets wether the component should use the container-breakout class. Default: true */\n containerBreakout?: boolean;\n /** Sets the background color of the tabs. Can only be used when the color is set to white. Default: onwhite */\n onColor?: TabsOnColor;\n /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Resources for component */\n resources?: Partial<HNDesignsystemTabs>;\n /** Overrides the default z-index of the tabs header */\n zIndex?: number;\n}\n\nexport const TabsRoot: React.FC<TabsProps> = ({\n activeTab,\n children,\n className,\n color = 'white',\n containerBreakout = true,\n onColor = 'onwhite',\n sticky = true,\n testId,\n resources,\n zIndex,\n}) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n\n const mergedResources: HNDesignsystemTabs = {\n ...defaultResources,\n ...resources,\n };\n\n let onColorUsed: TabsOnColor = 'onwhite';\n if (color === 'white') {\n onColorUsed = onColor;\n }\n\n const onValueChange = (newValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n return (\n <div className={classNames(className, containerBreakout && designsystemlayout['container-breakout'])} data-testid={testId}>\n <div\n ref={tabListRef}\n className={classNames(styles['tab-list-wrapper'], {\n [styles['tab-list-wrapper--sticky']]: sticky,\n })}\n style={{\n zIndex: zIndex,\n }}\n >\n <TabList\n onTabListClick={(index: number) => onValueChange(index)}\n selectedTab={activeTabIndex}\n color={color}\n onColor={onColorUsed}\n ariaLabelLeftButton={mergedResources.ariaLabelLeftButton}\n ariaLabelRightButton={mergedResources.ariaLabelRightButton}\n >\n {children}\n </TabList>\n <div className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`])}></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: '-50px' }}>\n <TabPanel ref={tabPanelRef} color={color} isFirst={activeTabIndex == 0}>\n {React.Children.toArray(children)[activeTabIndex]}\n </TabPanel>\n </div>\n </div>\n );\n};\n\ntype TabsComponent = typeof TabsRoot & {\n Tab: typeof Tab;\n};\nconst Tabs = TabsRoot as TabsComponent;\nTabsRoot.displayName = 'Tabs';\nTabs.displayName = 'Tabs';\nTabs.Tab = Tab;\nTabs.Tab.displayName = 'Tabs.Tab';\n\nexport default Tabs;\n","import Tabs from './Tabs';\nexport * from './Tabs';\nexport default Tabs;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AEMA,IAAa,gBAAgB,aAAkD;CAC7E,QAAQ,UAAR;EACE,KAAK,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAgB;EACrB,SACE,OAAO;CACX;AACF;;;AC6BA,IAAa,YAAiC,EAC5C,WACA,UACA,WACA,QAAQ,SACR,oBAAoB,MACpB,UAAU,WACV,SAAS,MACT,QACA,WACA,aACI;CACJ,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,CAAC;CAC5D,MAAM,UAAU,OAAuB,IAAI;CAC3C,MAAM,cAAc,OAAuB,IAAI;CAC/C,MAAM,aAAa,OAAuB,IAAI;CAC9C,MAAM,EAAE,aAAa,YAA6B,gBAAgB,SAAS;CAG3E,MAAM,kBAAsC;EAC1C,GAHuB,aAAa,QAGjC;EACH,GAAG;CACL;CAEA,IAAI,cAA2B;CAC/B,IAAI,UAAU,SACZ,cAAc;CAGhB,MAAM,iBAAiB,aAA2B;EAChD,IAAI,CAAC,cACH,qBAAqB,QAAQ;CAEjC;CAEA,MAAM,iBAAiB,eAAe,YAAY;CAElD,OACE,qBAAC,OAAD;EAAK,WAAW,WAAW,WAAW,qBAAqB,mBAAmB,qBAAqB;EAAG,eAAa;YAAnH,CACE,qBAAC,OAAD;GACE,KAAK;GACL,WAAW,WAAW,OAAO,qBAAqB,GAC/C,OAAO,8BAA8B,OACxC,CAAC;GACD,OAAO,EACG,OACV;aAPF,CASE,oBAAC,iBAAD;IACE,iBAAiB,UAAkB,cAAc,KAAK;IACtD,aAAa;IACN;IACP,SAAS;IACT,qBAAqB,gBAAgB;IACrC,sBAAsB,gBAAgB;IAErC;GACM,CAAA,GACT,oBAAC,OAAD,EAAK,WAAW,WAAW,OAAO,kBAAkB,OAAO,kBAAkB,QAAQ,EAAQ,CAAA,CAC1F;MACL,oBAAC,OAAD;GAAK,KAAK;GAAS,OAAO,EAAE,WAAW,QAAQ;aAC7C,oBAAC,kBAAD;IAAU,KAAK;IAAoB;IAAO,SAAS,kBAAkB;cAClE,MAAM,SAAS,QAAQ,QAAQ,EAAE;GAC1B,CAAA;EACP,CAAA,CACF;;AAET;AAKA,IAAM,OAAO;AACb,SAAS,cAAc;AACvB,KAAK,cAAc;AACnB,KAAK,MAAM;AACX,KAAK,IAAI,cAAc;;;ACtHvB,IAAA,eAAe"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/resources/HN.Designsystem.Tabs.en-GB.json","../../../src/resources/HN.Designsystem.Tabs.nb-NO.json","../../../src/resources/HN.Designsystem.Tabs.se-NO.json","../../../src/components/Tabs/resourceHelper.ts","../../../src/components/Tabs/Tabs.tsx","../../../src/components/Tabs/index.ts"],"sourcesContent":["{\n \"ariaLabelRightButton\": \"Scroll right\",\n \"ariaLabelLeftButton\": \"Scroll left\"\n}\n","{\n \"ariaLabelRightButton\": \"Scroll til høyre\",\n \"ariaLabelLeftButton\": \"Scroll til venstre\"\n}\n","{\n \"ariaLabelRightButton\": \"Sirdde olgeš guvlui\",\n \"ariaLabelLeftButton\": \"Sirdde gurut guvlui\"\n}\n","import type { HNDesignsystemTabs } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Tabs.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Tabs.nb-NO.json';\nimport seNO from '../../resources/HN.Designsystem.Tabs.se-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemTabs => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.SAMI_NORTHERN:\n return seNO;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n","import React, { useState, useRef } from 'react';\n\nimport classNames from 'classnames';\n\nimport type { HNDesignsystemTabs } from '../../resources/Resources';\nimport type { PaletteNames } from '../../theme/palette';\n\nimport { getResources } from './resourceHelper';\nimport Tab from './Tab';\nimport TabList from './TabList';\nimport TabPanel from './TabPanel';\nimport { LanguageLocales } from '../../constants';\nimport { useLanguage } from '../../hooks/useLanguage';\nimport designsystemlayout from '../../scss/layout.module.scss';\n\nimport styles from './styles.module.scss';\n\nexport type { TabProps } from './Tab';\nexport type TabsColors = Extract<PaletteNames, 'blueberry' | 'neutral' | 'white'>;\nexport type TabsOnColor = 'onblueberry' | 'onneutral' | 'onwhite';\n\nexport interface TabsProps {\n children?: React.ReactNode;\n /** Controlled state for Tabs component */\n activeTab?: number;\n /** Adds custom classes to the element. */\n className?: string;\n /** Sets the color of the tabs. Default: white */\n color?: TabsColors;\n /** Sets wether the component should use the container-breakout class. Default: true */\n containerBreakout?: boolean;\n /** Sets the background color of the tabs. Can only be used when the color is set to white. Default: onwhite */\n onColor?: TabsOnColor;\n /** Whether the tab list should be sticky */\n sticky?: boolean;\n /** Sets the data-testid attribute. */\n testId?: string;\n /** Resources for component */\n resources?: Partial<HNDesignsystemTabs>;\n /** Overrides the default z-index of the tabs header */\n zIndex?: number;\n}\n\nexport const TabsRoot: React.FC<TabsProps> = ({\n activeTab,\n children,\n className,\n color = 'white',\n containerBreakout = true,\n onColor = 'onwhite',\n sticky = true,\n testId,\n resources,\n zIndex,\n}) => {\n const isControlled = activeTab !== undefined;\n const [uncontrolledValue, setUncontrolledValue] = useState(0);\n const tabsRef = useRef<HTMLDivElement>(null);\n const tabPanelRef = useRef<HTMLDivElement>(null);\n const tabListRef = useRef<HTMLDivElement>(null);\n const { language } = useLanguage<LanguageLocales>(LanguageLocales.NORWEGIAN);\n const defaultResources = getResources(language);\n\n const mergedResources: HNDesignsystemTabs = {\n ...defaultResources,\n ...resources,\n };\n\n let onColorUsed: TabsOnColor = 'onwhite';\n if (color === 'white') {\n onColorUsed = onColor;\n }\n\n const onValueChange = (newValue: number): void => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n };\n\n const activeTabIndex = isControlled ? activeTab : uncontrolledValue;\n\n return (\n <div className={classNames(className, containerBreakout && designsystemlayout['container-breakout'])} data-testid={testId}>\n <div\n ref={tabListRef}\n className={classNames(styles['tab-list-wrapper'], {\n [styles['tab-list-wrapper--sticky']]: sticky,\n })}\n style={{\n zIndex: zIndex,\n }}\n >\n <TabList\n onTabListClick={(index: number) => onValueChange(index)}\n selectedTab={activeTabIndex}\n color={color}\n onColor={onColorUsed}\n ariaLabelLeftButton={mergedResources.ariaLabelLeftButton}\n ariaLabelRightButton={mergedResources.ariaLabelRightButton}\n >\n {children}\n </TabList>\n <div className={classNames(styles['panel-wrapper'], styles[`panel-wrapper--${color}`])}></div>\n </div>\n <div ref={tabsRef} style={{ marginTop: '-50px' }}>\n <TabPanel ref={tabPanelRef} color={color} isFirst={activeTabIndex == 0}>\n {React.Children.toArray(children)[activeTabIndex]}\n </TabPanel>\n </div>\n </div>\n );\n};\n\ntype TabsComponent = typeof TabsRoot & {\n Tab: typeof Tab;\n};\nconst Tabs = TabsRoot as TabsComponent;\nTabsRoot.displayName = 'Tabs';\nTabs.displayName = 'Tabs';\nTabs.Tab = Tab;\nTabs.Tab.displayName = 'Tabs.Tab';\n\nexport default Tabs;\n","import Tabs from './Tabs';\nexport * from './Tabs';\nexport default Tabs;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AGOA,IAAa,gBAAgB,aAAkD;CAC7E,QAAQ,UAAR;EACE,KAAK,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAgB,eACnB,OAAO;EACT,KAAK,gBAAgB;EACrB,SACE,OAAO;CACX;AACF;;;AC0BA,IAAa,YAAiC,EAC5C,WACA,UACA,WACA,QAAQ,SACR,oBAAoB,MACpB,UAAU,WACV,SAAS,MACT,QACA,WACA,aACI;CACJ,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,CAAC,mBAAmB,wBAAwB,SAAS,CAAC;CAC5D,MAAM,UAAU,OAAuB,IAAI;CAC3C,MAAM,cAAc,OAAuB,IAAI;CAC/C,MAAM,aAAa,OAAuB,IAAI;CAC9C,MAAM,EAAE,aAAa,YAA6B,gBAAgB,SAAS;CAG3E,MAAM,kBAAsC;EAC1C,GAHuB,aAAa,QAGjC;EACH,GAAG;CACL;CAEA,IAAI,cAA2B;CAC/B,IAAI,UAAU,SACZ,cAAc;CAGhB,MAAM,iBAAiB,aAA2B;EAChD,IAAI,CAAC,cACH,qBAAqB,QAAQ;CAEjC;CAEA,MAAM,iBAAiB,eAAe,YAAY;CAElD,OACE,qBAAC,OAAD;EAAK,WAAW,WAAW,WAAW,qBAAqB,mBAAmB,qBAAqB;EAAG,eAAa;YAAnH,CACE,qBAAC,OAAD;GACE,KAAK;GACL,WAAW,WAAW,OAAO,qBAAqB,GAC/C,OAAO,8BAA8B,OACxC,CAAC;GACD,OAAO,EACG,OACV;aAPF,CASE,oBAAC,iBAAD;IACE,iBAAiB,UAAkB,cAAc,KAAK;IACtD,aAAa;IACN;IACP,SAAS;IACT,qBAAqB,gBAAgB;IACrC,sBAAsB,gBAAgB;IAErC;GACM,CAAA,GACT,oBAAC,OAAD,EAAK,WAAW,WAAW,OAAO,kBAAkB,OAAO,kBAAkB,QAAQ,EAAQ,CAAA,CAC1F;MACL,oBAAC,OAAD;GAAK,KAAK;GAAS,OAAO,EAAE,WAAW,QAAQ;aAC7C,oBAAC,kBAAD;IAAU,KAAK;IAAoB;IAAO,SAAS,kBAAkB;cAClE,MAAM,SAAS,QAAQ,QAAQ,EAAE;GAC1B,CAAA;EACP,CAAA,CACF;;AAET;AAKA,IAAM,OAAO;AACb,SAAS,cAAc;AACvB,KAAK,cAAc;AACnB,KAAK,MAAM;AACX,KAAK,IAAI,cAAc;;;ACtHvB,IAAA,eAAe"}
@@ -9,7 +9,8 @@ var HN_Designsystem_Filter_en_GB_default = {
9
9
  searchClearButtonAriaLabel: "Reset",
10
10
  searchButtonAriaLabel: "Search",
11
11
  loadingText: "Loading results",
12
- resultsText: "{0} results"
12
+ resultsText: "{0} results",
13
+ activeFiltersListLabel: "Aktive filter"
13
14
  };
14
15
  var HN_Designsystem_Filter_nb_NO_default = {
15
16
  filterButtonText: "Finn ...",
@@ -21,13 +22,42 @@ var HN_Designsystem_Filter_nb_NO_default = {
21
22
  searchClearButtonAriaLabel: "Nullstill",
22
23
  searchButtonAriaLabel: "Søk",
23
24
  loadingText: "Henter treff",
24
- resultsText: "{0} treff"
25
+ resultsText: "{0} treff",
26
+ activeFiltersListLabel: "Aktive filter"
27
+ };
28
+ var HN_Designsystem_Filter_nn_NO_default = {
29
+ filterButtonText: "Finn ...",
30
+ sortLabel: "Sortering",
31
+ resetButtonText: "Nullstill",
32
+ showButtonText: "Vis treff",
33
+ filterOverviewTitle: "Finn ...",
34
+ searchPlaceholder: "Søk i lista",
35
+ searchClearButtonAriaLabel: "Nullstill",
36
+ searchButtonAriaLabel: "Søk",
37
+ loadingText: "Hentar treff",
38
+ resultsText: "{0} treff",
39
+ activeFiltersListLabel: "Aktive filter"
40
+ };
41
+ var HN_Designsystem_Filter_se_NO_default = {
42
+ filterButtonText: "Oza ...",
43
+ sortLabel: "Sirren",
44
+ resetButtonText: "Bija ruovttuluotta",
45
+ showButtonText: "Čájet deaivan",
46
+ filterOverviewTitle: "Oza ...",
47
+ searchPlaceholder: "Oza listtus",
48
+ searchClearButtonAriaLabel: "Bija ruovttuluotta",
49
+ searchButtonAriaLabel: "Oza",
50
+ loadingText: "Viežžá",
51
+ resultsText: "{0} deaivan",
52
+ activeFiltersListLabel: "Aktive filter"
25
53
  };
26
54
  //#endregion
27
55
  //#region src/components/Filter/resourceHelper.ts
28
56
  var getResources = (language) => {
29
57
  switch (language) {
30
58
  case LanguageLocales.ENGLISH: return HN_Designsystem_Filter_en_GB_default;
59
+ case LanguageLocales.NORWEGIAN_NYNORSK: return HN_Designsystem_Filter_nn_NO_default;
60
+ case LanguageLocales.SAMI_NORTHERN: return HN_Designsystem_Filter_se_NO_default;
31
61
  case LanguageLocales.NORWEGIAN:
32
62
  default: return HN_Designsystem_Filter_nb_NO_default;
33
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resourceHelper.js","names":[],"sources":["../src/resources/HN.Designsystem.Filter.en-GB.json","../src/resources/HN.Designsystem.Filter.nb-NO.json","../src/components/Filter/resourceHelper.ts"],"sourcesContent":["{\n \"filterButtonText\": \"Find ...\",\n \"sortLabel\": \"Sorting\",\n \"resetButtonText\": \"Reset\",\n \"showButtonText\": \"Show results\",\n \"filterOverviewTitle\": \"Find ...\",\n \"searchPlaceholder\": \"Search the list\",\n \"searchClearButtonAriaLabel\": \"Reset\",\n \"searchButtonAriaLabel\": \"Search\",\n \"loadingText\": \"Loading results\",\n \"resultsText\": \"{0} results\"\n}\n","{\n \"filterButtonText\": \"Finn ...\",\n \"sortLabel\": \"Sortering\",\n \"resetButtonText\": \"Nullstill\",\n \"showButtonText\": \"Vis treff\",\n \"filterOverviewTitle\": \"Finn ...\",\n \"searchPlaceholder\": \"Søk i listen\",\n \"searchClearButtonAriaLabel\": \"Nullstill\",\n \"searchButtonAriaLabel\": \"Søk\",\n \"loadingText\": \"Henter treff\",\n \"resultsText\": \"{0} treff\"\n}\n","import type { HNDesignsystemFilter } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Filter.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Filter.nb-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemFilter => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AEMA,IAAa,gBAAgB,aAAoD;CAC/E,QAAQ,UAAR;EACE,KAAK,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAgB;EACrB,SACE,OAAO;CACX;AACF"}
1
+ {"version":3,"file":"resourceHelper.js","names":[],"sources":["../src/resources/HN.Designsystem.Filter.en-GB.json","../src/resources/HN.Designsystem.Filter.nb-NO.json","../src/resources/HN.Designsystem.Filter.nn-NO.json","../src/resources/HN.Designsystem.Filter.se-NO.json","../src/components/Filter/resourceHelper.ts"],"sourcesContent":["{\n \"filterButtonText\": \"Find ...\",\n \"sortLabel\": \"Sorting\",\n \"resetButtonText\": \"Reset\",\n \"showButtonText\": \"Show results\",\n \"filterOverviewTitle\": \"Find ...\",\n \"searchPlaceholder\": \"Search the list\",\n \"searchClearButtonAriaLabel\": \"Reset\",\n \"searchButtonAriaLabel\": \"Search\",\n \"loadingText\": \"Loading results\",\n \"resultsText\": \"{0} results\",\n \"activeFiltersListLabel\": \"Aktive filter\"\n}\n","{\n \"filterButtonText\": \"Finn ...\",\n \"sortLabel\": \"Sortering\",\n \"resetButtonText\": \"Nullstill\",\n \"showButtonText\": \"Vis treff\",\n \"filterOverviewTitle\": \"Finn ...\",\n \"searchPlaceholder\": \"Søk i listen\",\n \"searchClearButtonAriaLabel\": \"Nullstill\",\n \"searchButtonAriaLabel\": \"Søk\",\n \"loadingText\": \"Henter treff\",\n \"resultsText\": \"{0} treff\",\n \"activeFiltersListLabel\": \"Aktive filter\"\n}\n","{\n \"filterButtonText\": \"Finn ...\",\n \"sortLabel\": \"Sortering\",\n \"resetButtonText\": \"Nullstill\",\n \"showButtonText\": \"Vis treff\",\n \"filterOverviewTitle\": \"Finn ...\",\n \"searchPlaceholder\": \"Søk i lista\",\n \"searchClearButtonAriaLabel\": \"Nullstill\",\n \"searchButtonAriaLabel\": \"Søk\",\n \"loadingText\": \"Hentar treff\",\n \"resultsText\": \"{0} treff\",\n \"activeFiltersListLabel\": \"Aktive filter\"\n}\n","{\n \"filterButtonText\": \"Oza ...\",\n \"sortLabel\": \"Sirren\",\n \"resetButtonText\": \"Bija ruovttuluotta\",\n \"showButtonText\": \"Čájet deaivan\",\n \"filterOverviewTitle\": \"Oza ...\",\n \"searchPlaceholder\": \"Oza listtus\",\n \"searchClearButtonAriaLabel\": \"Bija ruovttuluotta\",\n \"searchButtonAriaLabel\": \"Oza\",\n \"loadingText\": \"Viežžá\",\n \"resultsText\": \"{0} deaivan\",\n \"activeFiltersListLabel\": \"Aktive filter\"\n}\n","import type { HNDesignsystemFilter } from '../../resources/Resources';\n\nimport { LanguageLocales } from '../../constants';\nimport enGB from '../../resources/HN.Designsystem.Filter.en-GB.json';\nimport nbNO from '../../resources/HN.Designsystem.Filter.nb-NO.json';\nimport nnNO from '../../resources/HN.Designsystem.Filter.nn-NO.json';\nimport seNO from '../../resources/HN.Designsystem.Filter.se-NO.json';\n\nexport const getResources = (language: LanguageLocales): HNDesignsystemFilter => {\n switch (language) {\n case LanguageLocales.ENGLISH:\n return enGB;\n case LanguageLocales.NORWEGIAN_NYNORSK:\n return nnNO;\n case LanguageLocales.SAMI_NORTHERN:\n return seNO;\n case LanguageLocales.NORWEGIAN:\n default:\n return nbNO;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AIQA,IAAa,gBAAgB,aAAoD;CAC/E,QAAQ,UAAR;EACE,KAAK,gBAAgB,SACnB,OAAO;EACT,KAAK,gBAAgB,mBACnB,OAAO;EACT,KAAK,gBAAgB,eACnB,OAAO;EACT,KAAK,gBAAgB;EACrB,SACE,OAAO;CACX;AACF"}
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ "ariaLabelCloseBtn": "Gidde",
3
+ "ariaLabelBackButton": "Mana ruovttoluotta"
4
+ }
5
+ ;
6
+
7
+ export default _default;
@@ -8,7 +8,8 @@ declare const _default: {
8
8
  "searchClearButtonAriaLabel": "Reset",
9
9
  "searchButtonAriaLabel": "Search",
10
10
  "loadingText": "Loading results",
11
- "resultsText": "{0} results"
11
+ "resultsText": "{0} results",
12
+ "activeFiltersListLabel": "Aktive filter"
12
13
  }
13
14
  ;
14
15
 
@@ -8,7 +8,8 @@ declare const _default: {
8
8
  "searchClearButtonAriaLabel": "Nullstill",
9
9
  "searchButtonAriaLabel": "Søk",
10
10
  "loadingText": "Henter treff",
11
- "resultsText": "{0} treff"
11
+ "resultsText": "{0} treff",
12
+ "activeFiltersListLabel": "Aktive filter"
12
13
  }
13
14
  ;
14
15
 
@@ -0,0 +1,16 @@
1
+ declare const _default: {
2
+ "filterButtonText": "Finn ...",
3
+ "sortLabel": "Sortering",
4
+ "resetButtonText": "Nullstill",
5
+ "showButtonText": "Vis treff",
6
+ "filterOverviewTitle": "Finn ...",
7
+ "searchPlaceholder": "Søk i lista",
8
+ "searchClearButtonAriaLabel": "Nullstill",
9
+ "searchButtonAriaLabel": "Søk",
10
+ "loadingText": "Hentar treff",
11
+ "resultsText": "{0} treff",
12
+ "activeFiltersListLabel": "Aktive filter"
13
+ }
14
+ ;
15
+
16
+ export default _default;
@@ -0,0 +1,16 @@
1
+ declare const _default: {
2
+ "filterButtonText": "Oza ...",
3
+ "sortLabel": "Sirren",
4
+ "resetButtonText": "Bija ruovttuluotta",
5
+ "showButtonText": "Čájet deaivan",
6
+ "filterOverviewTitle": "Oza ...",
7
+ "searchPlaceholder": "Oza listtus",
8
+ "searchClearButtonAriaLabel": "Bija ruovttuluotta",
9
+ "searchButtonAriaLabel": "Oza",
10
+ "loadingText": "Viežžá",
11
+ "resultsText": "{0} deaivan",
12
+ "activeFiltersListLabel": "Aktive filter"
13
+ }
14
+ ;
15
+
16
+ export default _default;
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ "ariaLabelRightButton": "Sirdde olgeš guvlui",
3
+ "ariaLabelLeftButton": "Sirdde gurut guvlui"
4
+ }
5
+ ;
6
+
7
+ export default _default;
@@ -187,6 +187,10 @@ export type HNDesignsystemFilter = {
187
187
  * {0} treff
188
188
  */
189
189
  resultsText: string;
190
+ /**
191
+ * Aktive filter
192
+ */
193
+ activeFiltersListLabel: string;
190
194
  };
191
195
 
192
196
  export type HNDesignsystemChip = {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@helsenorge/designsystem-react",
3
3
  "sideEffects": false,
4
4
  "private": false,
5
- "version": "15.0.0",
5
+ "version": "15.1.0",
6
6
  "description": "The official design system for Helsenorge built with React.",
7
7
  "repository": {
8
8
  "type": "git",
@@ -834,11 +834,26 @@
834
834
  "import": "./lib/components/VisualRadioGroup/index.js",
835
835
  "require": "./lib/components/VisualRadioGroup/index.js",
836
836
  "default": "./lib/components/VisualRadioGroup/index.js"
837
- }
837
+ },
838
+ "./scss/body": "./scss/_body.scss",
839
+ "./scss/breakpoints": "./scss/_breakpoints.scss",
840
+ "./scss/font-mixins": "./scss/_font-mixins.scss",
841
+ "./scss/font-settings": "./scss/_font-settings.scss",
842
+ "./scss/fonts": "./scss/_fonts.scss",
843
+ "./scss/grid": "./scss/_grid.scss",
844
+ "./scss/icon": "./scss/_icon.scss",
845
+ "./scss/input": "./scss/_input.scss",
846
+ "./scss/palette": "./scss/_palette.scss",
847
+ "./scss/print": "./scss/_print.scss",
848
+ "./scss/radio-reset": "./scss/_radio-reset.scss",
849
+ "./scss/reset": "./scss/_reset.scss",
850
+ "./scss/screen-reader": "./scss/_screen-reader.scss",
851
+ "./scss/spacers": "./scss/_spacers.scss",
852
+ "./scss/visual-form": "./scss/_visual-form.scss"
838
853
  },
839
854
  "scripts": {
840
855
  "start": "storybook dev -p 3000",
841
- "prebuild": "npm-run-all link-scss clean generate:iconnames generate:illustrationnames generate:cssdefinitions",
856
+ "prebuild": "npm-run-all link-scss clean generate:iconnames generate:illustrationnames generate:cssdefinitions generate:scssexports",
842
857
  "build": "vite build",
843
858
  "postbuild": "node ../build-tools/lib/copy.js --root ../../CHANGELOG.md --include \"src/scss/**/*\" \"src/fonts/**/*\" \"src/components/**/*.module.scss*\" && npm run link-scss",
844
859
  "link-scss": "node __scripts__/link-root-scss.mjs",
@@ -851,6 +866,7 @@
851
866
  "generate:iconnames": "node __scripts__/generateIconNames.mjs",
852
867
  "generate:illustrationnames": "node __scripts__/generateIllustrationNames.mjs",
853
868
  "generate:cssdefinitions": "typed-scss-modules \"src/**/*.module.scss\" --nameFormat none --exportType default --includePaths node_modules ../../node_modules",
869
+ "generate:scssexports": "node __scripts__/gen-scss-exports.mjs",
854
870
  "eslint": "eslint \"src/**/*.{ts,tsx}\"",
855
871
  "eslint:fix": "npm run eslint -- --fix",
856
872
  "stylelint": "stylelint \"src/**/*.{css,scss}\"",