@vygruppen/spor-react 13.0.2 → 13.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.
Files changed (75) hide show
  1. package/.turbo/turbo-build.log +25 -25
  2. package/.turbo/turbo-postinstall.log +4 -4
  3. package/CHANGELOG.md +21 -0
  4. package/dist/index.cjs +554 -397
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +194 -181
  7. package/dist/index.d.ts +194 -181
  8. package/dist/index.mjs +556 -399
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +4 -8
  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/InputChip.tsx +33 -0
  20. package/src/input/PasswordInput.tsx +2 -1
  21. package/src/input/Popover.tsx +9 -7
  22. package/src/input/Select.tsx +44 -7
  23. package/src/input/index.ts +1 -0
  24. package/src/linjetag/LineIcon.tsx +1 -1
  25. package/src/loader/ColorInlineLoader.tsx +2 -1
  26. package/src/loader/ColorSpinner.tsx +2 -1
  27. package/src/loader/ContentLoader.tsx +2 -1
  28. package/src/loader/DarkFullScreenLoader.tsx +2 -1
  29. package/src/loader/DarkInlineLoader.tsx +2 -1
  30. package/src/loader/DarkSpinner.tsx +2 -1
  31. package/src/loader/LightFullScreenLoader.tsx +2 -1
  32. package/src/loader/LightInlineLoader.tsx +2 -1
  33. package/src/loader/LightSpinner.tsx +2 -1
  34. package/src/loader/Lottie.tsx +3 -2
  35. package/src/loader/text.ts +15 -0
  36. package/src/stepper/StepperStep.tsx +2 -2
  37. package/src/theme/recipes/badge.ts +24 -24
  38. package/src/theme/recipes/button.ts +22 -22
  39. package/src/theme/recipes/close-button.ts +2 -2
  40. package/src/theme/recipes/input.ts +9 -9
  41. package/src/theme/recipes/link.ts +1 -1
  42. package/src/theme/recipes/pressable-card.ts +12 -12
  43. package/src/theme/recipes/skeleton.ts +1 -1
  44. package/src/theme/recipes/static-card.ts +8 -8
  45. package/src/theme/semantic-tokens/colors.ts +1 -1
  46. package/src/theme/slot-recipes/accordion.ts +10 -10
  47. package/src/theme/slot-recipes/alert-expandable.ts +35 -35
  48. package/src/theme/slot-recipes/alert-service.ts +10 -10
  49. package/src/theme/slot-recipes/alert.ts +11 -11
  50. package/src/theme/slot-recipes/anatomy.ts +2 -0
  51. package/src/theme/slot-recipes/autocomplete.ts +5 -5
  52. package/src/theme/slot-recipes/breadcrumb.ts +4 -4
  53. package/src/theme/slot-recipes/checkbox.ts +11 -17
  54. package/src/theme/slot-recipes/choice-chip.ts +21 -21
  55. package/src/theme/slot-recipes/datepicker.ts +29 -29
  56. package/src/theme/slot-recipes/field.ts +3 -3
  57. package/src/theme/slot-recipes/floating-action-button.ts +14 -14
  58. package/src/theme/slot-recipes/index.ts +2 -0
  59. package/src/theme/slot-recipes/input-chip.ts +118 -0
  60. package/src/theme/slot-recipes/listbox.ts +9 -9
  61. package/src/theme/slot-recipes/media-controller-button.ts +9 -9
  62. package/src/theme/slot-recipes/menu.ts +7 -7
  63. package/src/theme/slot-recipes/numeric-stepper.ts +4 -4
  64. package/src/theme/slot-recipes/pagination.ts +4 -4
  65. package/src/theme/slot-recipes/popover.ts +4 -4
  66. package/src/theme/slot-recipes/progress-bar.ts +2 -2
  67. package/src/theme/slot-recipes/progress-indicator.ts +1 -1
  68. package/src/theme/slot-recipes/radio-card.ts +11 -11
  69. package/src/theme/slot-recipes/radio.ts +5 -5
  70. package/src/theme/slot-recipes/select.ts +16 -16
  71. package/src/theme/slot-recipes/stepper.ts +5 -5
  72. package/src/theme/slot-recipes/switch.ts +6 -6
  73. package/src/theme/slot-recipes/table.ts +2 -2
  74. package/src/theme/slot-recipes/tabs.ts +18 -18
  75. 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.2",
