@mattilsynet/design 3.2.9 → 3.3.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/mtds/ai/AGENTS.md +892 -0
- package/mtds/ai/alert.mdx +63 -0
- package/mtds/ai/alert.stories.tsx +128 -0
- package/mtds/ai/analytics.mdx +185 -0
- package/mtds/ai/app.mdx +60 -0
- package/mtds/ai/app.stories.tsx +897 -0
- package/mtds/ai/atlas.mdx +82 -0
- package/mtds/ai/atlas.stories.tsx +424 -0
- package/mtds/ai/avatar.mdx +45 -0
- package/mtds/ai/avatar.stories.tsx +109 -0
- package/mtds/ai/badge.mdx +70 -0
- package/mtds/ai/badge.stories.tsx +122 -0
- package/mtds/ai/breadcrumbs.mdx +36 -0
- package/mtds/ai/breadcrumbs.stories.tsx +158 -0
- package/mtds/ai/button.mdx +179 -0
- package/mtds/ai/button.stories.tsx +440 -0
- package/mtds/ai/card.mdx +51 -0
- package/mtds/ai/card.stories.tsx +469 -0
- package/mtds/ai/chart.mdx +67 -0
- package/mtds/ai/chart.stories.tsx +519 -0
- package/mtds/ai/chip.mdx +71 -0
- package/mtds/ai/chip.stories.tsx +211 -0
- package/mtds/ai/details.mdx +33 -0
- package/mtds/ai/details.stories.tsx +91 -0
- package/mtds/ai/dialog.mdx +38 -0
- package/mtds/ai/dialog.stories.tsx +373 -0
- package/mtds/ai/divider.mdx +19 -0
- package/mtds/ai/divider.stories.tsx +50 -0
- package/mtds/ai/errorsummary.mdx +26 -0
- package/mtds/ai/errorsummary.stories.tsx +137 -0
- package/mtds/ai/field.mdx +86 -0
- package/mtds/ai/field.stories.tsx +863 -0
- package/mtds/ai/fieldset.mdx +126 -0
- package/mtds/ai/fieldset.stories.tsx +298 -0
- package/mtds/ai/fileupload.mdx +16 -0
- package/mtds/ai/fileupload.stories.tsx +126 -0
- package/mtds/ai/helptext.mdx +24 -0
- package/mtds/ai/helptext.stories.tsx +106 -0
- package/mtds/ai/input.mdx +223 -0
- package/mtds/ai/input.stories.tsx +352 -0
- package/mtds/ai/law.mdx +115 -0
- package/mtds/ai/law.stories.tsx +168 -0
- package/mtds/ai/layout.mdx +145 -0
- package/mtds/ai/layout.stories.tsx +443 -0
- package/mtds/ai/link.mdx +45 -0
- package/mtds/ai/link.stories.tsx +44 -0
- package/mtds/ai/logo.mdx +86 -0
- package/mtds/ai/logo.stories.tsx +146 -0
- package/mtds/ai/pagination.mdx +136 -0
- package/mtds/ai/pagination.stories.tsx +404 -0
- package/mtds/ai/popover.mdx +86 -0
- package/mtds/ai/popover.stories.tsx +355 -0
- package/mtds/ai/print.mdx +96 -0
- package/mtds/ai/print.stories.tsx +839 -0
- package/mtds/ai/progress.mdx +41 -0
- package/mtds/ai/progress.stories.tsx +141 -0
- package/mtds/ai/skeleton.mdx +26 -0
- package/mtds/ai/skeleton.stories.tsx +131 -0
- package/mtds/ai/spinner.mdx +26 -0
- package/mtds/ai/spinner.stories.tsx +72 -0
- package/mtds/ai/steps.mdx +37 -0
- package/mtds/ai/steps.stories.tsx +568 -0
- package/mtds/ai/table.mdx +124 -0
- package/mtds/ai/table.stories.tsx +1715 -0
- package/mtds/ai/tabs.mdx +106 -0
- package/mtds/ai/tabs.stories.tsx +159 -0
- package/mtds/ai/tag.mdx +49 -0
- package/mtds/ai/tag.stories.tsx +111 -0
- package/mtds/ai/toast.mdx +67 -0
- package/mtds/ai/toast.stories.tsx +215 -0
- package/mtds/ai/togglegroup.mdx +75 -0
- package/mtds/ai/togglegroup.stories.tsx +96 -0
- package/mtds/ai/tooltip.mdx +32 -0
- package/mtds/ai/tooltip.stories.tsx +34 -0
- package/mtds/ai/typography.mdx +67 -0
- package/mtds/ai/typography.stories.tsx +798 -0
- package/mtds/ai/validation.mdx +19 -0
- package/mtds/ai/validation.stories.tsx +45 -0
- package/mtds/atlas/atlas-element.js +1 -1
- package/mtds/chart/chart-lines.js +19 -19
- package/mtds/chart/chart-lines.js.map +1 -1
- package/mtds/chart/chart.css.js +16 -1
- package/mtds/chart/chart.css.js.map +1 -1
- package/mtds/chart/chart.stories.d.ts +1 -0
- package/mtds/index.iife.js +32 -17
- package/mtds/package.json.js +1 -1
- package/mtds/styles.css +1 -1
- package/mtds/table/table-observer.js +26 -15
- package/mtds/table/table-observer.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Button, Flex, toast } from "../react";
|
|
3
|
+
import styles from "../styles.module.css";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Designsystem/Toast",
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: "padded",
|
|
9
|
+
},
|
|
10
|
+
decorators: [
|
|
11
|
+
(Story) => (
|
|
12
|
+
<div style={{ minHeight: 200 }}>
|
|
13
|
+
<Story />
|
|
14
|
+
</div>
|
|
15
|
+
),
|
|
16
|
+
],
|
|
17
|
+
} satisfies Meta;
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
let count = 1;
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
render: () => (
|
|
25
|
+
<button
|
|
26
|
+
onClick={() => toast(`Toast #${++count}`)}
|
|
27
|
+
type="button"
|
|
28
|
+
className={styles.button}
|
|
29
|
+
data-variant="secondary"
|
|
30
|
+
>
|
|
31
|
+
Vis en toast
|
|
32
|
+
</button>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const React: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<Button
|
|
39
|
+
onClick={() => toast(<span>Toast #{++count}</span>)}
|
|
40
|
+
data-variant="secondary"
|
|
41
|
+
>
|
|
42
|
+
Vis en toast
|
|
43
|
+
</Button>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Colors: Story = {
|
|
48
|
+
render: () => (
|
|
49
|
+
<Flex>
|
|
50
|
+
<button
|
|
51
|
+
onClick={() => toast("Toast default")}
|
|
52
|
+
type="button"
|
|
53
|
+
className={styles.button}
|
|
54
|
+
data-variant="secondary"
|
|
55
|
+
>
|
|
56
|
+
Vis default
|
|
57
|
+
</button>
|
|
58
|
+
<button
|
|
59
|
+
onClick={() => toast.info("Toast info")}
|
|
60
|
+
type="button"
|
|
61
|
+
className={styles.button}
|
|
62
|
+
data-variant="secondary"
|
|
63
|
+
data-color="info"
|
|
64
|
+
>
|
|
65
|
+
Vis info
|
|
66
|
+
</button>
|
|
67
|
+
<button
|
|
68
|
+
onClick={() => toast.success("Toast success")}
|
|
69
|
+
type="button"
|
|
70
|
+
className={styles.button}
|
|
71
|
+
data-variant="secondary"
|
|
72
|
+
data-color="success"
|
|
73
|
+
>
|
|
74
|
+
Vis success
|
|
75
|
+
</button>
|
|
76
|
+
<button
|
|
77
|
+
onClick={() => toast.warning("Toast warning")}
|
|
78
|
+
type="button"
|
|
79
|
+
className={styles.button}
|
|
80
|
+
data-variant="secondary"
|
|
81
|
+
data-color="warning"
|
|
82
|
+
>
|
|
83
|
+
Vis warning
|
|
84
|
+
</button>
|
|
85
|
+
<button
|
|
86
|
+
onClick={() => toast.danger("Toast danger")}
|
|
87
|
+
type="button"
|
|
88
|
+
className={styles.button}
|
|
89
|
+
data-variant="secondary"
|
|
90
|
+
data-color="danger"
|
|
91
|
+
>
|
|
92
|
+
Vis danger
|
|
93
|
+
</button>
|
|
94
|
+
<button
|
|
95
|
+
onClick={() => toast.neutral("Toast neutral")}
|
|
96
|
+
type="button"
|
|
97
|
+
className={styles.button}
|
|
98
|
+
data-variant="secondary"
|
|
99
|
+
data-color="neutral"
|
|
100
|
+
>
|
|
101
|
+
Vis neutral
|
|
102
|
+
</button>
|
|
103
|
+
</Flex>
|
|
104
|
+
),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const someApiCall = () => new Promise((resolve) => setTimeout(resolve, 2000));
|
|
108
|
+
export const WithUpdates: Story = {
|
|
109
|
+
render: () => (
|
|
110
|
+
<button
|
|
111
|
+
onClick={() => {
|
|
112
|
+
const id = toast.info(<span>Toast loading</span>, { busy: true });
|
|
113
|
+
someApiCall()
|
|
114
|
+
.then(() => toast.success("Ferdig!", { id, busy: false }))
|
|
115
|
+
.catch(() => toast.danger("Feil!", { id, busy: false }));
|
|
116
|
+
}}
|
|
117
|
+
type="button"
|
|
118
|
+
className={styles.button}
|
|
119
|
+
data-variant="secondary"
|
|
120
|
+
>
|
|
121
|
+
Vis laster
|
|
122
|
+
</button>
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const WithPromise: Story = {
|
|
127
|
+
render: () => (
|
|
128
|
+
<button
|
|
129
|
+
onClick={() =>
|
|
130
|
+
toast.promise(someApiCall, {
|
|
131
|
+
loading: <span>Toast loading</span>,
|
|
132
|
+
success: "Handlingen ble fullført",
|
|
133
|
+
error: "Noe gikk galt under utføring",
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
type="button"
|
|
137
|
+
className={styles.button}
|
|
138
|
+
data-variant="secondary"
|
|
139
|
+
>
|
|
140
|
+
Vis promise
|
|
141
|
+
</button>
|
|
142
|
+
),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export const WithNoTimeout: Story = {
|
|
146
|
+
render: () => (
|
|
147
|
+
<button
|
|
148
|
+
onClick={() => toast("Blir stående åpen", { timeout: false })}
|
|
149
|
+
type="button"
|
|
150
|
+
className={styles.button}
|
|
151
|
+
data-variant="secondary"
|
|
152
|
+
>
|
|
153
|
+
Vis uten automatisk lukking
|
|
154
|
+
</button>
|
|
155
|
+
),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const WithCustomClose: Story = {
|
|
159
|
+
render: () => (
|
|
160
|
+
<div className={styles.prose}>
|
|
161
|
+
<button
|
|
162
|
+
onClick={() => toast("Ingen lukke-kryss", { closedby: "none" })}
|
|
163
|
+
type="button"
|
|
164
|
+
className={styles.button}
|
|
165
|
+
data-variant="secondary"
|
|
166
|
+
>
|
|
167
|
+
Vis uten lukke-kryss
|
|
168
|
+
</button>
|
|
169
|
+
<button
|
|
170
|
+
onClick={() =>
|
|
171
|
+
toast.info(
|
|
172
|
+
<div className={styles.prose}>
|
|
173
|
+
<p>Pellentesque scelerisque urna orci in placerat.</p>
|
|
174
|
+
<button
|
|
175
|
+
className={styles.button}
|
|
176
|
+
commandfor="my-toast"
|
|
177
|
+
command="close"
|
|
178
|
+
data-variant="primary"
|
|
179
|
+
type="button"
|
|
180
|
+
>
|
|
181
|
+
Ok
|
|
182
|
+
</button>
|
|
183
|
+
</div>,
|
|
184
|
+
{ closedby: "none", timeout: false, id: "my-toast" },
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
type="button"
|
|
188
|
+
className={styles.button}
|
|
189
|
+
data-variant="secondary"
|
|
190
|
+
>
|
|
191
|
+
Vis egen lukk knapp
|
|
192
|
+
</button>
|
|
193
|
+
</div>
|
|
194
|
+
),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export const AsHTML: Story = {
|
|
198
|
+
render: () => (
|
|
199
|
+
<>
|
|
200
|
+
<button
|
|
201
|
+
onClick={() =>
|
|
202
|
+
document.querySelector<HTMLDialogElement>("#my-toast")?.show()
|
|
203
|
+
}
|
|
204
|
+
type="button"
|
|
205
|
+
className={styles.button}
|
|
206
|
+
data-variant="secondary"
|
|
207
|
+
>
|
|
208
|
+
Vis en toast
|
|
209
|
+
</button>
|
|
210
|
+
<dialog id="my-toast" className={styles.toast}>
|
|
211
|
+
Toasten
|
|
212
|
+
</dialog>
|
|
213
|
+
</>
|
|
214
|
+
),
|
|
215
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Example, CssVariables } from '../../.storybook/blocks';
|
|
3
|
+
import * as stories from './togglegroup.stories';
|
|
4
|
+
import { Grid } from '../react';
|
|
5
|
+
import { Flex } from '../react';
|
|
6
|
+
import styles from '../styles.module.css';
|
|
7
|
+
import { TextAlignCenterIcon, TextAlignLeftIcon, TextAlignRightIcon } from '@phosphor-icons/react';
|
|
8
|
+
|
|
9
|
+
<Meta of={stories} />
|
|
10
|
+
|
|
11
|
+
# Togglegroup
|
|
12
|
+
> ToggleGroup lar brukeren ta valg som påvirker innholdet på siden. Komponenten består av en gruppe knapper som henger sammen og bare én knapp kan være valgt om gangen.
|
|
13
|
+
|
|
14
|
+
## Kode
|
|
15
|
+
- Bruk klassen `togglegroup` på `<fieldset>` med `data-toggle-group="LABEL-PÅ-GRUPPEN"`
|
|
16
|
+
- Legg `<label><input type="radio">` elementer inni med samme `name` og `checked` på valgt verdier
|
|
17
|
+
<Canvas of={stories.Default} />
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Skikk og bruk
|
|
21
|
+
|
|
22
|
+
<Grid data-items={350} data-gap="5">
|
|
23
|
+
> ✅ **Egnet til:**<br />Filtrering eller endring av visning av samme innhold
|
|
24
|
+
|
|
25
|
+
> ❌ **Uegnet til:**<br />Navigasjon eller erstatning for radio/checkbox
|
|
26
|
+
</Grid>
|
|
27
|
+
|
|
28
|
+
<Flex data-items="350">
|
|
29
|
+
{/* Togglegroup med ikon */}
|
|
30
|
+
<Example data-color="success" text="ToggleGroup med bare ikoner bør kun brukes i ekspertløsninger. Bruk tooltip sammen med ikon." zoom="100%">
|
|
31
|
+
<div className={styles.grid}>
|
|
32
|
+
<fieldset className={styles.togglegroup} data-toggle-group="Mappe">
|
|
33
|
+
<label className={styles.button} data-tooltip="Venstrejustert">
|
|
34
|
+
<input type="radio" name="my-icon-example-1" value="left" />
|
|
35
|
+
<TextAlignLeftIcon />
|
|
36
|
+
</label>
|
|
37
|
+
<label className={styles.button} data-tooltip="Sentrert">
|
|
38
|
+
<input type="radio" name="my-icon-example-1" value="center" defaultChecked />
|
|
39
|
+
<TextAlignCenterIcon />
|
|
40
|
+
</label>
|
|
41
|
+
<label className={styles.button} data-tooltip="Høyrejustert">
|
|
42
|
+
<input type="radio" name="my-icon-example-1" value="right" />
|
|
43
|
+
<TextAlignRightIcon />
|
|
44
|
+
</label>
|
|
45
|
+
</fieldset>
|
|
46
|
+
</div>
|
|
47
|
+
</Example>
|
|
48
|
+
|
|
49
|
+
<Example data-color="danger" text="ToggleGroup med bare ikoner bør ha tooltip." zoom="100%">
|
|
50
|
+
<div className={styles.grid}>
|
|
51
|
+
<fieldset className={styles.togglegroup} data-toggle-group="Mappe">
|
|
52
|
+
<label className={styles.button}>
|
|
53
|
+
<input type="radio" name="my-icon-example-2" value="left" />
|
|
54
|
+
<TextAlignLeftIcon />
|
|
55
|
+
</label>
|
|
56
|
+
<label className={styles.button}>
|
|
57
|
+
<input type="radio" name="my-icon-example-2" value="center" defaultChecked />
|
|
58
|
+
<TextAlignCenterIcon />
|
|
59
|
+
</label>
|
|
60
|
+
<label className={styles.button}>
|
|
61
|
+
<input type="radio" name="my-icon-example-2" value="right" />
|
|
62
|
+
<TextAlignRightIcon />
|
|
63
|
+
</label>
|
|
64
|
+
</fieldset>
|
|
65
|
+
</div>
|
|
66
|
+
</Example>
|
|
67
|
+
</Flex>
|
|
68
|
+
|
|
69
|
+
## Med lenker
|
|
70
|
+
|
|
71
|
+
- Hvis du ønsker lenker istedenfor radio-knapper: Bruk `<nav>`, ikke `<fieldset>`
|
|
72
|
+
- Bruk `aria-current="true"` på den aktive lenken
|
|
73
|
+
<Canvas of={stories.AsLinks} />
|
|
74
|
+
|
|
75
|
+
<CssVariables component="togglegroup" />
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TextAlignCenterIcon,
|
|
3
|
+
TextAlignLeftIcon,
|
|
4
|
+
TextAlignRightIcon,
|
|
5
|
+
} from "@phosphor-icons/react";
|
|
6
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { Togglegroup } from "../react";
|
|
9
|
+
import styles from "../styles.module.css";
|
|
10
|
+
|
|
11
|
+
const meta = {
|
|
12
|
+
title: "Designsystem/Togglegroup",
|
|
13
|
+
} satisfies Meta;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
render: () => (
|
|
20
|
+
<div className={styles.grid}>
|
|
21
|
+
<fieldset className={styles.togglegroup} data-toggle-group="Mappe">
|
|
22
|
+
<label className={styles.button}>
|
|
23
|
+
<input type="radio" name="my-toggles" value="innboks" />
|
|
24
|
+
Innboks
|
|
25
|
+
</label>
|
|
26
|
+
<label className={styles.button}>
|
|
27
|
+
<input type="radio" name="my-toggles" value="utkast" defaultChecked />
|
|
28
|
+
Utkast
|
|
29
|
+
</label>
|
|
30
|
+
<label className={styles.button}>
|
|
31
|
+
<input type="radio" name="my-toggles" value="arkiv" />
|
|
32
|
+
Arkiv
|
|
33
|
+
</label>
|
|
34
|
+
<label className={styles.button}>
|
|
35
|
+
<input type="radio" name="my-toggles" value="sendt" />
|
|
36
|
+
Sendt
|
|
37
|
+
</label>
|
|
38
|
+
</fieldset>
|
|
39
|
+
<fieldset className={styles.togglegroup} data-toggle-group="Mappe">
|
|
40
|
+
<label className={styles.button}>
|
|
41
|
+
<input type="radio" name="my-icon-toggle" value="left" />
|
|
42
|
+
<TextAlignLeftIcon />
|
|
43
|
+
</label>
|
|
44
|
+
<label className={styles.button}>
|
|
45
|
+
<input
|
|
46
|
+
type="radio"
|
|
47
|
+
name="my-icon-toggle"
|
|
48
|
+
value="center"
|
|
49
|
+
defaultChecked
|
|
50
|
+
/>
|
|
51
|
+
<TextAlignCenterIcon />
|
|
52
|
+
</label>
|
|
53
|
+
<label className={styles.button}>
|
|
54
|
+
<input type="radio" name="my-icon-toggle" value="right" />
|
|
55
|
+
<TextAlignRightIcon />
|
|
56
|
+
</label>
|
|
57
|
+
</fieldset>
|
|
58
|
+
</div>
|
|
59
|
+
),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const React: Story = {
|
|
63
|
+
render: () => {
|
|
64
|
+
const items = ["Innboks", "Utkast", "Arkiv", "Sendt"];
|
|
65
|
+
const [value, setValue] = useState(items[1]);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<Togglegroup data-toggle-group="Mappe">
|
|
69
|
+
{items.map((item) => (
|
|
70
|
+
<Togglegroup.Item
|
|
71
|
+
checked={value === item}
|
|
72
|
+
key={item}
|
|
73
|
+
name="react-toggles"
|
|
74
|
+
onChange={() => setValue(item)}
|
|
75
|
+
value={item}
|
|
76
|
+
>
|
|
77
|
+
{item}
|
|
78
|
+
</Togglegroup.Item>
|
|
79
|
+
))}
|
|
80
|
+
</Togglegroup>
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const AsLinks: Story = {
|
|
86
|
+
render: () => (
|
|
87
|
+
<nav className={styles.togglegroup} data-toggle-group="Valgknapper">
|
|
88
|
+
<a href="#liste" className={styles.button} aria-current="true">
|
|
89
|
+
Liste
|
|
90
|
+
</a>
|
|
91
|
+
<a href="#tidslinje" className={styles.button}>
|
|
92
|
+
Tidslinje
|
|
93
|
+
</a>
|
|
94
|
+
</nav>
|
|
95
|
+
),
|
|
96
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Example, CssVariables } from '../../.storybook/blocks';
|
|
3
|
+
import * as stories from './tooltip.stories';
|
|
4
|
+
import { Flex } from '../react';
|
|
5
|
+
import styles from '../styles.module.css';
|
|
6
|
+
|
|
7
|
+
<Meta of={stories} />
|
|
8
|
+
|
|
9
|
+
# Tooltip
|
|
10
|
+
> Tooltip viser kort informasjon når brukeren holder musepekeren over (hover) eller fokuserer på et element. Den brukes til sekundær informasjon, for eksempel til å forklare hva et symbol betyr.
|
|
11
|
+
|
|
12
|
+
## Kode
|
|
13
|
+
- Bruk `data-tooltip="Hjelpetekst"` på hvilet et interaktivt element
|
|
14
|
+
- Bruk `data-tooltip-position="top | right | bottom | left"` for å endre plassering
|
|
15
|
+
- Dersom elementet ikke er interaktivt; legg på `tabindex="0"`
|
|
16
|
+
- Teksten blir også automatisk tilgjengelig for skjermlesere
|
|
17
|
+
- **Merk:** Tooltip senterer seg til sitt anker, så bruk en `<span data-tooltip="">` dersom du ønsker tooltip rundt kun tekst
|
|
18
|
+
<Canvas of={stories.Default} />
|
|
19
|
+
|
|
20
|
+
<CssVariables component="tooltip" />
|
|
21
|
+
|
|
22
|
+
## Skikk og bruk
|
|
23
|
+
<Flex data-items="350">
|
|
24
|
+
{/* Tooltip med lang tekst */}
|
|
25
|
+
<Example data-color="success" text="Bruk korte konsise forklaringer i Tooltip." zoom="100%">
|
|
26
|
+
<button type="button" className={styles.button} data-tooltip="Tooltip eksempel">Hover meg</button>
|
|
27
|
+
</Example>
|
|
28
|
+
|
|
29
|
+
<Example data-color="danger" text="Unngå lange tekster i tooltip. Bruk maks fire ord. Bruk heller popover hvis du trenger lengre forklaringer." zoom="100%">
|
|
30
|
+
<button type="button" className={styles.button} data-tooltip="Når du trykker på denne knappen vil det ikke skje noen ting. Dette er bare et eksempel på hvordan en tooltip ikke skal være.">Hover meg</button>
|
|
31
|
+
</Example>
|
|
32
|
+
</Flex>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { HeartIcon } from "@phosphor-icons/react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
|
+
import { Button } from "../react";
|
|
4
|
+
import styles from "../styles.module.css";
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Designsystem/Tooltip",
|
|
8
|
+
decorators: [
|
|
9
|
+
(Story) => (
|
|
10
|
+
<span className={styles.flex}>
|
|
11
|
+
<Story />
|
|
12
|
+
</span>
|
|
13
|
+
),
|
|
14
|
+
],
|
|
15
|
+
} satisfies Meta;
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
type Story = StoryObj<typeof meta>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
render: () => (
|
|
22
|
+
<button type="button" className={styles.button} data-tooltip="Innhold her">
|
|
23
|
+
Hold over meg
|
|
24
|
+
</button>
|
|
25
|
+
),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const React: Story = {
|
|
29
|
+
render: () => <Button data-tooltip="Innhold her">Hold over meg</Button>,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Icon: Story = {
|
|
33
|
+
render: () => <HeartIcon data-tooltip="Innhold her" tabIndex={0} />,
|
|
34
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Example, CssVariables, JumpTo } from '../../.storybook/blocks';
|
|
3
|
+
import { Button, Popover } from '../react.tsx';
|
|
4
|
+
import * as stories from './typography.stories';
|
|
5
|
+
import { Flex } from '../react';
|
|
6
|
+
import styles from '../styles.module.css';
|
|
7
|
+
import { BuildingOfficeIcon, HeartIcon } from '@phosphor-icons/react';
|
|
8
|
+
|
|
9
|
+
<Meta of={stories} />
|
|
10
|
+
|
|
11
|
+
# Typography
|
|
12
|
+
> Vi bruker vår egen open source font Mattilsynet Sans i alle løsninger. God og lesbar typografi er et viktig virkemiddel både når vi skal ivareta Mattilsynets identitet og når vi bygger brukervennlige løsninger.
|
|
13
|
+
|
|
14
|
+
<JumpTo />
|
|
15
|
+
|
|
16
|
+
## Text
|
|
17
|
+
- All tekst er automatisk satt til Figmas text style `text/default`
|
|
18
|
+
- Bruk klassen `ingress` for introtekster og <button type="button" data-popover="inline" popoverTarget="styles">`styles.muted`</button> eller `<small>` elementet for mindre tekst
|
|
19
|
+
- Tekststørrelser påvirkes av `data-size` (`mode: size` i Figma), og av teknikken [fluid typography](https://utopia.fyi/blog/designing-with-fluid-type-scales) som gradvis skalerer font ned et nivå basert på skjermbredde.
|
|
20
|
+
<Canvas of={stories.Default} />
|
|
21
|
+
<Popover id="styles">`import { styles } from '@mattilsynet/design'`</Popover>
|
|
22
|
+
|
|
23
|
+
## Heading
|
|
24
|
+
- Bruk klassen `styles.heading` på `<h[1-6]>` eller `<Heading as="h[1-6]">` komponenten
|
|
25
|
+
- Bruk `data-size="2xs | xs | sm | md | lg | xl | 2xl"`
|
|
26
|
+
- Bruk `data-justify="start | center | end"` for å endre tekstjustering
|
|
27
|
+
- I React kan du bruke `as="h1 | h2 | h3 | h4 | h5 | h6"` for å endre semantisk overskriftsnivå, hvor `h2` er default.
|
|
28
|
+
|
|
29
|
+
> **Merk:** `data-size` endrer kun størrelse - ikke semantisk overskriftsnivå. Benytt alltid korrekt HTML `<h[1-6]>` eller `as="h[1-6]"` for [god universell utforming →](https://www.uutilsynet.no/veiledning/246-overskrifter-og-ledetekster/1253)
|
|
30
|
+
|
|
31
|
+
<Canvas of={stories.HeadingStory} />
|
|
32
|
+
|
|
33
|
+
## Prose
|
|
34
|
+
- Bruk klassen `prose` på typisk `div` eller annen container som har prosa/skjema/typografisk innhold
|
|
35
|
+
- `Prose` styler direkte barn med typografisk justert margin over og under for god lesbarhet
|
|
36
|
+
- Bruk `data-justify="start | center | end"` for å endre tekstjustering
|
|
37
|
+
<div className="sbdocs-canvas-thumbnail">
|
|
38
|
+
<Button data-arrow data-variant="primary" href="?path=/story/designsystem-typography--prose">Se prose-layout i egen visning</Button>
|
|
39
|
+
<Canvas className="sbdocs-canvas--max-height" of={stories.Prose} />
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
## Info
|
|
43
|
+
- Bruk `info` rundt ledetekst+verdi, ikon+verdi eller kun verdi for enkelt, responsivt oppsett
|
|
44
|
+
- Bruk `<svg>` for ikon eller `<i>` rundt ikon dersom svg ikke er mulig
|
|
45
|
+
- Bruk `<strong>` som direkte barn, rundt ledetekst eller verdi
|
|
46
|
+
- Bruk `<span data-nowrap>` som direkte barn for å å tvinge tekst på én linje
|
|
47
|
+
- Bruk `data-size="sm | md | lg"` for å endre størrelse
|
|
48
|
+
- Bruk `data-variant="circle"` for å få sirkel rundt ikonet
|
|
49
|
+
- Bruk `data-color="success | warning | danger"` på sirkevariant for å endre farge
|
|
50
|
+
- Kan også brukes rundt andre elementer for å lage informasjonsoppsett
|
|
51
|
+
<Canvas of={stories.InfoStory} />
|
|
52
|
+
|
|
53
|
+
<Flex data-items="350">
|
|
54
|
+
|
|
55
|
+
{/* Info med ikon i sirkel */}
|
|
56
|
+
<Example data-color="success" text="Med varianten circle skal både ledetekst og informasjon alltid vises." zoom="100%">
|
|
57
|
+
<div className={styles.info} data-variant="circle"><BuildingOfficeIcon /> <strong>Firma</strong>Fisk & Video AS</div>
|
|
58
|
+
</Example>
|
|
59
|
+
|
|
60
|
+
<Example data-color="danger" text="Unngå bare informasjonstekst eller ledetekst når du bruker circle." zoom="100%">
|
|
61
|
+
<div className={styles.info} data-variant="circle"><BuildingOfficeIcon /> Fisk & Video AS</div>
|
|
62
|
+
</Example>
|
|
63
|
+
|
|
64
|
+
</Flex>
|
|
65
|
+
|
|
66
|
+
<CssVariables component="prose" />
|
|
67
|
+
|