@vygruppen/spor-react 13.0.3 → 13.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.turbo/turbo-build.log +12 -12
  2. package/.turbo/turbo-postinstall.log +2 -2
  3. package/CHANGELOG.md +24 -0
  4. package/dist/index.cjs +509 -427
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +178 -177
  7. package/dist/index.d.ts +178 -177
  8. package/dist/index.mjs +509 -426
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +6 -10
  11. package/src/alert/AlertIcon.tsx +2 -2
  12. package/src/alert/ServiceAlert.tsx +2 -1
  13. package/src/calendar/CalendarCell.tsx +4 -4
  14. package/src/datepicker/CalendarHeader.tsx +1 -1
  15. package/src/dialog/Drawer.tsx +1 -1
  16. package/src/input/CardSelect.tsx +4 -4
  17. package/src/input/Combobox.tsx +1 -1
  18. package/src/input/Field.tsx +1 -1
  19. package/src/input/Menu.tsx +9 -5
  20. package/src/input/Popover.tsx +9 -7
  21. package/src/linjetag/LineIcon.tsx +1 -1
  22. package/src/loader/ColorInlineLoader.tsx +2 -1
  23. package/src/loader/ColorSpinner.tsx +2 -1
  24. package/src/loader/ContentLoader.tsx +2 -1
  25. package/src/loader/DarkFullScreenLoader.tsx +2 -1
  26. package/src/loader/DarkInlineLoader.tsx +2 -1
  27. package/src/loader/DarkSpinner.tsx +2 -1
  28. package/src/loader/LightFullScreenLoader.tsx +2 -1
  29. package/src/loader/LightInlineLoader.tsx +2 -1
  30. package/src/loader/LightSpinner.tsx +2 -1
  31. package/src/loader/Lottie.tsx +3 -2
  32. package/src/loader/text.ts +15 -0
  33. package/src/stepper/StepperStep.tsx +2 -2
  34. package/src/theme/recipes/badge.ts +120 -48
  35. package/src/theme/recipes/button.ts +22 -22
  36. package/src/theme/recipes/close-button.ts +2 -2
  37. package/src/theme/recipes/input.ts +9 -9
  38. package/src/theme/recipes/link.ts +1 -1
  39. package/src/theme/recipes/pressable-card.ts +12 -12
  40. package/src/theme/recipes/skeleton.ts +1 -1
  41. package/src/theme/recipes/static-card.ts +8 -8
  42. package/src/theme/semantic-tokens/colors.ts +1 -1
  43. package/src/theme/slot-recipes/accordion.ts +10 -10
  44. package/src/theme/slot-recipes/alert-expandable.ts +35 -35
  45. package/src/theme/slot-recipes/alert-service.ts +10 -10
  46. package/src/theme/slot-recipes/alert.ts +11 -11
  47. package/src/theme/slot-recipes/autocomplete.ts +5 -5
  48. package/src/theme/slot-recipes/breadcrumb.ts +4 -4
  49. package/src/theme/slot-recipes/checkbox.ts +11 -17
  50. package/src/theme/slot-recipes/choice-chip.ts +21 -21
  51. package/src/theme/slot-recipes/datepicker.ts +29 -29
  52. package/src/theme/slot-recipes/field.ts +3 -3
  53. package/src/theme/slot-recipes/floating-action-button.ts +14 -14
  54. package/src/theme/slot-recipes/input-chip.ts +10 -10
  55. package/src/theme/slot-recipes/listbox.ts +9 -9
  56. package/src/theme/slot-recipes/media-controller-button.ts +9 -9
  57. package/src/theme/slot-recipes/menu.ts +7 -7
  58. package/src/theme/slot-recipes/numeric-stepper.ts +4 -4
  59. package/src/theme/slot-recipes/pagination.ts +4 -4
  60. package/src/theme/slot-recipes/popover.ts +4 -4
  61. package/src/theme/slot-recipes/progress-bar.ts +2 -2
  62. package/src/theme/slot-recipes/progress-indicator.ts +1 -1
  63. package/src/theme/slot-recipes/radio-card.ts +11 -11
  64. package/src/theme/slot-recipes/radio.ts +5 -5
  65. package/src/theme/slot-recipes/select.ts +16 -16
  66. package/src/theme/slot-recipes/stepper.ts +5 -5
  67. package/src/theme/slot-recipes/switch.ts +6 -6
  68. package/src/theme/slot-recipes/table.ts +2 -2
  69. package/src/theme/slot-recipes/tabs.ts +18 -18
  70. package/src/theme/slot-recipes/toast.ts +3 -3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