4
+ "version": "13.1.0",
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-design-tokens": "5.0.0",
50
51
  "@vygruppen/spor-icon-react": "5.0.0",
51
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
  )}
@@ -0,0 +1,33 @@
1
+ import { Box, Tag as ChakraTag, TagRootProps } from "@chakra-ui/react";
2
+ import { IconComponent } from "@vygruppen/spor-icon-react";
3
+ import React from "react";
4
+
5
+ export type InputChipProps = TagRootProps & {
6
+ startIcon?: IconComponent;
7
+ endIcon?: IconComponent;
8
+ onClick?: VoidFunction;
9
+ };
10
+
11
+ export const InputChip = ({
12
+ startIcon,
13
+ endIcon,
14
+ children,
15
+ ref,
16
+ ...rest
17
+ }: InputChipProps & { ref?: React.Ref<HTMLDivElement> }) => {
18
+ return (
19
+ <ChakraTag.Root ref={ref} {...rest} as="button">
20
+ {startIcon && (
21
+ <ChakraTag.StartElement>
22
+ <Box as={startIcon} />
23
+ </ChakraTag.StartElement>
24
+ )}
25
+ <ChakraTag.Label>{children}</ChakraTag.Label>
26
+ {endIcon && (
27
+ <ChakraTag.EndElement>
28
+ <Box as={endIcon} />
29
+ </ChakraTag.EndElement>
30
+ )}
31
+ </ChakraTag.Root>
32
+ );
33
+ };
@@ -16,7 +16,8 @@ export interface PasswordVisibilityProps {
16
16
  }
17
17
 
18
18
  export interface PasswordInputProps
19
- extends InputProps, PasswordVisibilityProps {
19
+ extends InputProps,
20
+ PasswordVisibilityProps {
20
21
  rootProps?: InputProps;
21
22
  }
22
23
 
@@ -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} />
@@ -8,6 +8,8 @@ import type {
8
8
  } from "@chakra-ui/react";
