@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.
Files changed (90) hide show
  1. package/mtds/ai/AGENTS.md +892 -0
  2. package/mtds/ai/alert.mdx +63 -0
  3. package/mtds/ai/alert.stories.tsx +128 -0
  4. package/mtds/ai/analytics.mdx +185 -0
  5. package/mtds/ai/app.mdx +60 -0
  6. package/mtds/ai/app.stories.tsx +897 -0
  7. package/mtds/ai/atlas.mdx +82 -0
  8. package/mtds/ai/atlas.stories.tsx +424 -0
  9. package/mtds/ai/avatar.mdx +45 -0
  10. package/mtds/ai/avatar.stories.tsx +109 -0
  11. package/mtds/ai/badge.mdx +70 -0
  12. package/mtds/ai/badge.stories.tsx +122 -0
  13. package/mtds/ai/breadcrumbs.mdx +36 -0
  14. package/mtds/ai/breadcrumbs.stories.tsx +158 -0
  15. package/mtds/ai/button.mdx +179 -0
  16. package/mtds/ai/button.stories.tsx +440 -0
  17. package/mtds/ai/card.mdx +51 -0
  18. package/mtds/ai/card.stories.tsx +469 -0
  19. package/mtds/ai/chart.mdx +67 -0
  20. package/mtds/ai/chart.stories.tsx +519 -0
  21. package/mtds/ai/chip.mdx +71 -0
  22. package/mtds/ai/chip.stories.tsx +211 -0
  23. package/mtds/ai/details.mdx +33 -0
  24. package/mtds/ai/details.stories.tsx +91 -0
  25. package/mtds/ai/dialog.mdx +38 -0
  26. package/mtds/ai/dialog.stories.tsx +373 -0
  27. package/mtds/ai/divider.mdx +19 -0
  28. package/mtds/ai/divider.stories.tsx +50 -0
  29. package/mtds/ai/errorsummary.mdx +26 -0
  30. package/mtds/ai/errorsummary.stories.tsx +137 -0
  31. package/mtds/ai/field.mdx +86 -0
  32. package/mtds/ai/field.stories.tsx +863 -0
  33. package/mtds/ai/fieldset.mdx +126 -0
  34. package/mtds/ai/fieldset.stories.tsx +298 -0
  35. package/mtds/ai/fileupload.mdx +16 -0
  36. package/mtds/ai/fileupload.stories.tsx +126 -0
  37. package/mtds/ai/helptext.mdx +24 -0
  38. package/mtds/ai/helptext.stories.tsx +106 -0
  39. package/mtds/ai/input.mdx +223 -0
  40. package/mtds/ai/input.stories.tsx +352 -0
  41. package/mtds/ai/law.mdx +115 -0
  42. package/mtds/ai/law.stories.tsx +168 -0
  43. package/mtds/ai/layout.mdx +145 -0
  44. package/mtds/ai/layout.stories.tsx +443 -0
  45. package/mtds/ai/link.mdx +45 -0
  46. package/mtds/ai/link.stories.tsx +44 -0
  47. package/mtds/ai/logo.mdx +86 -0
  48. package/mtds/ai/logo.stories.tsx +146 -0
  49. package/mtds/ai/pagination.mdx +136 -0
  50. package/mtds/ai/pagination.stories.tsx +404 -0
  51. package/mtds/ai/popover.mdx +86 -0
  52. package/mtds/ai/popover.stories.tsx +355 -0
  53. package/mtds/ai/print.mdx +96 -0
  54. package/mtds/ai/print.stories.tsx +839 -0
  55. package/mtds/ai/progress.mdx +41 -0
  56. package/mtds/ai/progress.stories.tsx +141 -0
  57. package/mtds/ai/skeleton.mdx +26 -0
  58. package/mtds/ai/skeleton.stories.tsx +131 -0
  59. package/mtds/ai/spinner.mdx +26 -0
  60. package/mtds/ai/spinner.stories.tsx +72 -0
  61. package/mtds/ai/steps.mdx +37 -0
  62. package/mtds/ai/steps.stories.tsx +568 -0
  63. package/mtds/ai/table.mdx +124 -0
  64. package/mtds/ai/table.stories.tsx +1715 -0
  65. package/mtds/ai/tabs.mdx +106 -0
  66. package/mtds/ai/tabs.stories.tsx +159 -0
  67. package/mtds/ai/tag.mdx +49 -0
  68. package/mtds/ai/tag.stories.tsx +111 -0
  69. package/mtds/ai/toast.mdx +67 -0
  70. package/mtds/ai/toast.stories.tsx +215 -0
  71. package/mtds/ai/togglegroup.mdx +75 -0
  72. package/mtds/ai/togglegroup.stories.tsx +96 -0
  73. package/mtds/ai/tooltip.mdx +32 -0
  74. package/mtds/ai/tooltip.stories.tsx +34 -0
  75. package/mtds/ai/typography.mdx +67 -0
  76. package/mtds/ai/typography.stories.tsx +798 -0
  77. package/mtds/ai/validation.mdx +19 -0
  78. package/mtds/ai/validation.stories.tsx +45 -0
  79. package/mtds/atlas/atlas-element.js +1 -1
  80. package/mtds/chart/chart-lines.js +19 -19
  81. package/mtds/chart/chart-lines.js.map +1 -1
  82. package/mtds/chart/chart.css.js +16 -1
  83. package/mtds/chart/chart.css.js.map +1 -1
  84. package/mtds/chart/chart.stories.d.ts +1 -0
  85. package/mtds/index.iife.js +32 -17
  86. package/mtds/package.json.js +1 -1
  87. package/mtds/styles.css +1 -1
  88. package/mtds/table/table-observer.js +26 -15
  89. package/mtds/table/table-observer.js.map +1 -1
  90. package/package.json +4 -2