3
  "type": "module",
4
- "version": "13.0.3",
4
+ "version": "13.1.1",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -39,6 +39,7 @@
39
39
  "awesome-phonenumber": "^5.11.0",
40
40
  "deepmerge": "^4.3.1",
41
41
  "framer-motion": "^11.11.17",
42
+ "jscodeshift": "^17.3.0",
42
43
  "lottie-react": "^2.4.1",
43
44
  "next-themes": "^0.4.4",
44
45
  "react-aria": "^3.33.1",
@@ -46,15 +47,13 @@
46
47
  "react-stately": "^3.31.1",
47
48
  "react-swipeable": "^7.0.1",
48
49
  "usehooks-ts": "^3.1.0",
49
- "@vygruppen/spor-design-tokens": "4.3.3",
50
- "@vygruppen/spor-loader": "0.7.0",
51
- "@vygruppen/spor-icon-react": "5.0.0"
50
+ "@vygruppen/spor-design-tokens": "5.0.1",
51
+ "@vygruppen/spor-icon-react": "5.0.0",
52
+ "@vygruppen/spor-loader": "0.7.0"
52
53
  },
53
54
  "devDependencies": {
54
55
  "@react-types/datepicker": "^3.10.0",
55
56
  "@react-types/shared": "^3.27.0",
56
- "@testing-library/jest-dom": "^6.4.5",
57
- "@testing-library/react": "^14.3.1",
58
57
  "@types/node": "^22.13.4",
59
58
  "@types/react": "19.2.3",
60
59
  "@types/react-dom": "19.2.3",
@@ -65,10 +64,7 @@
65
64
  "react-dom": "19.2.3",
66
65
  "tsup": "^7.2.0",
67
66
  "typescript": "^5.7.3",
68
- "vitest": "^0.26.3",
69
- "vitest-axe": "^0.1.0",
70
- "vitest-canvas-mock": "^0.2.2",
71
- "@vygruppen/eslint-config": "2.1.0",
67
+ "@vygruppen/eslint-config": "2.2.0",
72
68
  "@vygruppen/tsconfig": "0.1.1"
73
69
  },
