@navikt/ds-react 0.14.3 → 0.14.7
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/cjs/form/Select.js +1 -1
- package/cjs/form/Switch.js +15 -4
- package/cjs/index.js +1 -0
- package/cjs/link-panel/LinkPanel.js +1 -1
- package/cjs/step-indicator/Step.js +62 -0
- package/cjs/step-indicator/StepIndicator.js +76 -0
- package/cjs/step-indicator/index.js +19 -0
- package/cjs/step-indicator/package.json +6 -0
- package/esm/form/Select.js +1 -1
- package/esm/form/Select.js.map +1 -1
- package/esm/form/Switch.d.ts +4 -0
- package/esm/form/Switch.js +16 -5
- package/esm/form/Switch.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/link-panel/LinkPanel.js +1 -1
- package/esm/link-panel/LinkPanel.js.map +1 -1
- package/esm/step-indicator/Step.d.ts +20 -0
- package/esm/step-indicator/Step.js +39 -0
- package/esm/step-indicator/Step.js.map +1 -0
- package/esm/step-indicator/StepIndicator.d.ts +41 -0
- package/esm/step-indicator/StepIndicator.js +52 -0
- package/esm/step-indicator/StepIndicator.js.map +1 -0
- package/esm/step-indicator/index.d.ts +2 -0
- package/esm/step-indicator/index.js +3 -0
- package/esm/step-indicator/index.js.map +1 -0
- package/package.json +5 -5
- package/src/form/Select.tsx +1 -1
- package/src/form/Switch.tsx +65 -6
- package/src/form/stories/switch.stories.mdx +73 -3
- package/src/form/stories/switch.stories.tsx +27 -1
- package/src/index.ts +1 -0
- package/src/link-panel/LinkPanel.tsx +1 -4
- package/src/step-indicator/Step.tsx +79 -0
- package/src/step-indicator/StepIndicator.tsx +145 -0
- package/src/step-indicator/index.ts +2 -0
- package/src/step-indicator/stories/Example.tsx +23 -0
- package/src/step-indicator/stories/step-indicator.stories.mdx +122 -0
- package/src/step-indicator/stories/step-indicator.stories.tsx +104 -0
package/src/form/Switch.tsx
CHANGED
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
import cl from "classnames";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
InputHTMLAttributes,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
3
8
|
import { BodyShort, Detail, Loader, omit } from "..";
|
|
4
9
|
import { FormFieldProps, useFormField } from "./useFormField";
|
|
5
10
|
|
|
11
|
+
const SelectedIcon = () => (
|
|
12
|
+
<svg
|
|
13
|
+
width="12px"
|
|
14
|
+
height="12px"
|
|
15
|
+
viewBox="0 0 12 12"
|
|
16
|
+
fill="none"
|
|
17
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
18
|
+
focusable={false}
|
|
19
|
+
role="img"
|
|
20
|
+
aria-hidden
|
|
21
|
+
aria-label="Deaktiver valg"
|
|
22
|
+
>
|
|
23
|
+
<path
|
|
24
|
+
fill-rule="evenodd"
|
|
25
|
+
clip-rule="evenodd"
|
|
26
|
+
d="M4.01386 8L10.25 2L11 2.75L4.01386 9.5L1 6.5L1.75 5.75L4.01386 8Z"
|
|
27
|
+
fill="currentColor"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
/>
|
|
30
|
+
</svg>
|
|
31
|
+
);
|
|
32
|
+
|
|
6
33
|
export interface SwitchProps
|
|
7
34
|
extends Omit<FormFieldProps, "error" | "errorId">,
|
|
8
35
|
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
@@ -18,6 +45,10 @@ export interface SwitchProps
|
|
|
18
45
|
* Toggles loading state with loader-component on switch
|
|
19
46
|
*/
|
|
20
47
|
loading?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Positions switch on left/right side of label
|
|
50
|
+
*/
|
|
51
|
+
position?: "left" | "right";
|
|
21
52
|
}
|
|
22
53
|
|
|
23
54
|
const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
|
|
@@ -29,30 +60,58 @@ const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
|
|
|
29
60
|
description,
|
|
30
61
|
hideLabel = false,
|
|
31
62
|
loading,
|
|
63
|
+
checked: checkedProp,
|
|
64
|
+
defaultChecked,
|
|
65
|
+
position = "left",
|
|
32
66
|
...rest
|
|
33
67
|
} = props;
|
|
34
68
|
|
|
35
69
|
const Description = size === "medium" ? BodyShort : Detail;
|
|
36
70
|
|
|
71
|
+
const [checked, setChecked] = useState(
|
|
72
|
+
defaultChecked ?? checkedProp ?? false
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
checkedProp !== undefined && setChecked(checkedProp);
|
|
77
|
+
}, [checkedProp]);
|
|
78
|
+
|
|
79
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
80
|
+
setChecked(e.target.checked);
|
|
81
|
+
props.onChange && props.onChange(e);
|
|
82
|
+
};
|
|
83
|
+
|
|
37
84
|
return (
|
|
38
85
|
<div
|
|
39
|
-
className={cl(
|
|
40
|
-
"navds-switch
|
|
41
|
-
|
|
86
|
+
className={cl(
|
|
87
|
+
"navds-switch",
|
|
88
|
+
props.className,
|
|
89
|
+
`navds-switch--${size}`,
|
|
90
|
+
`navds-switch--${position}`,
|
|
91
|
+
{
|
|
92
|
+
"navds-switch--disabled": inputProps.disabled,
|
|
93
|
+
}
|
|
94
|
+
)}
|
|
42
95
|
>
|
|
43
96
|
<input
|
|
44
97
|
{...omit(rest, ["size"])}
|
|
45
98
|
{...omit(inputProps, ["aria-invalid", "aria-describedby"])}
|
|
99
|
+
checked={checkedProp}
|
|
100
|
+
defaultChecked={defaultChecked}
|
|
46
101
|
ref={ref}
|
|
47
102
|
type="checkbox"
|
|
103
|
+
onChange={(e) => handleChange(e)}
|
|
48
104
|
className={cl(className, "navds-switch__input")}
|
|
49
105
|
/>
|
|
50
106
|
<span className="navds-switch__track">
|
|
51
107
|
<span className="navds-switch__thumb">
|
|
52
|
-
{loading
|
|
108
|
+
{loading ? (
|
|
109
|
+
<Loader size="xsmall" />
|
|
110
|
+
) : checked ? (
|
|
111
|
+
<SelectedIcon />
|
|
112
|
+
) : null}
|
|
53
113
|
</span>
|
|
54
114
|
</span>
|
|
55
|
-
|
|
56
115
|
<label htmlFor={inputProps.id} className="navds-switch__label-wrapper">
|
|
57
116
|
<div
|
|
58
117
|
className={cl("navds-switch__content", {
|
|
@@ -6,21 +6,70 @@ import { Switch } from "../index";
|
|
|
6
6
|
# Hvordan ta i bruk Switch
|
|
7
7
|
|
|
8
8
|
```jsx
|
|
9
|
-
<Switch>Slå på feature</Switch>
|
|
9
|
+
<Switch>Slå på feature</Switch>
|
|
10
|
+
<div>
|
|
11
|
+
<Switch position="right">Slå på feature</Switch>
|
|
12
|
+
</div>
|
|
10
13
|
```
|
|
11
14
|
|
|
12
15
|
<Canvas>
|
|
13
16
|
<Switch>Slå på feature</Switch>
|
|
17
|
+
<div>
|
|
18
|
+
<Switch position="right">Slå på feature</Switch>
|
|
19
|
+
</div>
|
|
14
20
|
</Canvas>
|
|
15
21
|
|
|
16
22
|
## Description
|
|
17
23
|
|
|
18
24
|
```jsx
|
|
19
25
|
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
|
|
26
|
+
<div>
|
|
27
|
+
<Switch position="right" description="Dette vil gjøre x og y">
|
|
28
|
+
Slå på feature
|
|
29
|
+
</Switch>
|
|
30
|
+
</div>
|
|
20
31
|
```
|
|
21
32
|
|
|
22
33
|
<Canvas>
|
|
23
34
|
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
|
|
35
|
+
<div>
|
|
36
|
+
<Switch position="right" description="Dette vil gjøre x og y">
|
|
37
|
+
Slå på feature
|
|
38
|
+
</Switch>
|
|
39
|
+
</div>
|
|
40
|
+
</Canvas>
|
|
41
|
+
|
|
42
|
+
## Position
|
|
43
|
+
|
|
44
|
+
Switch kan ha label på høyre eller venstre side. Velges med "Position"-prop "left" | "right". Husk at hvis position
|
|
45
|
+
"right" velges, må man selv passe på at den har en definert bredde slik at elementet ikke vises over hele skjermen.
|
|
46
|
+
|
|
47
|
+
```jsx
|
|
48
|
+
<div>
|
|
49
|
+
<div>
|
|
50
|
+
<h3>Feil</h3>
|
|
51
|
+
<Switch position="right">Slå på feature</Switch>
|
|
52
|
+
<h3>Riktig</h3>
|
|
53
|
+
<div style={{ width: 200 }}>
|
|
54
|
+
<Switch position="right">Slå på feature 1</Switch>
|
|
55
|
+
<Switch position="right">Slå på feature 2</Switch>
|
|
56
|
+
<Switch position="right">Slå på feature 3</Switch>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
<Canvas>
|
|
63
|
+
<div>
|
|
64
|
+
<h3>Feil</h3>
|
|
65
|
+
<Switch position="right">Slå på feature</Switch>
|
|
66
|
+
<h3>Riktig</h3>
|
|
67
|
+
<div style={{ width: 300 }}>
|
|
68
|
+
<Switch position="right">Slå på feature 1</Switch>
|
|
69
|
+
<Switch position="right">Slå på feature 2</Switch>
|
|
70
|
+
<Switch position="right">Slå på feature 3</Switch>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
24
73
|
</Canvas>
|
|
25
74
|
|
|
26
75
|
## Sizing
|
|
@@ -30,6 +79,9 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
|
|
|
30
79
|
```jsx
|
|
31
80
|
<Switch size="small" >Slå på feature</Switch>
|
|
32
81
|
<Switch size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
|
|
82
|
+
|
|
83
|
+
<Switch position="right" size="small" >Slå på feature</Switch>
|
|
84
|
+
<Switch position="right" size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
|
|
33
85
|
```
|
|
34
86
|
|
|
35
87
|
<Canvas>
|
|
@@ -39,6 +91,14 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
|
|
|
39
91
|
Slå på feature
|
|
40
92
|
</Switch>
|
|
41
93
|
</div>
|
|
94
|
+
<div>
|
|
95
|
+
<Switch position="right" size="small">
|
|
96
|
+
Slå på feature
|
|
97
|
+
</Switch>
|
|
98
|
+
<Switch position="right" size="small" description="Dette vil gjøre x og y">
|
|
99
|
+
Slå på feature
|
|
100
|
+
</Switch>
|
|
101
|
+
</div>
|
|
42
102
|
</Canvas>
|
|
43
103
|
|
|
44
104
|
## defaultChecked
|
|
@@ -58,11 +118,21 @@ Switch er en stylet checkbox, så både `checked` og `defaultChecked` fungerer
|
|
|
58
118
|
Ved bruk av `hideLegend` på Switch kan man gjøre slik at legend/description bare vises for skjermlesere
|
|
59
119
|
|
|
60
120
|
```jsx
|
|
61
|
-
<
|
|
121
|
+
<div style={{ width: 300 }}>
|
|
122
|
+
<Switch hideLabel>Slå på feature</Switch>
|
|
123
|
+
<Switch hideLabel position="right">
|
|
124
|
+
Slå på feature
|
|
125
|
+
</Switch>
|
|
126
|
+
</div>
|
|
62
127
|
```
|
|
63
128
|
|
|
64
129
|
<Canvas>
|
|
65
|
-
<
|
|
130
|
+
<div style={{ width: 300 }}>
|
|
131
|
+
<Switch hideLabel>Slå på feature</Switch>
|
|
132
|
+
<Switch hideLabel position="right">
|
|
133
|
+
Slå på feature
|
|
134
|
+
</Switch>
|
|
135
|
+
</div>
|
|
66
136
|
</Canvas>
|
|
67
137
|
|
|
68
138
|
## Disabled
|
|
@@ -10,15 +10,22 @@ export default {
|
|
|
10
10
|
export const All = () => {
|
|
11
11
|
const [checked, setChecked] = useState(false);
|
|
12
12
|
return (
|
|
13
|
-
<div>
|
|
13
|
+
<div style={{ width: "fit-content" }}>
|
|
14
14
|
<h1>Switch</h1>
|
|
15
15
|
<Switch>Label text</Switch>
|
|
16
|
+
<Switch position="right">Label text</Switch>
|
|
16
17
|
|
|
17
18
|
<h2>Switch w/Description</h2>
|
|
18
19
|
<Switch>Label text</Switch>
|
|
19
20
|
<Switch description="Switch description">Label text</Switch>
|
|
20
21
|
<Switch>Label text</Switch>
|
|
21
22
|
|
|
23
|
+
<Switch position="right">Label text</Switch>
|
|
24
|
+
<Switch position="right" description="Switch description">
|
|
25
|
+
Label text
|
|
26
|
+
</Switch>
|
|
27
|
+
<Switch position="right">Label text</Switch>
|
|
28
|
+
|
|
22
29
|
<h2>hidelabel</h2>
|
|
23
30
|
<Switch description="Switch description" hideLabel>
|
|
24
31
|
Label text
|
|
@@ -29,6 +36,15 @@ export const All = () => {
|
|
|
29
36
|
<Switch hideLabel size="small">
|
|
30
37
|
Label text small
|
|
31
38
|
</Switch>
|
|
39
|
+
<Switch position="right" description="Switch description" hideLabel>
|
|
40
|
+
Label text
|
|
41
|
+
</Switch>
|
|
42
|
+
<Switch position="right" description="Switch description" hideLabel>
|
|
43
|
+
Label text
|
|
44
|
+
</Switch>
|
|
45
|
+
<Switch position="right" hideLabel size="small">
|
|
46
|
+
Label text small
|
|
47
|
+
</Switch>
|
|
32
48
|
|
|
33
49
|
<h2>Switch small</h2>
|
|
34
50
|
<Switch size="small">Label text</Switch>
|
|
@@ -37,6 +53,16 @@ export const All = () => {
|
|
|
37
53
|
</Switch>
|
|
38
54
|
<Switch size="small">Label text</Switch>
|
|
39
55
|
|
|
56
|
+
<Switch position="right" size="small">
|
|
57
|
+
Label text
|
|
58
|
+
</Switch>
|
|
59
|
+
<Switch position="right" description="Switch description" size="small">
|
|
60
|
+
Label text
|
|
61
|
+
</Switch>
|
|
62
|
+
<Switch position="right" size="small">
|
|
63
|
+
Label text
|
|
64
|
+
</Switch>
|
|
65
|
+
|
|
40
66
|
<h2>Controlled</h2>
|
|
41
67
|
<Switch checked={checked} onChange={() => setChecked(!checked)}>
|
|
42
68
|
Label text
|
package/src/index.ts
CHANGED
|
@@ -40,10 +40,7 @@ const LinkPanelComponent: OverridableComponent<
|
|
|
40
40
|
className={cl("navds-link-panel", className)}
|
|
41
41
|
>
|
|
42
42
|
<div className="navds-link-panel__content">{children}</div>
|
|
43
|
-
<Next
|
|
44
|
-
className="navds-link-panel__chevron"
|
|
45
|
-
aria-label="arrow-icon pointing right"
|
|
46
|
-
/>
|
|
43
|
+
<Next className="navds-link-panel__chevron" aria-hidden />
|
|
47
44
|
</Panel>
|
|
48
45
|
);
|
|
49
46
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, { forwardRef, useContext } from "react";
|
|
2
|
+
import cl from "classnames";
|
|
3
|
+
import { StepContext } from ".";
|
|
4
|
+
import { BodyShort, Label, OverridableComponent } from "..";
|
|
5
|
+
|
|
6
|
+
export interface StepIndicatorStepProps
|
|
7
|
+
extends React.HTMLAttributes<HTMLButtonElement> {
|
|
8
|
+
/**
|
|
9
|
+
* Text content under indicator
|
|
10
|
+
*/
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Disables interaction with element
|
|
14
|
+
*/
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Handled by StepIndicator
|
|
18
|
+
*/
|
|
19
|
+
index?: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface StepIndicatorStepType
|
|
23
|
+
extends OverridableComponent<StepIndicatorStepProps, HTMLButtonElement> {}
|
|
24
|
+
|
|
25
|
+
const StepComponent: OverridableComponent<
|
|
26
|
+
StepIndicatorStepProps,
|
|
27
|
+
HTMLButtonElement
|
|
28
|
+
> = forwardRef(
|
|
29
|
+
(
|
|
30
|
+
{ className, children, as: Component = "button", disabled, index, ...rest },
|
|
31
|
+
ref
|
|
32
|
+
) => {
|
|
33
|
+
const context = useContext(StepContext);
|
|
34
|
+
|
|
35
|
+
if (context === null) {
|
|
36
|
+
console.error(
|
|
37
|
+
"<StepIndicator.Step> has to be used within an <StepIndicator>"
|
|
38
|
+
);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const safeIndex = index ?? 0;
|
|
43
|
+
|
|
44
|
+
const Number = context.activeStep === safeIndex ? Label : BodyShort;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Component
|
|
48
|
+
{...rest}
|
|
49
|
+
disabled={disabled}
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cl("navds-step-indicator__step", className, {
|
|
52
|
+
"navds-step-indicator__step--disabled": disabled,
|
|
53
|
+
"navds-step-indicator__step--active":
|
|
54
|
+
context.activeStep === safeIndex,
|
|
55
|
+
"navds-step-indicator__step--finished":
|
|
56
|
+
context.activeStep > safeIndex,
|
|
57
|
+
})}
|
|
58
|
+
onClick={(e) => {
|
|
59
|
+
context.onStepChange(safeIndex);
|
|
60
|
+
rest.onClick && rest.onClick(e);
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
<Number className="navds-step-indicator__step-number">
|
|
64
|
+
{safeIndex + 1}
|
|
65
|
+
</Number>
|
|
66
|
+
<div className={cl("navds-step-indicator__step-label")}>
|
|
67
|
+
{!context.hideLabels && children}
|
|
68
|
+
</div>
|
|
69
|
+
{safeIndex !== 0 && (
|
|
70
|
+
<span aria-hidden className="navds-step-indicator__step-line" />
|
|
71
|
+
)}
|
|
72
|
+
</Component>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const Step = StepComponent as StepIndicatorStepType;
|
|
78
|
+
|
|
79
|
+
export default Step;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import cl from "classnames";
|
|
2
|
+
import React, {
|
|
3
|
+
createContext,
|
|
4
|
+
forwardRef,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react";
|
|
10
|
+
import mergeRefs from "react-merge-refs";
|
|
11
|
+
import Step, { StepIndicatorStepProps, StepIndicatorStepType } from "./Step";
|
|
12
|
+
|
|
13
|
+
export interface StepIndicatorProps
|
|
14
|
+
extends React.HTMLAttributes<HTMLOListElement> {
|
|
15
|
+
/**
|
|
16
|
+
* <StepIndicator.Step /> elements
|
|
17
|
+
*/
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Adds classname to wrapper
|
|
21
|
+
*/
|
|
22
|
+
className?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Current active step index
|
|
25
|
+
*/
|
|
26
|
+
activeStep: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback for clicked step index
|
|
29
|
+
*/
|
|
30
|
+
onStepChange?: (step: number) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Hides labels for each step if true
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
hideLabels?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* enables `hideLabels` internally when steps start to overflow.
|
|
38
|
+
* @note declaring `hideLabels` overwrites this functionality
|
|
39
|
+
*/
|
|
40
|
+
responsive?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface StepIndicatorComponent
|
|
44
|
+
extends React.ForwardRefExoticComponent<
|
|
45
|
+
StepIndicatorProps & React.RefAttributes<HTMLOListElement>
|
|
46
|
+
> {
|
|
47
|
+
Step: StepIndicatorStepType;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface StepContextProps {
|
|
51
|
+
activeStep: number;
|
|
52
|
+
onStepChange: (step: number) => void;
|
|
53
|
+
hideLabels: boolean;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const StepContext = createContext<StepContextProps | null>(null);
|
|
57
|
+
|
|
58
|
+
const StepIndicator: StepIndicatorComponent = forwardRef<
|
|
59
|
+
HTMLOListElement,
|
|
60
|
+
StepIndicatorProps
|
|
61
|
+
>(
|
|
62
|
+
(
|
|
63
|
+
{
|
|
64
|
+
children,
|
|
65
|
+
className,
|
|
66
|
+
activeStep,
|
|
67
|
+
hideLabels,
|
|
68
|
+
onStepChange = () => {},
|
|
69
|
+
responsive,
|
|
70
|
+
...rest
|
|
71
|
+
},
|
|
72
|
+
ref
|
|
73
|
+
) => {
|
|
74
|
+
const wrapperRef = useRef<HTMLOListElement | null>(null);
|
|
75
|
+
const mergedRef = mergeRefs([wrapperRef, ref]);
|
|
76
|
+
|
|
77
|
+
const [showLabels, setShowLabels] = useState(true);
|
|
78
|
+
|
|
79
|
+
const removeLabels = hideLabels ?? (!!responsive && !showLabels);
|
|
80
|
+
|
|
81
|
+
const stepsWithIndex = React.Children.map(children, (step, index) => {
|
|
82
|
+
return React.isValidElement<StepIndicatorStepProps>(step) ? (
|
|
83
|
+
<li
|
|
84
|
+
className={cl("navds-step-indicator__step-wrapper", {
|
|
85
|
+
"navds-step-indicator__step-wrapper--hidelabel": removeLabels,
|
|
86
|
+
})}
|
|
87
|
+
key={index}
|
|
88
|
+
aria-current={index === activeStep && "step"}
|
|
89
|
+
>
|
|
90
|
+
{React.cloneElement(step, {
|
|
91
|
+
...step.props,
|
|
92
|
+
index,
|
|
93
|
+
})}
|
|
94
|
+
</li>
|
|
95
|
+
) : (
|
|
96
|
+
step
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const canShowLabels = useCallback(() => {
|
|
101
|
+
const remSize = parseFloat(
|
|
102
|
+
String(getComputedStyle(document.documentElement).fontSize)
|
|
103
|
+
);
|
|
104
|
+
const childrenLength = React.Children.toArray(children).filter((child) =>
|
|
105
|
+
React.isValidElement(child)
|
|
106
|
+
).length;
|
|
107
|
+
|
|
108
|
+
wrapperRef.current &&
|
|
109
|
+
setShowLabels(
|
|
110
|
+
wrapperRef.current?.getBoundingClientRect().width >=
|
|
111
|
+
remSize * 10 * childrenLength
|
|
112
|
+
);
|
|
113
|
+
}, [children]);
|
|
114
|
+
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
window.addEventListener("resize", canShowLabels);
|
|
117
|
+
canShowLabels();
|
|
118
|
+
return () => {
|
|
119
|
+
window.removeEventListener("resize", canShowLabels);
|
|
120
|
+
};
|
|
121
|
+
}, [canShowLabels]);
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<ol
|
|
125
|
+
ref={mergedRef}
|
|
126
|
+
className={cl(`navds-step-indicator`, className)}
|
|
127
|
+
{...rest}
|
|
128
|
+
>
|
|
129
|
+
<StepContext.Provider
|
|
130
|
+
value={{
|
|
131
|
+
activeStep,
|
|
132
|
+
onStepChange,
|
|
133
|
+
hideLabels: removeLabels,
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{stepsWithIndex}
|
|
137
|
+
</StepContext.Provider>
|
|
138
|
+
</ol>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
) as StepIndicatorComponent;
|
|
142
|
+
|
|
143
|
+
StepIndicator.Step = Step;
|
|
144
|
+
|
|
145
|
+
export default StepIndicator;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { StepIndicator } from "..";
|
|
3
|
+
|
|
4
|
+
export const Example = ({ ...props }) => {
|
|
5
|
+
const [active, setactive] = useState(1);
|
|
6
|
+
|
|
7
|
+
const { disabled, ...rest } = props;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<StepIndicator {...rest} activeStep={active} onStepChange={setactive}>
|
|
11
|
+
<StepIndicator.Step>Start</StepIndicator.Step>
|
|
12
|
+
<StepIndicator.Step>
|
|
13
|
+
Sunt deserunt qui sit sunt culpa nisi
|
|
14
|
+
</StepIndicator.Step>
|
|
15
|
+
<StepIndicator.Step disabled={disabled}>
|
|
16
|
+
Nulla nisi pariatur nulla cupidatat elit.
|
|
17
|
+
</StepIndicator.Step>
|
|
18
|
+
<StepIndicator.Step>
|
|
19
|
+
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
|
20
|
+
</StepIndicator.Step>
|
|
21
|
+
</StepIndicator>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Meta, Canvas } from "@storybook/addon-docs";
|
|
2
|
+
import { StepIndicator } from "..";
|
|
3
|
+
import { Example } from "./Example";
|
|
4
|
+
|
|
5
|
+
<Meta title="ds-react/step-indicator/intro" />
|
|
6
|
+
|
|
7
|
+
# Hvordan ta i bruk StepIndicator
|
|
8
|
+
|
|
9
|
+
Vi flytter over Stegindikator til `ds-react` uten noen veldig store endringer i design.
|
|
10
|
+
Du må nå selv styre state med `activeStep` og `onStepChange`.
|
|
11
|
+
|
|
12
|
+
```jsx
|
|
13
|
+
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
|
|
14
|
+
<StepIndicator.Step>Start</StepIndicator.Step>
|
|
15
|
+
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
|
|
16
|
+
<StepIndicator.Step>
|
|
17
|
+
Nulla nisi pariatur nulla cupidatat elit.
|
|
18
|
+
</StepIndicator.Step>
|
|
19
|
+
<StepIndicator.Step>
|
|
20
|
+
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
|
21
|
+
</StepIndicator.Step>
|
|
22
|
+
</StepIndicator>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
<Canvas>
|
|
26
|
+
<Example />
|
|
27
|
+
</Canvas>
|
|
28
|
+
|
|
29
|
+
## responsive
|
|
30
|
+
|
|
31
|
+
Bruk `responsive`-prop for å skjule labels med en gang StepIndicator begynner å overlfowe.
|
|
32
|
+
|
|
33
|
+
```jsx
|
|
34
|
+
<StepIndicator
|
|
35
|
+
responsive
|
|
36
|
+
activeStep={activeStep}
|
|
37
|
+
onStepChange={(x) => setActiveStep(x)}
|
|
38
|
+
>
|
|
39
|
+
<StepIndicator.Step>Start</StepIndicator.Step>
|
|
40
|
+
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
|
|
41
|
+
<StepIndicator.Step>
|
|
42
|
+
Nulla nisi pariatur nulla cupidatat elit.
|
|
43
|
+
</StepIndicator.Step>
|
|
44
|
+
<StepIndicator.Step>
|
|
45
|
+
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
|
46
|
+
</StepIndicator.Step>
|
|
47
|
+
</StepIndicator>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
<Canvas>
|
|
51
|
+
<Example responsive />
|
|
52
|
+
</Canvas>
|
|
53
|
+
|
|
54
|
+
## hideLabels
|
|
55
|
+
|
|
56
|
+
Du kan gjemme labels fra hvert steg med `hideLabels`-prop
|
|
57
|
+
|
|
58
|
+
```jsx
|
|
59
|
+
<StepIndicator
|
|
60
|
+
hideLabels
|
|
61
|
+
activeStep={activeStep}
|
|
62
|
+
onStepChange={(x) => setActiveStep(x)}
|
|
63
|
+
>
|
|
64
|
+
<StepIndicator.Step>Start</StepIndicator.Step>
|
|
65
|
+
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
|
|
66
|
+
<StepIndicator.Step>
|
|
67
|
+
Nulla nisi pariatur nulla cupidatat elit.
|
|
68
|
+
</StepIndicator.Step>
|
|
69
|
+
<StepIndicator.Step>
|
|
70
|
+
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
|
71
|
+
</StepIndicator.Step>
|
|
72
|
+
</StepIndicator>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
<Canvas>
|
|
76
|
+
<Example hideLabels />
|
|
77
|
+
</Canvas>
|
|
78
|
+
|
|
79
|
+
## disabled
|
|
80
|
+
|
|
81
|
+
```jsx
|
|
82
|
+
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
|
|
83
|
+
<StepIndicator.Step>Start</StepIndicator.Step>
|
|
84
|
+
<StepIndicator.Step disabled>
|
|
85
|
+
Sunt deserunt qui sit sunt culpa nisi
|
|
86
|
+
</StepIndicator.Step>
|
|
87
|
+
<StepIndicator.Step disabled>
|
|
88
|
+
Nulla nisi pariatur nulla cupidatat elit.
|
|
89
|
+
</StepIndicator.Step>
|
|
90
|
+
<StepIndicator.Step>
|
|
91
|
+
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
|
92
|
+
</StepIndicator.Step>
|
|
93
|
+
</StepIndicator>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
<Canvas>
|
|
97
|
+
<Example disabled />
|
|
98
|
+
</Canvas>
|
|
99
|
+
|
|
100
|
+
## Override tags
|
|
101
|
+
|
|
102
|
+
`StepIndicator.Step` er implementert med Overridable-component noe som gjør at du kan endre taggen til
|
|
103
|
+
det du selv ønsker ved å bruke `as`-prop
|
|
104
|
+
|
|
105
|
+
```jsx
|
|
106
|
+
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
|
|
107
|
+
{/* Dette er default */}
|
|
108
|
+
<StepIndicator.Step as="button">Start</StepIndicator.Step>
|
|
109
|
+
<StepIndicator.Step as="a" href="#">
|
|
110
|
+
Sunt deserunt qui sit sunt culpa nisi
|
|
111
|
+
</StepIndicator.Step>
|
|
112
|
+
</StepIndicator>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
<Canvas>
|
|
116
|
+
<StepIndicator activeStep={1} onStepChange={console.log}>
|
|
117
|
+
<StepIndicator.Step as="button">{`<button>`}</StepIndicator.Step>
|
|
118
|
+
<StepIndicator.Step as="a" href="#">
|
|
119
|
+
{`<a>`}
|
|
120
|
+
</StepIndicator.Step>
|
|
121
|
+
</StepIndicator>
|
|
122
|
+
</Canvas>
|