@@ -0,0 +1,82 @@
1
+ import { Meta, Canvas } from '@storybook/addon-docs/blocks';
2
+ import { JumpTo, CssVariables } from '../../.storybook/blocks';
3
+ import * as stories from './atlas.stories';
4
+ import { Table, Popover } from '../react';
5
+ import atlasCSS from './atlas.css?raw';
6
+
7
+ <Meta of={stories} />
8
+
9
+ # Atlas (Eksperimentell)
10
+
11
+ > Atlas er et standardisert oppsett for presentasjon av kart.
12
+
13
+ <JumpTo />
14
+ <Popover id="pop-jsref" style={{ maxWidth: 500 }}>For eksempel via `document.getElementById` eller via `useRef` i React.</Popover>
15
+
16
+ ## Kode
17
+ - Importer `import "@mattilsynet/design/atlas"` og bruk elementene<br />`<mtds-atlas>`, `<mtds-atlas-marker>` og `<mtds-atlas-matgeo>`
18
+ - **React?** Importer `import { Atlas } from "@mattilsynet/design/atlas/react"` og bruk elementene `<Atlas>`, `<Atlas.Marker>` og `<Atlas.Matgeo>`. Husk `"use client"`
19
+ - **Avansert bruk?** Du får tilgang til hele [Leaflet](https://leafletjs.com/) via `import { L } from "@mattilsynet/design/atlas"` eller `import { L } from "@mattilsynet/design/atlas/react"`
20
+ - **Kartlag** leveres av [Kartverket](https://cache.kartverket.no/) for oppnå gjenkjennlige og presise norgeskart
21
+ - **Karttegning** leveres av [Leaflet](https://leafletjs.com/) ([2.0.0@alpha.1](https://leafletjs.com/2025/05/18/leaflet-2.0.0-alpha.html)) i [EPSG:4326 koordinatsystem](https://epsg.io/4326)
22
+
23
+ ## Utsnitt
24
+ - Bruk `data-view="lat, lng, zoom"` for å sette eller endre kartutsnitt
25
+ - Bruk `data-view="fit"` for å få et utsnitt som viser alle markører
26
+ - Du kan også hente Atlas elementet via JS (f.eks `document.getElementById` eller `useRef` i React) og kalle `atlasElement.setView([lat, lng, zoom])` eller `atlasElement.setView('fit')` for å endre utsnitt programatisk
27
+ <Canvas of={stories.WithView} />
28
+
29
+ ## Kartlag
30
+ - Bruk `data-tiles="gray | color"` for å endre kartlag
31
+ <Canvas of={stories.WithColor} />
32
+
33
+ ## Markører
34
+ - Legg elementer i `<mtds-atlas>` eller `<Atlas.Marker>` med `data-marker="lat, lng"`
35
+ - Legg innhold inni for å gi markøren ikon eller tekst
36
+ - Bruk `popovertarget="ID"` for å knytte en popover til markøren
37
+ - Bruk `data-tooltip="TEKST"` for å legge til tooltip
38
+ - Bruk `draggable` for å gjøre markøren flyttbar
39
+ - Bruk `data-color` for å endre farge
40
+ - Du kan style markører via CSS-variabler, enten individuelt eller satt på Atlas-elementet
41
+ <Canvas of={stories.WithMarker} />
42
+
43
+ ## Clustering
44
+ - Bruk `data-cluster="number"` for å aktivere clustring fra til et gitt zoom-nivå og utover
45
+ - Bruk `data-cluster="true"` for clustering på alle zoomnivå. Dette er anbefalt dersom du kan ha datapunker på samme posisjon
46
+ <Canvas of={stories.WithClustering} />
47
+
48
+ ## Popover
49
+ - Legg et Popover element med `id` inni Atlas med ønsket innhold
50
+ - Bruk `popovertarget="ID"` på markører eller matgeo for å tilknytte
51
+ - Du kan også hente Atlas elementet via JS (f.eks `document.getElementById` eller `useRef` i React) og kalle `atlasElement.map.openPopup("content", [lat, lng])` for å åpne en popover programatisk. Dersom du kaller `atlasElement.map.openPopup("#ID", [lat, lng])`, vil popupen automatisk vise innholdet fra et annet element med gitt `ID`.
52
+ <Canvas of={stories.WithPopover} />
53
+
54
+ ## Matgeo
55
+ - Matgeo er Mattilsynets egne stedfestede data fra alle fagområder
56
+ - Du kan vise Matgeo-data i Atlas ved å bruke `<mtds-atlas-matgeo>` eller `<Atlas.Matgeo>`
57
+ - Bruk `data-collection="COLLECTION-ID"` for å velge collection
58
+ - Hvis du ikke setter en gyldig `COLLECTION-ID`, listes mulige collections i konsoll
59
+ - Bruk `data-color` for å endre farge
60
+ - Bruk `popovertarget="ID"` for å knytte en popover til matgeo
61
+ - Lytt til `atlasfeatureclick` (eller `onFeatureClick` i React) for å fange opp klikk på matgeo
62
+ - Bruk `await AtlasMatgeoElement.getCollection()` for å hente collection metadata
63
+ - Bruk `await AtlasElement.getCollections()` for å hente alle collections
64
+ <Canvas of={stories.WithMatgeo} />
65
+
66
+ ## WMS
67
+ - WMS (web map service), er en åpen standard for utveksling av kartlag på tvers av kilder
68
+ - Du kan vise WMS-lag fra f.eks [geonorge](https://kartkatalog.geonorge.no/) ved å bruke `<mtds-atlas-wma>` eller `<Atlas.WMS>`
69
+ - Bruk `data-url="MATRIKKEL-URL-MED-PARAMETER"` for å hente karlag
70
+ <Canvas of={stories.WithWMS} />
71
+
72
+ ## Klikk-for-markør
73
+ - Bruk `data-cursor="pointer"` på `<mtds-atlas>` for å indikere at kartet er klikkbart
74
+ - Lytt til `click`, og sjekk at `event.currentTarget === event.target` for å sikre at klikket skjedde på kartet og ikke en markør eller matgeo
75
+ - Bruk `event.currentTarget.latLngFromPoint(event.clientX, event.clientY)` for å få lat/lng fra klikkpunktet
76
+ <Canvas of={stories.WithClickToAddMarker} />
77
+
78
+ ## Uten scroll-zoom
79
+ - Bruk `data-scroll-zoom="false"` for å deaktivere zooming med scroll-hjul
80
+ <Canvas of={stories.WithoutScrollZoom} />
81
+
82
+ <CssVariables component='atlas' css={atlasCSS} />
@@ -0,0 +1,424 @@
1
+ import { MagnifyingGlassMinusIcon, StarIcon } from "@phosphor-icons/react";
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import type { MTDSAtlasCollection, MTDSAtlasElement } from "../atlas";
5
+ import {
6
+ Button,
7
+ Details,
8
+ Field,
9
+ Fieldset,
10
+ Flex,
11
+ Group,
12
+ Heading,
13
+ Popover,
14
+ Prose,
15
+ toast,
16
+ } from "../react";
17
+ import { Atlas, type AtlasMatgeoProps } from "../react-atlas";
18
+
19
+ const meta = {
20
+ title: "Designsystem/Atlas",
21
+ parameters: {
22
+ layout: "padded",
23
+ },
24
+ } satisfies Meta;
25
+
26
+ export default meta;
27
+ type Story = StoryObj<typeof meta>;
28
+
29
+ const LOREM_IPSUM =
30
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque finibus dui id efficitur lobortis. Aliquam erat volutpat. Pellentesque imperdiet consectetur posuere. Donec ultrices libero eu velit egestas tincidunt. Suspendisse placerat risus non tellus faucibus, eu ultricies augue tempus. Donec vestibulum arcu diam, efficitur auctor lectus placerat vel. Nullam aliquam turpis vel mollis pharetra. Etiam eget pulvinar dui, imperdiet congue nisi. Nullam vel finibus risus. Ut sodales luctus odio quis interdum. Donec ligula quam, viverra vitae finibus a, bibendum quis odio. Quisque sodales erat volutpat condimentum maximus. Sed eget augue sed ligula congue hendrerit id sed turpis. Fusce nec leo fringilla, faucibus turpis a, tristique est. In ac semper libero, nec lacinia tellus.";
31
+
32
+ export const Default: Story = {
33
+ parameters: {
34
+ showInOverview: false,
35
+ },
36
+ render: () => <mtds-atlas />,
37
+ };
38
+
39
+ export const React: Story = {
40
+ parameters: {
41
+ showInOverview: false,
42
+ },
43
+ render: () => <Atlas />,
44
+ };
45
+
46
+ export const WithView: Story = {
47
+ render: () => <Atlas data-view="63.431958, 10.397461, 12" />,
48
+ };
49
+
50
+ export const WithViewAdvanced: Story = {
51
+ render: function Render() {
52
+ const atlasRef = useRef<MTDSAtlasElement>(null);
53
+ const [open, setOpen] = useState<(typeof markers)[number]>();
54
+ const markers = [
55
+ {
56
+ latlng: "59.910815, 10.754078",
57
+ summary: "Oslo",
58
+ content: "Informasjon om Oslo",
59
+ },
60
+ {
61
+ latlng: "63.431958, 10.397461",
62
+ summary: "Trondheim",
63
+ content: "Informasjon om Trondheim",
64
+ },
65
+ {
66
+ latlng: "60.391449, 5.324119",
67
+ summary: "Bergen",
68
+ content: "Informasjon om Bergen",
69
+ },
70
+ ];
71
+
72
+ return (
73
+ <Flex data-items="300" data-nowrap>
74
+ <Atlas ref={atlasRef} data-view={open ? `${open.latlng}, 14` : "fit"}>
75
+ {markers.map((marker) => (
76
+ <Atlas.Marker
77
+ key={marker.summary}
78
+ data-tooltip={marker.summary}
79
+ data-latlng={marker.latlng}
80
+ onClick={() => setOpen(marker)}
81
+ />
82
+ ))}
83
+ </Atlas>
84
+ <Group as={Prose} data-items="200" data-fixed>
85
+ {markers.map((marker) => (
86
+ <Details
87
+ key={marker.summary}
88
+ open={open?.summary === marker.summary}
89
+ name="place"
90
+ >
91
+ <Details.Summary onClick={() => setOpen(marker)}>
92
+ {marker.summary}
93
+ </Details.Summary>
94
+ <div>{marker.content}</div>
95
+ </Details>
96
+ ))}
97
+ <Button onClick={() => setOpen(undefined)}>
98
+ <MagnifyingGlassMinusIcon /> Zoom ut
99
+ </Button>
100
+ </Group>
101
+ </Flex>
102
+ );
103
+ },
104
+ };
105
+
106
+ export const WithColor: Story = {
107
+ render: () => (
108
+ <mtds-atlas data-tiles="color" data-view="63.431958, 10.397461, 12" />
109
+ ),
110
+ };
111
+
112
+ export const WithCustomSize: Story = {
113
+ render: () => (
114
+ <mtds-atlas style={{ width: "100%", height: "calc(100vh - 30px)" }} />
115
+ ),
116
+ };
117
+
118
+ export const WithMarker: Story = {
119
+ render: () => (
120
+ <Atlas data-view="60.722, 10.989, 16">
121
+ <Atlas.Marker data-latlng="60.7223, 10.9861" aria-label="Min markør" />
122
+ <Atlas.Marker
123
+ data-color="info"
124
+ data-latlng="60.72235, 10.9837"
125
+ aria-label="Min markør med stjerne"
126
+ >
127
+ <StarIcon weight="fill" />
128
+ </Atlas.Marker>
129
+ <Atlas.Marker
130
+ data-latlng="60.7222, 10.988"
131
+ aria-label="Min markør med tekst"
132
+ >
133
+ A
134
+ </Atlas.Marker>
135
+ </Atlas>
136
+ ),
137
+ };
138
+ export const WithMarkerStyling: Story = {
139
+ render: () => (
140
+ <Atlas data-view="60.722, 10.989, 16">
141
+ <Atlas.Marker
142
+ data-latlng="60.72235, 10.9837"
143
+ aria-label="Min markør rød"
144
+ data-color="danger"
145
+ />
146
+ <Atlas.Marker
147
+ data-latlng="60.7223, 10.9861"
148
+ aria-label="Min markør styled"
149
+ style={
150
+ {
151
+ "--mtdsc-atlas-marker-size": "var(--mtds-10)",
152
+ "--mtdsc-atlas-marker-inset": "var(--mtds-2)",
153
+ "--mtdsc-atlas-marker-color": "var(--mtds-color-info-base-default)",
154
+ "--mtdsc-atlas-marker-border": "2px solid",
155
+ "--mtdsc-atlas-marker-background":
156
+ "var(--mtds-color-info-base-contrast-default)",
157
+ "--mtdsc-atlas-marker-background-outer":
158
+ "var(--mtds-color-info-base-default)",
159
+ } as React.CSSProperties
160
+ }
161
+ />
162
+ </Atlas>
163
+ ),
164
+ };
165
+
166
+ const getRandomCoordinates = (lat = 60.722, lng = 10.985) =>
167
+ Array.from({ length: 100 }, () => {
168
+ return `${lat + (Math.random() - 0.5) * 0.025}, ${lng + (Math.random() - 0.5) * 0.1}`;
169
+ });
170
+
171
+ export const WithClustering: Story = {
172
+ render: () => (
173
+ <Atlas data-view={"60.722, 10.985, 12"} data-cluster="true">
174
+ {getRandomCoordinates().map((latlng, index) => (
175
+ <Atlas.Marker
176
+ aria-label={`Markør ${index + 1}`}
177
+ key={index.toString()}
178
+ data-latlng={latlng}
179
+ popoverTarget="my-cluster-popover"
180
+ />
181
+ ))}
182
+ <Popover id="my-cluster-popover">Popover</Popover>
183
+ </Atlas>
184
+ ),
185
+ };
186
+
187
+ export const WithPopover: Story = {
188
+ render: () => (
189
+ <Atlas data-view="60.722, 10.985, 16">
190
+ <Atlas.Marker
191
+ aria-label="Markør 1"
192
+ data-latlng="60.722, 10.985"
193
+ popoverTarget="popover-1"
194
+ />
195
+ <Atlas.Marker
196
+ aria-label="Markør 2"
197
+ data-latlng="60.721, 10.980"
198
+ popoverTarget="popover-2"
199
+ />
200
+ <Popover id="popover-1">Popover 1</Popover>
201
+ <Popover id="popover-2">Popover 2</Popover>
202
+ </Atlas>
203
+ ),
204
+ };
205
+
206
+ export const WithPopoverDynamic: Story = {
207
+ render: function Render() {
208
+ const [open, setOpen] = useState(-1);
209
+ const markers = [
210
+ { latlng: "60.722, 10.985", popover: "Min nydelige popover" },
211
+ {
212
+ latlng: "60.721, 10.980",
213
+ popover: (
214
+ <Prose>
215
+ <Heading>Avansert popover</Heading>
216
+ <p>Innhold</p>
217
+ </Prose>
218
+ ),
219
+ },
220
+ ];
221
+
222
+ return (
223
+ <Atlas data-view="60.722, 10.985, 16">
224
+ {markers.map((marker, index) => (
225
+ <Atlas.Marker
226
+ aria-label={`Markør ${index + 1}`}
227
+ data-latlng={marker.latlng}
228
+ key={index.toString()}
229
+ onClick={() => setOpen(index)}
230
+ popoverTarget="my-popover"
231
+ />
232
+ ))}
233
+ <Popover id="my-popover">{markers[open]?.popover}</Popover>
234
+ </Atlas>
235
+ );
236
+ },
237
+ };
238
+
239
+ export const WithMatgeo: Story = {
240
+ render: () => {
241
+ const [content, setContent] = useState("");
242
+
243
+ return (
244
+ <Atlas data-view="60.722, 10.985, 16">
245
+ <Atlas.Matgeo
246
+ data-collection="bygg"
247
+ popoverTarget="my-matgeo-popover"
248
+ onFeatureClick={(event) => {
249
+ setContent(
250
+ JSON.stringify(
251
+ event.detail.targets.map((layer) => layer.feature?.properties),
252
+ null,
253
+ " ",
254
+ ),
255
+ );
256
+ }}
257
+ />
258
+ <Popover as={Prose} id="my-matgeo-popover">
259
+ <pre data-size="sm">{content}</pre>
260
+ </Popover>
261
+ </Atlas>
262
+ );
263
+ },
264
+ };
265
+
266
+ export const WithMatgeoToggle: Story = {
267
+ render: () => {
268
+ const atlasRef = useRef<MTDSAtlasElement>(null);
269
+ const colors = ["info", "success", "warning", "danger"] as const;
270
+ const [content, setContent] = useState("");
271
+ const [collections, setCollections] = useState<
272
+ (MTDSAtlasCollection & { hidden?: boolean })[]
273
+ >([]);
274
+
275
+ const handleFeatureClick: AtlasMatgeoProps["onFeatureClick"] = (event) => {
276
+ const targets = event.detail.targets;
277
+ const props = targets.map((layer) => layer.feature?.properties);
278
+ setContent(JSON.stringify(props, null, " "));
279
+ };
280
+
281
+ useEffect(() => {
282
+ atlasRef.current
283
+ ?.getCollections()
284
+ .then((collections) => setCollections(Object.values(collections)));
285
+ }, []);
286
+
287
+ return (
288
+ <Flex data-nowrap data-items="300">
289
+ <Atlas ref={atlasRef} data-view="60.722, 10.985, 16">
290
+ {collections.map((collection, index) => (
291
+ <Atlas.Matgeo
292
+ hidden={collection.hidden}
293
+ key={collection.id}
294
+ data-collection={collection.id}
295
+ data-color={colors[index % colors.length]}
296
+ popoverTarget="my-matgeo-popover"
297
+ onFeatureClick={handleFeatureClick}
298
+ />
299
+ ))}
300
+ <Popover as={Prose} id="my-matgeo-popover">
301
+ <pre data-size="sm">{content}</pre>
302
+ </Popover>
303
+ </Atlas>
304
+ <Group data-fixed>
305
+ <Fieldset aria-label="Lag">
306
+ {collections.map((collection, index) => (
307
+ <Field
308
+ as="input"
309
+ type="checkbox"
310
+ key={collection.id}
311
+ data-color={colors[index % colors.length]}
312
+ checked={!collection.hidden}
313
+ label={collection.title}
314
+ onChange={() => {
315
+ const clone = collections.slice();
316
+ clone[index].hidden = !clone[index].hidden;
317
+ setCollections(clone);
318
+ }}
319
+ />
320
+ ))}
321
+ </Fieldset>
322
+ </Group>
323
+ </Flex>
324
+ );
325
+ },
326
+ };
327
+
328
+ export const WithWMS: Story = {
329
+ render: () => (
330
+ <Atlas data-view="63.431958, 10.397461, 16">
331
+ <Atlas.WMS data-url="https://wms.geonorge.no/skwms1/wms.matrikkel?request=GetMap&version=1.3.0&layers=matrikkel_WMS&format=image/png&transparent=true" />
332
+ </Atlas>
333
+ ),
334
+ };
335
+
336
+ export const WithTooltip: Story = {
337
+ render: () => (
338
+ <Atlas data-view="60.722, 10.985, 16">
339
+ <Atlas.Marker data-latlng="60.722, 10.985" data-tooltip="Mitt tooltip" />
340
+ </Atlas>
341
+ ),
342
+ };
343
+
344
+ export const WithClickToAddMarker: Story = {
345
+ render: function Render() {
346
+ const atlasRef = useRef<MTDSAtlasElement>(null);
347
+ const [markers, setMarkers] = useState<string[]>([]);
348
+
349
+ return (
350
+ <>
351
+ <Atlas
352
+ role="application"
353
+ ref={atlasRef}
354
+ data-cursor="pointer"
355
+ data-view="60.722, 10.985, 16"
356
+ onClick={({ currentTarget: atlas, clientX, clientY, target }) => {
357
+ if (atlas !== target) return; // Only add if clicking directly on map
358
+ const latlng = atlas.latLngFromPoint(clientX, clientY);
359
+ setMarkers([...markers, `${latlng?.lat}, ${latlng?.lng}`]);
360
+ toast(<code>{`${latlng}`}</code>);
361
+ }}
362
+ >
363
+ {markers.map((latlng, index) => (
364
+ <Atlas.Marker
365
+ key={index.toString()}
366
+ data-latlng={latlng}
367
+ aria-label={`Markør ${index + 1}`}
368
+ draggable
369
+ onClick={() => {
370
+ const clone = [...markers];
371
+ clone.splice(index, 1); // Remove marker
372
+ setMarkers(clone);
373
+ }}
374
+ onDragEnd={(event) => {
375
+ const clone = [...markers];
376
+ clone[index] = event.currentTarget.latlng;
377
+ setMarkers(clone);
378
+ }}
379
+ >
380
+ {index + 1}
381
+ </Atlas.Marker>
382
+ ))}
383
+ </Atlas>
384
+ <ol>
385
+ <li>Klikk på kartet for å legge til markør</li>
386
+ <li>Dra markør for å flytte</li>
387
+ <li>Klikk på markør for å fjerne</li>
388
+ </ol>
389
+ </>
390
+ );
391
+ },
392
+ };
393
+
394
+ export const WithoutScrollZoom: Story = {
395
+ render: () => (
396
+ <Prose>
397
+ <p>{LOREM_IPSUM}</p>
398
+ <Atlas data-scrollzoom="false" />
399
+ <p>{LOREM_IPSUM}</p>
400
+ </Prose>
401
+ ),
402
+ };
403
+
404
+ // export const WithGeoJSON: Story = {
405
+ // render: () => {
406
+ // const atlasRef = useRef<MTDSAtlasElement>(null);
407
+
408
+ // useEffect(() => {
409
+ // const map = atlasRef.current?.map;
410
+ // const url =
411
+ // "https://mattilsynet.avadaptive.dev/api/core/v1/ogc/features/collections/slammelding_spredeareal/items";
412
+
413
+ // if (!map) return;
414
+ // fetch(url)
415
+ // .then((res) => res.json())
416
+ // .then((data) => {
417
+ // console.log(data);
418
+ // L.geoJSON(data).addTo(map);
419
+ // });
420
+ // }, []);
421
+
422
+ // return <Atlas ref={atlasRef} />;
423
+ // },
424
+ // };
@@ -0,0 +1,45 @@
1
+ import { Meta, Canvas } from '@storybook/addon-docs/blocks';
2
+ import { Example, CssVariables } from '../../.storybook/blocks';
3
+ import * as stories from './avatar.stories';
4
+ import styles from '../styles.module.css';
5
+ import { EnvelopeIcon, UserIcon, FilePdfIcon } from '@phosphor-icons/react';
6
+ import { Flex } from '../react';
7
+ import avatar from "./avatar.jpg";
8
+
9
+ <Meta of={stories} />
10
+
11
+ # Avatar
12
+ > Avatar er en komponent som viser et bilde, initialer eller ikon for en person, enhet eller profil.
13
+
14
+ ## Kode
15
+ - Bruk klassen `avatar` på typisk `<span>` eller `<Avatar>` komponenten i React
16
+ <Canvas of={stories.Default} />
17
+
18
+ ## Skikk og bruk
19
+
20
+ <Flex data-items="350">
21
+ {/* Ikoner i Badge: */}
22
+ <Example data-color="success" text="Avatar kan inneholde tekst, bilde eller ikon som representerer en person eller enhet" zoom="100%">
23
+ <div className={styles.flex}>
24
+ <div className={styles.avatar}>MT</div>
25
+ <div className={styles.avatar}>
26
+ <img src={avatar} alt="Navn Navnesen" />
27
+ </div>
28
+ <div className={styles.avatar}>
29
+ <UserIcon aria-label="Navn Navnesen" />
30
+ </div>
31
+ </div>
32
+ </Example>
33
+ <Example data-color="danger" text="Ikke bruk avatar til å representere noe annet enn en person eller enhet, for eksempel et dokument." zoom="100%">
34
+ <div className={styles.avatar}>
35
+ <FilePdfIcon aria-label="PDF fil" />
36
+ </div>
37
+
38
+ </Example>
39
+
40
+ </Flex>
41
+
42
+ ## Sizes
43
+ <Canvas of={stories.Sizes} />
44
+
45
+ <CssVariables component="avatar" />
@@ -0,0 +1,109 @@
1
+ import { UserIcon } from "@phosphor-icons/react";
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { Avatar } from "../react";
4
+ import styles from "../styles.module.css";
5
+ import avatar from "./avatar.jpg";
6
+
7
+ const meta = {
8
+ title: "Designsystem/Avatar",
9
+ decorators: [
10
+ (Story) => (
11
+ <div className={styles.flex} data-align="center">
12
+ <Story />
13
+ </div>
14
+ ),
15
+ ],
16
+ } satisfies Meta;
17
+
18
+ export default meta;
19
+ type Story = StoryObj<typeof meta>;
20
+
21
+ export const Default: Story = {
22
+ render: () => (
23
+ <>
24
+ <div className={styles.avatar}>MT</div>
25
+ <div className={styles.avatar}>
26
+ <img src={avatar} alt="Navn Navnesen" />
27
+ </div>
28
+ <div className={styles.avatar}>
29
+ <UserIcon aria-label="Navn Navnesen" />
30
+ </div>
31
+ </>
32
+ ),
33
+ };
34
+
35
+ export const React: Story = {
36
+ render: () => (
37
+ <>
38
+ <Avatar>MT</Avatar>
39
+ <Avatar>
40
+ <img src={avatar} alt="Navn Navnesen" />
41
+ </Avatar>
42
+ <Avatar href="#">
43
+ <UserIcon aria-label="Navn Navnesen" />
44
+ </Avatar>
45
+ </>
46
+ ),
47
+ };
48
+
49
+ export const Sizes: Story = {
50
+ render: () => (
51
+ <>
52
+ <div className={styles.avatar} data-size="xs">
53
+ XS
54
+ </div>
55
+ <div className={styles.avatar} data-size="sm">
56
+ SM
57
+ </div>
58
+ <div className={styles.avatar} data-size="md">
59
+ MD
60
+ </div>
61
+ <div className={styles.avatar} data-size="lg">
62
+ LG
63
+ </div>
64
+ </>
65
+ ),
66
+ };
67
+
68
+ export const WithBadge: Story = {
69
+ render: () => (
70
+ <>
71
+ <div className={styles.badge}>
72
+ <div className={styles.avatar} data-size="xs">
73
+ <img src={avatar} alt="Navn Navnesen" />
74
+ </div>
75
+ </div>
76
+ <div className={styles.badge}>
77
+ <div className={styles.avatar} data-size="sm">
78
+ <img src={avatar} alt="Navn Navnesen" />
79
+ </div>
80
+ </div>
81
+ <div className={styles.badge}>
82
+ <a className={styles.avatar} data-size="md" href="#none">
83
+ <img src={avatar} alt="Navn Navnesen" />
84
+ </a>
85
+ </div>
86
+ <div className={styles.badge}>
87
+ <button type="button" className={styles.avatar} data-size="lg">
88
+ <img src={avatar} alt="Navn Navnesen" />
89
+ </button>
90
+ </div>
91
+ </>
92
+ ),
93
+ };
94
+
95
+ export const InButton: Story = {
96
+ render: () => (
97
+ <>
98
+ <button type="button" className={styles.button}>
99
+ <div className={styles.avatar} data-size="xs">
100
+ NN
101
+ </div>
102
+ Navn Navnesen
103
+ </button>
104
+ <button type="button" className={styles.button}>
105
+ More buttons
106
+ </button>
107
+ </>
108
+ ),
109
+ };