74
70
  "peerDependencies": {
@@ -48,10 +48,10 @@ export const BaseAlertIcon = ({
48
48
  }) => {
49
49
  const css = {
50
50
  "& path:first-of-type": {
51
- fill: `alert.${variant}.icon`,
51
+ fill: `icon.${variant}`,
52
52
  },
53
53
  "& path:not(:first-of-type)": {
54
- fill: `alert.${variant}.surface`,
54
+ fill: `surface.${variant}`,
55
55
  },
56
56
  };
57
57
 
@@ -87,6 +87,7 @@ export const ServiceAlert = ({
87
87
  css={{ ...styles.root, ...css }}
88
88
  ref={ref}
89
89
  {...rest}
90
+ className="light"
90
91
  >
91
92
  <Accordion.Item value={defaultValue}>
92
93
  <Accordion.ItemTrigger css={styles.itemTrigger}>
@@ -122,7 +123,7 @@ export const ServiceAlert = ({
122
123
  </Text>
123
124
  )}
124
125
  <Accordion.ItemIndicator>
125
- <DropdownDownFill24Icon color="icon.inverted" />
126
+ <DropdownDownFill24Icon color="icon.brand" />
126
127
  </Accordion.ItemIndicator>
127
128
  </Flex>
128
129
  </HStack>
@@ -103,18 +103,18 @@ const cellStyles = {
103
103
  },
104
104
  // Selection edge (single-mode selected OR range start/end)
105
105
  "&[data-edge]": {
106
- backgroundColor: "brand.surface",
107
- color: "text.inverted",
106
+ backgroundColor: "surface.brand",
107
+ color: "text.brand",
108
108
  },
109
109
  // Range middle
110
110
  "&[data-middle]": {
111
- backgroundColor: "surface.secondary",
111
+ backgroundColor: "surface.subtle",
112
112
  color: "text",
113
113
  },
114
114
  // Hover for non-selected, non-disabled cells on devices that support hover
115
115
  "@media (hover: hover)": {
116
116
  "&:not([data-edge]):not([data-middle]):not([data-disabled]):hover": {
117
- backgroundColor: "surface.secondary",
117
+ backgroundColor: "surface.subtle",
118
118
  color: "text",
119
119
  },
120
120
  },
@@ -116,7 +116,7 @@ export const CalendarNavigator = ({
116
116
  fontWeight="bold"
117
117
  flex="1"
118
118
  textAlign="center"
119
- color="core.text"
119
+ color="text.core"
120
120
  >
121
121
  {capitalize(title)}
122
122
  </Text>
@@ -115,7 +115,7 @@ export const CloseDrawerLine = ({
115
115
  top={0}
116
116
  marginY={2}
117
117
  marginX="auto"
118
- backgroundColor="floating.outline.active"
118
+ backgroundColor="outline.neutral"
119
119
  borderRadius="xs"
120
120
  {...props}
121
121
  ref={ref}
@@ -33,7 +33,7 @@ export const CardSelectContent = ({
33
33
  p="2"
34
34
  bg="bg"
35
35
  border="sm"
36
- borderColor="floating.outline"
36
+ borderColor="outline.floating"
37
37
  borderRadius="sm"
38
38
  {...props}
39
39
  >
@@ -61,9 +61,9 @@ export type CardSelectTriggerProps = {
61
61
  } & Omit<ButtonProps, "variant" | "rightIcon" | "leftIcon">;
62
62
 
63
63
  const bgActiveStyleMap = {
64
- core: "core.surface.active",
65
- ghost: "ghost.surface.active",
66
- floating: "floating.surface.active",
64
+ core: "surface.core.active",
65
+ ghost: "surface.ghost.active",
66
+ floating: "surface.floating.active",
67
67
  };
68
68
 
69
69
  export const CardSelectTrigger = ({
@@ -185,7 +185,7 @@ export const Combobox = (props: ComboboxProps<object>) => {
185
185
  borderBottomRightRadius={
186
186
  state.isOpen && !loading ? 0 : borderBottomRightRadius
187
187
  }
188
- _active={{ backgroundColor: "core.surface.active" }}
188
+ _active={{ backgroundColor: "surface.core.active" }}
189
189
  {...filteredInputProps}
190
190
  startElement={leftIcon}
191
191
  endElement={
@@ -140,7 +140,7 @@ export const Field = ({
140
140
  )}
141
141
  </ChakraField.Root>
142
142
  {helperText && (
143
- <Text variant="sm" color="text.tertiary">
143
+ <Text variant="sm" color="text.subtle">
144
144
  {helperText}
145
145
  </Text>
146
146
  )}
@@ -74,7 +74,8 @@ export const MenuContent = ({
74
74
 
75
75
  export type MenuTriggerProps = {
76
76
  icon?: ReactNode;
77
- } & Omit<ButtonProps, "variant" | "rightIcon" | "leftIcon"> & {
77
+ withChevron?: boolean;
78
+ } & Omit<ButtonProps, "rightIcon" | "leftIcon"> & {
78
79
  ref?: Ref<HTMLButtonElement>;
79
80
  };
80
81
 
@@ -83,6 +84,7 @@ export const MenuTrigger = ({
83
84
  size,
84
85
  children,
85
86
  ref,
87
+ withChevron = true,
86
88
  ...props
87
89
  }: MenuTriggerProps) => {
88
90
  const { variant } = useMenuContext();
@@ -104,10 +106,12 @@ export const MenuTrigger = ({
104
106
  size={size}
105
107
  {...props}
106
108
  rightIcon={
107
- <ChevronIcon
108
- transform={open ? "rotate(180deg)" : undefined}
109
- transition="transform 0.3s"
110
- />
109
+ withChevron && (
110
+ <ChevronIcon
111
+ transform={open ? "rotate(180deg)" : undefined}
112
+ transition="transform 0.3s"
113
+ />
114
+ )
111
115
  }
112
116
  >
113
117
  {children}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { Box } from "@chakra-ui/react";
3
- import React, { useRef } from "react";
3
+ import React, { useLayoutEffect, useRef } from "react";
4
4
  import {
5
5
  AriaPopoverProps,
6
6
  DismissButton,
@@ -75,6 +75,13 @@ export const Popover = ({
75
75
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
76
  const popoverRef = ref ?? (internalRef as any);
77
77
 
78
+ useLayoutEffect(() => {
79
+ const element = typeof popoverRef === "object" ? popoverRef?.current : null;
80
+ if (element) {
81
+ element.style.minWidth = `${triggerRef.current?.clientWidth ?? 0}px`;
82
+ }
83
+ });
84
+
78
85
  const { popoverProps, underlayProps } = usePopover(
79
86
  {
80
87
  triggerRef,
@@ -90,12 +97,7 @@ export const Popover = ({
90
97
  );
91
98
 
92
99
  const popoverBox = (
93
- <Box
94
- {...popoverProps}
95
- ref={popoverRef}
96
- // eslint-disable-next-line react-hooks/refs
97
- minWidth={triggerRef.current?.clientWidth ?? "auto"}
98
- >
100
+ <Box {...popoverProps} ref={popoverRef}>
99
101
  <DismissButton onDismiss={state.close} />
100
102
  {children}
101
103
  <DismissButton onDismiss={state.close} />
@@ -108,7 +108,7 @@ export const LineIcon = function LineIcon({
108
108
  css={{ ...styles.iconContainer, ...style }}
109
109
  padding={targetPadding()}
110
110
  borderWidth={borderContainer()}
111
- borderColor={variant === "walk" ? "core.outline" : "transparent"}
111
+ borderColor={variant === "walk" ? "outline.core" : "transparent"}
112
112
  aria-label={label}
113
113
  ref={ref}
114
114
  className={clsx("light", rest.className)}
@@ -8,6 +8,7 @@ import {
8
8
  import { inlineLoaderColorData } from "@vygruppen/spor-loader";
9
9
 
10
10
  import Lottie from "./Lottie";
11
+ import { useGetLoadingText } from "./text";
11
12
 
12
13
  export type ColorInlineLoaderProps = Exclude<BoxProps, "children">;
13
14
  /**
@@ -27,7 +28,7 @@ export const ColorInlineLoader = ({
27
28
  <Lottie animationData={inlineLoaderColorData} />
28
29
  </ClientOnly>
29
30
  </Box>
30
- <VisuallyHidden>Loading...</VisuallyHidden>
31
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
31
32
  </Center>
32
33
  );
33
34
  };
@@ -9,6 +9,7 @@ import {
9
9
  import { spinnerColorData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  export type SpinnerProps = BoxProps;
14
15
  export type ColorSpinnerProps = SpinnerProps;
@@ -40,7 +41,7 @@ export const ColorSpinner = ({
40
41
  <Lottie animationData={spinnerColorData} />
41
42
  </ClientOnly>
42
43
  </Box>
43
- <VisuallyHidden>Loading...</VisuallyHidden>
44
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
44
45
  {children && (
45
46
  <Box marginTop={3} fontWeight="bold">
46
47
  {children}
@@ -3,6 +3,7 @@ import { Box, BoxProps, ClientOnly, VisuallyHidden } from "@chakra-ui/react";
3
3
  import { contentLoaderData } from "@vygruppen/spor-loader";
4
4
 
5
5
  import Lottie from "./Lottie";
6
+ import { useGetLoadingText } from "./text";
6
7
 
7
8
  export type ContentLoaderProps = BoxProps;
8
9
  /**
@@ -17,7 +18,7 @@ export const ContentLoader = ({ children, ...props }: ContentLoaderProps) => {
17
18
  <Lottie animationData={contentLoaderData} />
18
19
  </ClientOnly>
19
20
  </Box>
20
- <VisuallyHidden>Loading...</VisuallyHidden>
21
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
21
22
  {children && (
22
23
  <Box textAlign="center" fontWeight="bold">
23
24
  {children}
@@ -9,6 +9,7 @@ import {
9
9
  import { fullScreenLoaderWhiteData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  type DarkFullScreenLoaderProps = BoxProps;
14
15
 
@@ -31,7 +32,7 @@ export const DarkFullScreenLoader = ({
31
32
  <Lottie animationData={fullScreenLoaderWhiteData} />
32
33
  </ClientOnly>
33
34
  </Box>
34
- <VisuallyHidden>Loading...</VisuallyHidden>
35
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
35
36
  </Center>
36
37
  );
37
38
  };
@@ -9,6 +9,7 @@ import {
9
9
  import { inlineLoaderDarkData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  export type DarkInlineLoaderProps = Exclude<BoxProps, "children">;
14
15
  /**
@@ -26,7 +27,7 @@ export const DarkInlineLoader = ({
26
27
  <Lottie animationData={inlineLoaderDarkData} />
27
28
  </ClientOnly>
28
29
  </Box>
29
- <VisuallyHidden>Loading...</VisuallyHidden>
30
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
30
31
  </Center>
31
32
  );
32
33
  };
@@ -10,6 +10,7 @@ import {
10
10
  VisuallyHidden,
11
11
  } from "..";
12
12
  import Lottie from "./Lottie";
13
+ import { useGetLoadingText } from "./text";
13
14
 
14
15
  export type DarkSpinnerProps = BoxProps;
15
16
  /** A circular spinner
@@ -42,7 +43,7 @@ export const DarkSpinner = ({
42
43
  <Lottie animationData={spinnerData} />
43
44
  </ClientOnly>
44
45
  </Box>
45
- <VisuallyHidden>Loading...</VisuallyHidden>
46
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
46
47
  {children && (
47
48
  <Box marginTop={3} fontWeight="bold">
48
49
  {children}
@@ -9,6 +9,7 @@ import {
9
9
  import { fullScreenLoaderBlackData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  type LightFullScreenLoaderProps = BoxProps;
14
15
 
@@ -24,7 +25,7 @@ export const LightFullScreenLoader = ({
24
25
  <Lottie animationData={fullScreenLoaderBlackData} />
25
26
  </ClientOnly>
26
27
  </Box>
27
- <VisuallyHidden>Loading...</VisuallyHidden>
28
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
28
29
  </Center>
29
30
  );
30
31
  };
@@ -9,6 +9,7 @@ import {
9
9
  import { inlineLoaderLightData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  export type LightInlineLoaderProps = Exclude<BoxProps, "children">;
14
15
  /**
@@ -26,7 +27,7 @@ export const LightInlineLoader = ({
26
27
  <Lottie animationData={inlineLoaderLightData} />
27
28
  </ClientOnly>
28
29
  </Box>
29
- <VisuallyHidden>Loading...</VisuallyHidden>
30
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
30
31
  </Center>
31
32
  );
32
33
  };
@@ -9,6 +9,7 @@ import {
9
9
  import { spinnerLightData } from "@vygruppen/spor-loader";
10
10
 
11
11
  import Lottie from "./Lottie";
12
+ import { useGetLoadingText } from "./text";
12
13
 
13
14
  export type LightSpinnerProps = BoxProps;
14
15
  /** A circular spinner
@@ -39,7 +40,7 @@ export const LightSpinner = ({
39
40
  <Lottie animationData={spinnerLightData} />
40
41
  </ClientOnly>
41
42
  </Box>
42
- <VisuallyHidden>Loading...</VisuallyHidden>
43
+ <VisuallyHidden>{useGetLoadingText()}</VisuallyHidden>
43
44
  {children && (
44
45
  <Box marginTop={3} fontWeight="bold">
45
46
  {children}
@@ -1,8 +1,9 @@
1
- import ReactLottie from "lottie-react";
1
+ import { useLottie } from "lottie-react";
2
2
 
3
3
  /**
4
4
  * A wrapper around Lottie to make it tree-shakeable for SSR.
5
5
  */
6
6
  export default function Lottie({ animationData }: { animationData: unknown }) {
7
- return <ReactLottie animationData={animationData} />;
7
+ const { View } = useLottie({ animationData });
8
+ return View;
8
9
  }
@@ -0,0 +1,15 @@
1
+ import { createTexts, useTranslation } from "@/i18n";
2
+
3
+ export const useGetLoadingText = () => {
4
+ const { t } = useTranslation();
5
+ return t(loadingText.loading);
6
+ };
7
+
8
+ const loadingText = createTexts({
9
+ loading: {
10
+ en: "Loading",
11
+ nb: "Laster",
12
+ nn: "Lastar",
13
+ sv: "Laddar",
14
+ },
15
+ });
@@ -23,8 +23,8 @@ export const StepperStep = ({
23
23
  const state = getState(stepNumber, activeStep);
24
24
  const recipe = useSlotRecipe({ key: "stepper" });
25
25
  const style = recipe({ variant });
26
- const disabledTextColor = "text.tertiary";
27
- const iconColor = "text.tertiary";
26
+ const disabledTextColor = "text.subtle";
27
+ const iconColor = "text.subtle";
28
28
 
29
29
  const disabled =
30
30
  (state !== "active" && disabledOverride) || state === "disabled";