9
9
  import {
10
10
  Box,
11
+ Checkbox as ChakraCheckbox,
12
+ Flex,
11
13
  Portal,
12
14
  Select as ChakraSelect,
13
15
  useSelectContext,
@@ -21,6 +23,7 @@ import * as React from "react";
21
23
 
22
24
  import { CloseButton } from "@/button";
23
25
 
26
+ import { Badge } from "..";
24
27
  import { Field, FieldProps } from "./Field";
25
28
 
26
29
  export type SelectProps = ChakraSelectRootProps &
@@ -95,7 +98,7 @@ export const Select = ({
95
98
  position="relative"
96
99
  >
97
100
  <SelectTrigger data-attachable>
98
- <SelectValueText withPlaceholder={label ? true : false} />
101
+ <SelectValueText withPlaceholder={!!label} />
99
102
  </SelectTrigger>
100
103
  {label && <SelectLabel css={styles.label}>{label}</SelectLabel>}
101
104
  <SelectContent css={styles.selectContent} baseStyle={css}>
@@ -112,7 +115,7 @@ export const SelectLabel = (props: SelectLabelProps) => {
112
115
  return (
113
116
  <ChakraSelect.Label
114
117
  {...props}
115
- data-selected={value.length > 0 ? true : undefined}
118
+ data-selected={value.length > 0 || undefined}
116
119
  />
117
120
  );
118
121
  };
@@ -131,8 +134,19 @@ export const SelectItem = ({
131
134
  const { item, children, description, ...rest } = props;
132
135
  const recipe = useSlotRecipe({ key: "select" });
133
136
  const styles = recipe();
137
+ const selectContext = useSelectContext();
138
+ const multiple = selectContext.multiple;
139
+ const isSelected = selectContext.value.includes(item.value);
140
+
134
141
  return (
135
142
  <ChakraSelect.Item item={item} {...rest} ref={ref} css={styles.item}>
143
+ {multiple && (
144
+ <ChakraCheckbox.Root checked={isSelected} pointerEvents="none">
145
+ <ChakraCheckbox.Control>
146
+ <ChakraCheckbox.Indicator />
147
+ </ChakraCheckbox.Control>
148
+ </ChakraCheckbox.Root>
149
+ )}
136
150
  <Box width="100%">
137
151
  <ChakraSelect.ItemText display="flex">{children}</ChakraSelect.ItemText>
138
152
  {description && (
@@ -142,12 +156,15 @@ export const SelectItem = ({
142
156
  )}
143
157
  </Box>
144
158
 
145
- <ChakraSelect.ItemIndicator>
146
- <CheckmarkFill18Icon />
147
- </ChakraSelect.ItemIndicator>
159
+ {!multiple && (
160
+ <ChakraSelect.ItemIndicator>
161
+ <CheckmarkFill18Icon />
162
+ </ChakraSelect.ItemIndicator>
163
+ )}
148
164
  </ChakraSelect.Item>
149
165
  );
150
166
  };
167
+ SelectItem.displayName = "SelectItem";
151
168
 
152
169
  type SelectItemGroupProps = ChakraSelect.ItemGroupProps & {
153
170
  label: React.ReactNode;
@@ -249,6 +266,7 @@ type SelectValueTextProps = Omit<ChakraSelect.ValueTextProps, "children"> & {
249
266
  children?(items: CollectionItem[]): React.ReactNode;
250
267
  placeholder?: string;
251
268
  withPlaceholder?: boolean;
269
+ multiple?: boolean;
252
270
  };
253
271
 
254
272
  export const SelectValueText = function SelectValueText({
@@ -258,6 +276,10 @@ export const SelectValueText = function SelectValueText({
258
276
  ref?: React.Ref<HTMLSpanElement>;
259
277
  }) {
260
278
  const { children, withPlaceholder, placeholder, ...rest } = props;
279
+
280
+ const selectContext = useSelectContext();
281
+ const multiple = selectContext.multiple;
282
+
261
283
  return (
262
284
  <ChakraSelect.ValueText
263
285
  {...rest}
@@ -277,9 +299,24 @@ export const SelectValueText = function SelectValueText({
277
299
  const items = select.selectedItems;
278
300
  if (items.length === 0) return placeholder;
279
301
  if (children) return children(items);
280
- if (items.length === 1)
302
+ if (multiple) {
303
+ return (
304
+ <Flex gap={0.5} marginBottom={1}>
305
+ {items.map((item) => (
306
+ <Badge
307
+ key={select.collection.stringifyItem(item)}
308
+ size="sm"
309
+ colorPalette="green"
310
+ >
311
+ {select.collection.stringifyItem(item)}
312
+ </Badge>
313
+ ))}
314
+ </Flex>
315
+ );
316
+ }
317
+ if (items.length === 1) {
281
318
  return select.collection.stringifyItem(items[0]);
282
- return `${items.length} selected`;
319
+ }
283
320
  }}
284
321
  </ChakraSelect.Context>
285
322
  </ChakraSelect.ValueText>
@@ -8,6 +8,7 @@ export * from "./Combobox";
8
8
  export * from "./Field";
9
9
  export * from "./Fieldset";
10
10
  export * from "./Input";
11
+ export * from "./InputChip";
11
12
  export * from "./ListBox";
12
13
  export * from "./Menu";
13
14
  export * from "./NativeSelect";
@@ -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";