Compare commits

..
Author SHA1 Message Date
github-actions[bot] c6c721a469 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.19
 - @navikt/ds-icons@0.8.10
 - @navikt/ds-react@0.17.22
 - @navikt/ds-react-internal@0.12.23
2022-04-07 07:31:34 +00:00
Ken b26a906300 [fix] flyttet max-width til token (#1493) 2022-04-07 09:22:04 +02:00
Ken d18a731eed ErrorSummary og Search stories (#1489)
* errorsummary stories

* search story

* rename story
2022-04-07 09:18:10 +02:00
Andreas NordahlandKen cbc5940a40 [fix] prepend svg title id to avoid id starting with num (#1490)
* prepend svg title id to avoid id starting with num

* Update @navikt/core/icons/template.js

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* dont pass unnecessary arg to useId

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2022-04-07 09:17:07 +02:00
github-actions[bot] 104ab0d51a Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.18
2022-04-06 13:32:28 +00:00
Ken 9a73b23e09 [FIX] Readme.md 2022-04-06 15:22:11 +02:00
Martin Berglund 81a18ea271 Prevent SVG-icons in Link from shrinking (#1492) 2022-04-06 15:21:10 +02:00
github-actions[bot] e21bd15423 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.17
2022-04-05 09:08:55 +00:00
larseirikhansen 329124dda9 [fix] invisible line between labels (#1487) 2022-04-05 11:00:02 +02:00
github-actions[bot] 1662dc91c0 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.9
 - @navikt/ds-react@0.17.21
 - @navikt/ds-react-internal@0.12.22
2022-04-05 08:38:26 +00:00
André Roaldseth 071962fc29 [fix] Bruk OR-operator mellom React 17 og 18 (#1488)
* Bruk OR-operator mellom React 17 og 18

* Bruk OR-operator mellom React 17 og 18

* Bruk OR-operator mellom React 17 og 18
2022-04-05 10:29:09 +02:00
Ken 0c5085002f Checkbox + Radio stories (#1486)
* checkbox stories

* radio-stories

* radio-stories
2022-04-05 10:20:34 +02:00
github-actions[bot] 2a468378dd Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.16
 - @navikt/ds-tailwind@0.1.9
 - @navikt/ds-tokens@0.8.7
 - @navikt/ds-react-internal@0.12.21
2022-04-04 14:37:36 +00:00
Ken 626b9069d2 [fix]
riktig aksel-repo link
2022-04-04 16:29:08 +02:00
KenandAndreas Nordahl 49c5e8f284 Tokens stories (#1484)
* tokens stories

* Update @navikt/core/tokens/stories/spacing.stories.tsx

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-04-04 16:03:55 +02:00
Andreas Nordahl 0d549cb87b [fix] overridable title for copy-to-clipboard (#1485) 2022-04-04 16:02:09 +02:00
Ken c0ef8a4d7d Permalenke til chromatic build 2022-04-04 15:06:25 +02:00
github-actions[bot] 3daa36efa7 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.8
 - @navikt/ds-react@0.17.20
 - @navikt/ds-react-internal@0.12.20
2022-04-04 13:05:20 +00:00
Ken 16bec93d1f [FIX] storybook-lenke 2022-04-04 14:56:10 +02:00
Ken ad033d9b1a Flyttet noen komponenter under (deprecated) (#1483) 2022-04-04 14:30:46 +02:00
Ken b55ead2301 button stories (#1481) 2022-04-04 14:29:20 +02:00
Ken 92532dd586 [FIX] React v18 upgrade (#1482) 2022-04-04 14:25:38 +02:00
Ken 5d3361615a Alert stories (#1478) 2022-04-01 22:41:49 +02:00
Ken 7779d93bf3 Storybook + Accordion-story rydding (#1477) 2022-04-01 14:13:13 +02:00
github-actions[bot] 31bd40c02c Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.15
 - @navikt/ds-icons@0.8.7
 - @navikt/ds-react@0.17.19
 - @navikt/ds-css-internal@0.7.3
 - @navikt/ds-react-internal@0.12.19
2022-04-01 11:48:01 +00:00
Ken 52eda50e3c [FIX] Script for å gjøre :root mer lesbar (#1476) 2022-04-01 13:37:51 +02:00
larseirikhansen e9e5084214 Patch updates (#1474)
* patch-update pretty-quick, fast-glob, fs-extra

* publish and share .git-blame-ignore-revs-file
2022-04-01 11:14:56 +02:00
github-actions[bot] dd14eb272e Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.14
 - @navikt/ds-react@0.17.18
 - @navikt/ds-tailwind@0.1.8
 - @navikt/ds-tokens@0.8.6
 - @navikt/ds-css-internal@0.7.2
 - @navikt/ds-react-internal@0.12.18
2022-04-01 07:38:03 +00:00
Andreas NordahlandKen 022d3a6a6f [fix] New/suggestfield (#1472)
* satt opp react

* stylet suggest-field

* stylet inverted versjon

* inverted label-farge

* bedre eksempel

* lint fix

* fikset border på inverted

* bruker spacing

* form -> div

* fikset stories

* fjernet clearbutton

* fikset story

* wip darkmode and combined search and suggest field

* no-button fixes

* paddings

* icon sizes

* default value clear bug

* focus

* placeholder

* search icon color

* primary and secondary button

* update tokens from figma

* purge suggest field

* internal header with data-theme dark

* fix some dark theme text color issues

* stylelint

* dark clear hover color

* no-button -> simple

Co-authored-by: Ken <ken.aleksander@gmail.com>
2022-04-01 09:29:45 +02:00
github-actions[bot] fcbd614a34 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.13
 - @navikt/ds-react@0.17.17
 - @navikt/ds-tailwind@0.1.7
 - @navikt/ds-tokens@0.8.5
 - @navikt/ds-react-internal@0.12.17
2022-03-31 10:50:28 +00:00
0a9aa6d3a1 [FIX] Tooltip komponent (#1462)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Martin Berglund <martin.berglund@nav.no>
Co-authored-by: larseirikhansen <71271458+larseirikhansen@users.noreply.github.com>
2022-03-31 11:38:09 +02:00
Ida 926437f06f Update README.md (#1475) 2022-03-31 11:34:34 +02:00
Ken 288456a460 type button på readmore (#1473) 2022-03-30 14:46:01 +02:00
github-actions[bot] 61f6b62c9e Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.16
 - @navikt/ds-react-internal@0.12.16
2022-03-28 15:02:20 +00:00
Andreas Nordahl dc9ffdebaf [fix] expandable icon title (#1471) 2022-03-28 16:53:05 +02:00
github-actions[bot] c80cb199a1 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.12
 - @navikt/ds-react@0.17.15
 - @navikt/ds-react-internal@0.12.15
2022-03-28 14:44:27 +00:00
Andreas Nordahl 5ec431456e [fix] Expantable table row (#1468)
* wip

* non-working api sketches

* working example of Table.ExpandableRow

* right|left toggle

* controlled/uncontrolled

* toggle fills cell

* collapse animation

* small

* oopsie

* docs

* inline toggle

* aria-label -> title (like helptext comp)

* oopsie

* fix visual glitch

* muted open border color

* expanded-row-cell padding issue

* expanded content alignment
2022-03-28 16:34:32 +02:00
dependabot[bot] 9e0af943a1 Bump minimist from 1.2.5 to 1.2.6 (#1467)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-28 10:58:50 +02:00
github-actions[bot] 9ed31d5401 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.11
2022-03-28 08:50:52 +00:00
Ken 5248625027 [FIX] Pointer på Scrollbutton i Tabs (#1470) 2022-03-28 10:42:37 +02:00
github-actions[bot] f62b9a6f7b Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.10
2022-03-28 07:28:10 +00:00
Andreas Nordahl c07dd59399 [fix] update button styling to match figma (#1469) 2022-03-28 09:20:24 +02:00
github-actions[bot] 88e2c2b2fe Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.14
 - @navikt/ds-react-internal@0.12.14
2022-03-24 14:37:53 +00:00
Ken 924c21365b [FIX] fikset tabs-scroll når scrollleft=0 2022-03-24 15:28:19 +01:00
github-actions[bot] 9e1b0ab1d1 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.9
 - @navikt/ds-react@0.17.13
 - @navikt/ds-react-internal@0.12.13
2022-03-24 12:38:43 +00:00
9c4d41e4c8 [FIX] Tabs komponent (#1451)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: larseirikhansen <71271458+larseirikhansen@users.noreply.github.com>
2022-03-24 13:29:52 +01:00
16e141a624 [NEW] New/stepper (#1429)
* satt opp stepper react

* satt opp stepper css

* oppdatert react-kode

* førsteutkast styling

* ♿ aria-label added to icons

* Stepper spacing and last-child focus

* add aria-labelledby

* add aria-labelledby to sb

* fix spelling mistake

* Remove 'finished' step api-option

* refactor Stepper-children jsx

* create Stepper example for sb

* WIP: Stepper mdx with practical props examples

* intro mdx disabled state

* ds intro overridable tags example

* add flex gap and fix last-child margin

* step-line is now pseudo-element

* cleanup css

* last child no margin-bottom

* remove disabled state

* update storybook

* aria-current to active step

* styling and color fixes

* color change line step

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/react/src/stepper/Step.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* [FIX] Bedre width for search (#1455)

* Lerna versionbump [ci skip]

 - @navikt/ds-css@0.16.3

* [fix] Helptext uu fix (#1407)

* storybook no div in p fix

* move title inside svg

* extra helptext in story

* remove duplicate title

* remove aria-props and refactor

* remove unused style

* simplify styling some

* default help text content to body-short

* cleanup

* tabindex 0 på popover

* flyttet story

* fjernet tabindex

* Update @navikt/core/react/src/help-text/HelpText.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Lerna versionbump [ci skip]

 - @navikt/ds-css@0.16.4
 - @navikt/ds-react@0.17.4
 - @navikt/ds-react-internal@0.12.4

* [FIX] Oppdatert ikon-template, SSR-safe uuid (#1458)

* oppdatert ikon-template

* oppdatert pakkversjoner

* fikset pakkeversjoner

* oppdatert ikon-template

* fikset config

* Lerna versionbump [ci skip]

 - @navikt/ds-icons@0.8.5
 - @navikt/ds-react@0.17.5
 - @navikt/ds-react-internal@0.12.5

* [fix] Read more component (#1456)

* scrips yo

* unused import

* stylez

* aria-expanded

* add link to storybook

* oopsie

* read more focus style

* read more collapse animation

* Lerna versionbump [ci skip]

 - @navikt/ds-css@0.16.5
 - @navikt/ds-react@0.17.6
 - @navikt/ds-react-internal@0.12.6

* remove ariaLabelledBy as its in by default

* Update @navikt/core/css/stepper.css

* anchor tag is default overridable

* rm space

* default from button to anchor

* add y-axis click affordance to steps

* click affordance, flex-align-start and stretching h-line with long label

* Update @navikt/core/css/stepper.css

Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-03-24 12:58:54 +01:00
github-actions[bot] 08be6c0e8b Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.12
 - @navikt/ds-react-internal@0.12.12
2022-03-23 18:50:44 +00:00
Andreas Nordahl becb01d429 [fix] Label react node (#1466) 2022-03-23 19:41:50 +01:00
github-actions[bot] 62ba36ae09 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.8
 - @navikt/ds-react@0.17.11
 - @navikt/ds-react-internal@0.12.11
2022-03-22 13:40:06 +00:00
Martin BerglundandAndreas Nordahl 2114c2bb53 [FIX] Replace hard coded values with tokens (#1463)
* Replace hard coded values with tokens

* Update yarn.lock

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-03-22 14:30:48 +01:00
Ken 213ef258aa [FIX] Fikset title på HelpText (#1464) 2022-03-22 14:27:22 +01:00
github-actions[bot] 85dd252e43 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.7
 - @navikt/ds-react@0.17.10
 - @navikt/ds-react-internal@0.12.10
2022-03-22 11:18:22 +00:00
Ken 9ebeff4ae0 [FIX] Endringsforslag Pagination (#1457) 2022-03-22 12:09:23 +01:00
github-actions[bot] b383a6baec Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.6
 - @navikt/ds-react@0.17.9
 - @navikt/ds-react-internal@0.12.9
2022-03-22 10:06:07 +00:00
b09ea568d4 [FIX] Alert styling og ikoner (#1447)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-03-22 10:57:09 +01:00
github-actions[bot] a3b28bb9ad Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.8
 - @navikt/ds-react-internal@0.12.8
2022-03-17 11:33:19 +00:00
Andreas Nordahl 1d04a06885 [fix] up-down for default sort state (#1461) 2022-03-17 12:23:39 +01:00
github-actions[bot] 88adfdc310 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.6
 - @navikt/ds-react@0.17.7
 - @navikt/ds-react-internal@0.12.7
2022-03-17 10:06:07 +00:00
Andreas Nordahl 502326dc33 [fix] update icons from Figma (#1460) 2022-03-17 10:55:43 +01:00
github-actions[bot] f6042d01aa Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.5
 - @navikt/ds-react@0.17.6
 - @navikt/ds-react-internal@0.12.6
2022-03-16 16:18:56 +00:00
Andreas Nordahl 3f4c35b0ef [fix] Read more component (#1456)
* scrips yo

* unused import

* stylez

* aria-expanded

* add link to storybook

* oopsie

* read more focus style

* read more collapse animation
2022-03-16 17:09:06 +01:00
github-actions[bot] b2a71fd227 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.5
 - @navikt/ds-react@0.17.5
 - @navikt/ds-react-internal@0.12.5
2022-03-16 15:53:15 +00:00
Ken d4aed1b59a [FIX] Oppdatert ikon-template, SSR-safe uuid (#1458)
* oppdatert ikon-template

* oppdatert pakkversjoner

* fikset pakkeversjoner

* oppdatert ikon-template

* fikset config
2022-03-16 16:44:24 +01:00
github-actions[bot] ddc0db1905 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.4
 - @navikt/ds-react@0.17.4
 - @navikt/ds-react-internal@0.12.4
2022-03-14 12:29:03 +00:00
211bd751cd [fix] Helptext uu fix (#1407)
* storybook no div in p fix

* move title inside svg

* extra helptext in story

* remove duplicate title

* remove aria-props and refactor

* remove unused style

* simplify styling some

* default help text content to body-short

* cleanup

* tabindex 0 på popover

* flyttet story

* fjernet tabindex

* Update @navikt/core/react/src/help-text/HelpText.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2022-03-14 13:18:43 +01:00
github-actions[bot] 3e334453e3 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.3
2022-03-14 12:00:11 +00:00
Ken 70819de284 [FIX] Bedre width for search (#1455) 2022-03-14 12:51:53 +01:00
github-actions[bot] 4baebb4340 Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.3
 - @navikt/ds-react-internal@0.12.3
2022-03-08 10:50:29 +00:00
Ken 7866333ae2 [FIX] Search: form -> div (#1454) 2022-03-08 11:40:25 +01:00
github-actions[bot] 2f13905d61 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.2
2022-03-07 15:23:32 +00:00
KenandAndreas Nordahl 0160383ff0 [FIX] Synket ConfirmationPanel med Figma (#1437)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-03-07 16:14:04 +01:00
github-actions[bot] dd1c128aac Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.2
 - @navikt/ds-react-internal@0.12.2
2022-03-07 11:25:20 +00:00
Ken f1a6d768fc [FIX] onSubmit kjører onSearch callback i Search (#1452) 2022-03-07 12:16:56 +01:00
github-actions[bot] c47967589a Lerna versionbump [ci skip]
- @navikt/ds-react@0.17.1
 - @navikt/ds-react-internal@0.12.1
2022-03-07 10:13:39 +00:00
Ken 51654edbfb [FIX] parentElement prop på Modal (#1450) 2022-03-07 11:05:02 +01:00
Ken 5c3683a89e Search clearbutton label comment 2022-03-04 17:19:59 +01:00
github-actions[bot] 9d9bf898e9 Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.1
2022-03-04 16:06:56 +00:00
Ken e8e530b764 [FIX] Search label layout hotfix 2022-03-04 16:57:09 +01:00
github-actions[bot] d2d08f58ce Lerna versionbump [ci skip]
- @navikt/ds-css@0.16.0
 - @navikt/ds-react@0.17.0
 - @navikt/ds-react-internal@0.12.0
2022-03-04 15:18:02 +00:00
KenandAndreas Nordahl f75abaff4b [FEATURE] Nytt søkefelt (#1382)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-03-04 16:08:26 +01:00
github-actions[bot] 7e8899df34 Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.20
 - @navikt/ds-react-internal@0.11.20
2022-03-02 10:10:05 +00:00
Ken 3926b24350 [FIX] Modal aria-label (#1449) 2022-03-02 11:01:45 +01:00
github-actions[bot] f1c2c718e5 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.12
 - @navikt/ds-react@0.16.19
 - @navikt/ds-react-internal@0.11.19
2022-03-01 10:13:40 +00:00
Ken ddcc6b8bd7 [FIX] Ny versjon av Radix ToggleGroup (#1448) 2022-03-01 11:03:45 +01:00
github-actions[bot] 6f5fee9628 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.11
 - @navikt/ds-react@0.16.18
 - @navikt/ds-react-internal@0.11.18
2022-03-01 08:33:43 +00:00
ad191179ab [fix] Table sort (#1445)
* story baseline

* pagination first take

* sort first take

* fix sort logic

* sort styling

* fix widths

* scope row

* steps

* pagination styles

* sortable birth year

* simplify comparator

* async table story

* HeaderCell allows sorting

* remove redundant story. fix some styling

* fix chromatic

* refactor column header

* overflow auto

* refactor pagination

* fix pagination steps test

* separate pagination comp

* xsmall button in table

* fikset type-error i ds-react-internal

* Update @navikt/core/css/button.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/pagination.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/pagination.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/table.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/react/src/pagination/Pagination.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/react/src/pagination/Pagination.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/react/src/table/ColumnHeader.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* move storybook static conf

* sort arrow fix

* new, adjustable step logic

* fix ellipsis key bug

* pagination styling

* some a11y things

* lint

* some sizing

* next prev focus style

* add pagination component and styles

* pagination css custom props

* 1px #fff linje mellom bg og shadow

* fix page logic on story

* user defined sort change logic

* fix table padding

* fix focus bug

* fix tilbake title bug

* digihot table story

* no active style, selected blue

* yarn.lock

* remove duplicate pagination stories

* fix storybook

* bump

* table cell alignment

* Update @navikt/core/react/src/table/Table.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/react/src/table/stories/table-async.stories.tsx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* Update @navikt/core/css/table.css

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2022-03-01 09:23:54 +01:00
github-actions[bot] 9c86becab0 Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.17
 - @navikt/ds-react-internal@0.11.17
2022-02-28 13:12:38 +00:00
Ken 200d420723 [FIX] readme 2022-02-28 14:05:20 +01:00
Ken 44ab348ecf force v0.1.4 for ToggleGroup 2022-02-28 14:03:31 +01:00
github-actions[bot] e631b894bf Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.16
 - @navikt/ds-react-internal@0.11.16
2022-02-25 11:33:07 +00:00
Andreas Nordahl fda0f5b3c5 [fix] use any for checkbox value (#1443) 2022-02-25 12:26:07 +01:00
github-actions[bot] 8e4e08d51c Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.15
 - @navikt/ds-react-internal@0.11.15
2022-02-25 09:52:42 +00:00
Andreas Nordahl 5095184abf [fix] omit indeterminate (#1444) 2022-02-25 10:45:42 +01:00
github-actions[bot] 8ef07f0807 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.10
 - @navikt/ds-tailwind@0.1.6
 - @navikt/ds-tokens@0.8.4
2022-02-24 13:25:45 +00:00
Martin Berglund fb670a9809 [fix] Adjust shadow values (#1442)
Softer and shorter
2022-02-24 14:17:00 +01:00
github-actions[bot] b4377a228a Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.9
 - @navikt/ds-tailwind@0.1.5
 - @navikt/ds-tokens@0.8.3
2022-02-23 13:34:12 +00:00
Martin Berglund 58273eccb4 [fix] Add border-radius scale (#1440) 2022-02-23 14:25:51 +01:00
github-actions[bot] 7c9b21495f Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.8
 - @navikt/ds-tailwind@0.1.4
 - @navikt/ds-tokens@0.8.2
2022-02-23 08:48:55 +00:00
Martin Berglund b53842633e [fix] Add shadow tokens scale (#1434)
* Add shadow tokens scale

* Remove global from shadow tokens

* Replace rgb with rgba

* Remove inner shadow
2022-02-23 09:41:52 +01:00
github-actions[bot] 8d07378f1d Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.14
 - @navikt/ds-react-internal@0.11.14
2022-02-23 08:12:35 +00:00
Andreas Nordahl f32c50fa88 [fix] Pagination fixes (#1436)
* remove disabled next and prev

* Tilbake -> Forrige
2022-02-23 09:04:04 +01:00
github-actions[bot] 5aa54c7aaf Lerna versionbump [ci skip]
- @navikt/ds-tailwind@0.1.3
2022-02-22 19:05:49 +00:00
Ken a771948d99 [FIX] Tailwind config token-casing (#1435) 2022-02-22 19:58:17 +01:00
github-actions[bot] 537cdd3def Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.13
 - @navikt/ds-react-internal@0.11.13
2022-02-22 15:05:37 +00:00
Andreas Nordahl e9cd4f2e2b [fix] Checkbox any value (#1432)
* bugfix: default checkbox group state to default value

* small refactor

* allow value of type any for checkbox and radio

* any -> string | number | boolean
2022-02-22 15:58:29 +01:00
github-actions[bot] 064bf66c0f Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.7
2022-02-22 14:00:59 +00:00
Ken a8b66dfec9 [FIX] charset utf-8 i css (#1433) 2022-02-22 14:53:27 +01:00
github-actions[bot] 8f99813590 Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.12
 - @navikt/ds-react-internal@0.11.12
2022-02-22 11:47:39 +00:00
Ken 21b078a9a4 [FIX] hotfix modal-props 2022-02-22 12:39:41 +01:00
github-actions[bot] e89d3b27b2 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.6
 - @navikt/ds-react@0.16.11
 - @navikt/ds-react-internal@0.11.11
2022-02-22 11:20:41 +00:00
Andreas NordahlandKen ddd2fd2e08 [fix] Pagination component (#1420)
* add pagination component and styles

* pagination css custom props

* 1px #fff linje mellom bg og shadow

* fix focus bug

* fix tilbake title bug

* endret på stories

* errors on invalid pagination arguments

* prev & next -> prev-next

* fix next-prev button focus padding

Co-authored-by: Ken <ken.aleksander@gmail.com>
2022-02-22 12:13:39 +01:00
github-actions[bot] a7c326aa43 Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.10
 - @navikt/ds-react-internal@0.11.10
2022-02-22 10:09:25 +00:00
Ken 0b89387bae [FIX] ToggleGroup role=toolbar for NVDA-støtte (#1431) 2022-02-22 11:01:44 +01:00
github-actions[bot] 8a58d75efb Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.5
 - @navikt/ds-react@0.16.9
 - @navikt/ds-react-internal@0.11.9
2022-02-21 09:35:40 +00:00
Ken bf18ffcb0c [FIX] ToggleGroup css-patch (#1430) 2022-02-21 10:28:43 +01:00
Ken ad3c88d542 [ci skip] revert siste endring 2022-02-18 16:01:41 +01:00
Ken eb90447bb7 [FIX] Forced CJS-versjon av ToggleGroup 2022-02-18 14:23:42 +01:00
github-actions[bot] cb429868c1 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.4
 - @navikt/ds-react@0.16.8
 - @navikt/ds-react-internal@0.11.8
2022-02-18 10:42:43 +00:00
KenandAndreas Nordahl e09f478a09 [FIX] Toggle-buttons (#1371)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>

Har fått 👍 på design og UU nå, så publiserer komponenten!
2022-02-18 11:34:32 +01:00
173 changed files with 9567 additions and 4323 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
509e1f2ded31a7d804422d05025454fac5a4c988
+12
View File
@@ -0,0 +1,12 @@
import { Meta, Canvas } from "@storybook/addon-docs";
<Meta title="ds-react(deprecated)/intro" />
# Utdaterte pakker
På sikt vil komponentene under bli flyttet ut av ds-react eller erstattes av andre komponenter
- PageHeader -> @navikt/ds-react-navno
- MicroCard -> @navikt/ds-react-navno
- StepIndicator -> Horisontal `<Stepper />`
+17
View File
@@ -0,0 +1,17 @@
.rowgap {
display: flex;
gap: 1rem;
padding: 1rem;
}
.colgap {
display: flex;
gap: 1rem;
flex-direction: column;
padding: 1rem;
}
.colgap[data-theme="dark"],
.rowgap[data-theme="dark"] {
background-color: #262626;
}
+2 -1
View File
@@ -10,7 +10,7 @@ module.exports = {
return config;
},
devServer: { stats: "errors-only" },
stories: () => getStories(),
stories: () => [...getStories(), "./*.stories.mdx"],
addons: [
"@storybook/addon-docs",
"@storybook/addon-a11y",
@@ -33,4 +33,5 @@ module.exports = {
core: {
builder: "webpack5",
},
staticDirs: ["./public"],
};
+10 -2
View File
@@ -1,13 +1,21 @@
import "@navikt/ds-css/index.css";
import "@navikt/ds-css-internal/index.css";
import "./layout.css";
import { initialize, mswDecorator } from "msw-storybook-addon";
initialize();
export const decorators = [mswDecorator];
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
/* actions: { argTypesRegex: "^on[A-Z].*" }, */
options: {
storySort: {
method: "",
order: [],
order: ["ds-icons", "ds-react", ["Default"]],
locales: "",
},
},
viewMode: "docs",
layout: "centered",
};
+338
View File
@@ -0,0 +1,338 @@
/* eslint-disable */
/* tslint:disable */
/**
* Mock Service Worker (0.36.5).
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
*/
const INTEGRITY_CHECKSUM = "02f4ad4a2797f85668baf196e553d929";
const bypassHeaderName = "x-msw-bypass";
const activeClientIds = new Set();
self.addEventListener("install", function () {
return self.skipWaiting();
});
self.addEventListener("activate", async function (event) {
return self.clients.claim();
});
self.addEventListener("message", async function (event) {
const clientId = event.source.id;
if (!clientId || !self.clients) {
return;
}
const client = await self.clients.get(clientId);
if (!client) {
return;
}
const allClients = await self.clients.matchAll();
switch (event.data) {
case "KEEPALIVE_REQUEST": {
sendToClient(client, {
type: "KEEPALIVE_RESPONSE",
});
break;
}
case "INTEGRITY_CHECK_REQUEST": {
sendToClient(client, {
type: "INTEGRITY_CHECK_RESPONSE",
payload: INTEGRITY_CHECKSUM,
});
break;
}
case "MOCK_ACTIVATE": {
activeClientIds.add(clientId);
sendToClient(client, {
type: "MOCKING_ENABLED",
payload: true,
});
break;
}
case "MOCK_DEACTIVATE": {
activeClientIds.delete(clientId);
break;
}
case "CLIENT_CLOSED": {
activeClientIds.delete(clientId);
const remainingClients = allClients.filter((client) => {
return client.id !== clientId;
});
// Unregister itself when there are no more clients
if (remainingClients.length === 0) {
self.registration.unregister();
}
break;
}
}
});
// Resolve the "main" client for the given event.
// Client that issues a request doesn't necessarily equal the client
// that registered the worker. It's with the latter the worker should
// communicate with during the response resolving phase.
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId);
if (client.frameType === "top-level") {
return client;
}
const allClients = await self.clients.matchAll();
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === "visible";
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id);
});
}
async function handleRequest(event, requestId) {
const client = await resolveMainClient(event);
const response = await getResponse(event, client, requestId);
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
(async function () {
const clonedResponse = response.clone();
sendToClient(client, {
type: "RESPONSE",
payload: {
requestId,
type: clonedResponse.type,
ok: clonedResponse.ok,
status: clonedResponse.status,
statusText: clonedResponse.statusText,
body:
clonedResponse.body === null ? null : await clonedResponse.text(),
headers: serializeHeaders(clonedResponse.headers),
redirected: clonedResponse.redirected,
},
});
})();
}
return response;
}
async function getResponse(event, client, requestId) {
const { request } = event;
const requestClone = request.clone();
const getOriginalResponse = () => fetch(requestClone);
// Bypass mocking when the request client is not active.
if (!client) {
return getOriginalResponse();
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return await getOriginalResponse();
}
// Bypass requests with the explicit bypass header
if (requestClone.headers.get(bypassHeaderName) === "true") {
const cleanRequestHeaders = serializeHeaders(requestClone.headers);
// Remove the bypass header to comply with the CORS preflight check.
delete cleanRequestHeaders[bypassHeaderName];
const originalRequest = new Request(requestClone, {
headers: new Headers(cleanRequestHeaders),
});
return fetch(originalRequest);
}
// Send the request to the client-side MSW.
const reqHeaders = serializeHeaders(request.headers);
const body = await request.text();
const clientMessage = await sendToClient(client, {
type: "REQUEST",
payload: {
id: requestId,
url: request.url,
method: request.method,
headers: reqHeaders,
cache: request.cache,
mode: request.mode,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body,
bodyUsed: request.bodyUsed,
keepalive: request.keepalive,
},
});
switch (clientMessage.type) {
case "MOCK_SUCCESS": {
return delayPromise(
() => respondWithMock(clientMessage),
clientMessage.payload.delay
);
}
case "MOCK_NOT_FOUND": {
return getOriginalResponse();
}
case "NETWORK_ERROR": {
const { name, message } = clientMessage.payload;
const networkError = new Error(message);
networkError.name = name;
// Rejecting a request Promise emulates a network error.
throw networkError;
}
case "INTERNAL_ERROR": {
const parsedBody = JSON.parse(clientMessage.payload.body);
console.error(
`\
[MSW] Uncaught exception in the request handler for "%s %s":
${parsedBody.location}
This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses\
`,
request.method,
request.url
);
return respondWithMock(clientMessage);
}
}
return getOriginalResponse();
}
self.addEventListener("fetch", function (event) {
const { request } = event;
const accept = request.headers.get("accept") || "";
// Bypass server-sent events.
if (accept.includes("text/event-stream")) {
return;
}
// Bypass navigation requests.
if (request.mode === "navigate") {
return;
}
// Opening the DevTools triggers the "only-if-cached" request
// that cannot be handled by the worker. Bypass such requests.
if (request.cache === "only-if-cached" && request.mode !== "same-origin") {
return;
}
// Bypass all requests when there are no active clients.
// Prevents the self-unregistered worked from handling requests
// after it's been deleted (still remains active until the next reload).
if (activeClientIds.size === 0) {
return;
}
const requestId = uuidv4();
return event.respondWith(
handleRequest(event, requestId).catch((error) => {
if (error.name === "NetworkError") {
console.warn(
'[MSW] Successfully emulated a network error for the "%s %s" request.',
request.method,
request.url
);
return;
}
// At this point, any exception indicates an issue with the original request/response.
console.error(
`\
[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`,
request.method,
request.url,
`${error.name}: ${error.message}`
);
})
);
});
function serializeHeaders(headers) {
const reqHeaders = {};
headers.forEach((value, name) => {
reqHeaders[name] = reqHeaders[name]
? [].concat(reqHeaders[name]).concat(value)
: value;
});
return reqHeaders;
}
function sendToClient(client, message) {
return new Promise((resolve, reject) => {
const channel = new MessageChannel();
channel.port1.onmessage = (event) => {
if (event.data && event.data.error) {
return reject(event.data.error);
}
resolve(event.data);
};
client.postMessage(JSON.stringify(message), [channel.port2]);
});
}
function delayPromise(cb, duration) {
return new Promise((resolve) => {
setTimeout(() => resolve(cb()), duration);
});
}
function respondWithMock(clientMessage) {
return new Response(clientMessage.payload.body, {
...clientMessage.payload,
headers: clientMessage.payload.headers,
});
}
function uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0;
const v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
-3
View File
@@ -1,3 +0,0 @@
# Designsystem v2
Storybook: https://navikt.github.io/Designsystemet/
+15 -37
View File
@@ -3,53 +3,32 @@
--navds-alert-color-error-border: var(
--navds-semantic-color-feedback-danger-border
);
--navds-alert-color-error-background: var(
--navds-semantic-color-feedback-danger-background
);
--navds-alert-color-error-background: var(--navds-global-color-red-50);
--navds-alert-color-warning-border: var(
--navds-semantic-color-feedback-warning-border
);
--navds-alert-color-warning-background: var(
--navds-semantic-color-feedback-warning-background
);
--navds-alert-color-warning-background: var(--navds-global-color-orange-50);
--navds-alert-color-info-border: var(
--navds-semantic-color-feedback-info-border
);
--navds-alert-color-info-background: var(
--navds-semantic-color-feedback-info-background
);
--navds-alert-color-info-background: var(--navds-global-color-lightblue-50);
--navds-alert-color-success-border: var(
--navds-semantic-color-feedback-success-border
);
--navds-alert-color-success-background: var(
--navds-semantic-color-feedback-success-background
);
--navds-alert-color-success-background: var(--navds-global-color-green-50);
--navds-alert-color-error-icon: var(
--navds-semantic-color-feedback-danger-icon
);
--navds-alert-color-error-icon-background: var(
--navds-semantic-color-component-background-light
);
--navds-alert-color-warning-icon: var(
--navds-semantic-color-feedback-warning-icon
);
--navds-alert-color-warning-icon-background: var(
--navds-semantic-color-component-background-inverted
);
--navds-alert-color-warning-icon: var(--navds-global-color-orange-600);
--navds-alert-color-info-icon: var(--navds-semantic-color-feedback-info-icon);
--navds-alert-color-info-icon-background: var(
--navds-semantic-color-component-background-light
);
--navds-alert-color-success-icon: var(
--navds-semantic-color-feedback-success-icon
);
--navds-alert-color-success-icon-background: var(
--navds-semantic-color-component-background-light
);
--navds-alert-color-icon-background: var(--navds-global-color-white);
}
.navds-alert {
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 1px solid;
border-color: var(--navds-alert-color-border);
padding: calc(var(--navds-spacing-4) + 1px) calc(var(--navds-spacing-4) + 1px);
@@ -91,7 +70,7 @@
color: var(--navds-alert-color-error-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-error-icon-background) 50%,
var(--navds-alert-color-icon-background) 50%,
0,
transparent
);
@@ -104,12 +83,11 @@
.navds-alert--warning > .navds-alert__icon {
color: var(--navds-alert-color-warning-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-warning-icon-background) 50%,
0,
transparent
);
background: linear-gradient(
var(--navds-alert-color-icon-background),
var(--navds-alert-color-icon-background)
)
center / 16% 60% no-repeat;
}
.navds-alert--info {
@@ -121,7 +99,7 @@
color: var(--navds-alert-color-info-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-info-icon-background) 50%,
var(--navds-alert-color-icon-background) 50%,
0,
transparent
);
@@ -136,7 +114,7 @@
color: var(--navds-alert-color-success-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-success-icon-background) 50%,
var(--navds-alert-color-icon-background) 50%,
0,
transparent
);
+13 -1
View File
@@ -20,10 +20,22 @@ html {
box-sizing: inherit;
}
:root,
[data-theme="light"] {
--navds-shadow-focus: 0 0 0 3px var(--navds-semantic-color-focus);
color: var(--navds-semantic-color-text);
}
[data-theme="dark"] {
--navds-shadow-focus: var(--navds-shadow-focus-inverted);
color: var(--navds-semantic-color-text-inverted);
}
body {
font-family: var(--navds-font-family);
line-height: 1.333;
color: var(--navds-semantic-color-text);
font-size: 1.125rem;
}
+48 -10
View File
@@ -1,4 +1,5 @@
:root {
:root,
[data-theme="light"] {
/* Primary */
--navds-button-color-primary-text: var(--navds-semantic-color-text-inverted);
--navds-button-color-primary-border-focus: var(
@@ -19,7 +20,7 @@
--navds-semantic-color-interaction-primary
);
--navds-button-color-secondary-text-hover: var(
--navds-semantic-color-text-inverted
--navds-semantic-color-interaction-primary
);
--navds-button-color-secondary-text-active: var(
--navds-semantic-color-text-inverted
@@ -34,7 +35,7 @@
--navds-semantic-color-component-background-light
);
--navds-button-color-secondary-background-hover: var(
--navds-semantic-color-interaction-primary-hover
--navds-semantic-color-interaction-primary-hover-subtle
);
--navds-button-color-secondary-background-active: var(
--navds-semantic-color-interaction-primary-selected
@@ -47,8 +48,8 @@
--navds-button-color-tertiary-text-active: var(
--navds-semantic-color-text-inverted
);
--navds-button-color-tertiary-border-hover: var(
--navds-semantic-color-interaction-primary
--navds-button-color-tertiary-background-hover: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
--navds-button-color-tertiary-border-focus: var(
--navds-semantic-color-interaction-primary
@@ -80,6 +81,39 @@
--navds-loader-color-on-button-foreground: currentColor;
}
[data-theme="dark"] {
/* Primary */
--navds-button-color-primary-text: var(--navds-semantic-color-text);
--navds-button-color-primary-border-focus: var(--navds-semantic-color-text);
--navds-button-color-primary-background: var(--navds-global-color-blue-200);
--navds-button-color-primary-background-hover: var(
--navds-global-color-blue-300
);
--navds-button-color-primary-background-active: var(
--navds-global-color-blue-400
);
/* Secondary */
--navds-button-color-secondary-text: var(--navds-global-color-blue-200);
--navds-button-color-secondary-text-hover: var(--navds-global-color-blue-200);
--navds-button-color-secondary-text-active: var(
--navds-global-color-blue-200
);
--navds-button-color-secondary-border: var(--navds-global-color-blue-200);
--navds-button-color-secondary-border-focus-active-hover: var(
--navds-semantic-color-text
);
--navds-button-color-secondary-background: var(
--navds-semantic-color-component-background-inverted
);
--navds-button-color-secondary-background-hover: var(
--navds-global-color-blue-900
);
--navds-button-color-secondary-background-active: var(
--navds-global-color-blue-800
);
}
.navds-button {
display: inline-flex;
cursor: pointer;
@@ -88,7 +122,7 @@
text-decoration: none;
border: none;
background: none;
border-radius: 2px;
border-radius: var(--navds-border-radius-small);
min-width: 48px;
padding: var(--navds-spacing-3);
}
@@ -99,6 +133,11 @@
min-width: 32px;
}
.navds-button--xsmall {
padding: 0.125rem 0.375rem;
min-width: 24px;
}
.navds-button:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
@@ -115,7 +154,8 @@
font-size: 1.5rem;
}
.navds-button--small svg {
.navds-button--small svg,
.navds-button--xsmall svg {
font-size: 1.25rem;
}
@@ -159,7 +199,6 @@
.navds-button--secondary:hover {
color: var(--navds-button-color-secondary-text-hover);
background-color: var(--navds-button-color-secondary-background-hover);
box-shadow: none;
}
.navds-button--secondary:focus {
@@ -173,7 +212,6 @@
box-shadow: none;
}
.navds-button--secondary:focus:hover,
.navds-button--secondary:focus:active {
box-shadow: inset 0 0 0 1px
var(--navds-button-color-secondary-border-focus-active-hover),
@@ -196,7 +234,7 @@
}
.navds-button--tertiary:hover {
box-shadow: inset 0 0 0 2px var(--navds-button-color-tertiary-border-hover);
background-color: var(--navds-button-color-tertiary-background-hover);
}
.navds-button--tertiary:focus {
+1 -1
View File
@@ -27,7 +27,7 @@
*/
.navds-card__micro {
border-radius: 1rem;
border-radius: var(--navds-border-radius-full);
color: var(--navds-card-micro-color-text);
display: inline-flex;
padding: var(--navds-spacing-1) var(--navds-spacing-2);
+5 -1
View File
@@ -1,7 +1,11 @@
:root {
--navds-content-container-max-width: 79.5rem;
}
.navds-content-container {
margin-left: auto;
margin-right: auto;
max-width: 79.5rem;
max-width: var(--navds-content-container-max-width);
padding: var(--navds-spacing-4);
}
+12 -5
View File
@@ -1,15 +1,21 @@
:root {
--navds-confirmation-panel-color-background: var(
--navds-semantic-color-feedback-warning-background
--navds-global-color-orange-50
);
--navds-confirmation-panel-color-background-checked: var(
--navds-semantic-color-feedback-success-background
--navds-global-color-green-50
);
--navds-confirmation-panel-color-border: var(
--navds-semantic-color-feedback-warning-border
);
--navds-confirmation-panel-color-border-checked: var(
--navds-semantic-color-feedback-success-background
--navds-semantic-color-feedback-success-border
);
--navds-confirmation-panel-color-border-error: var(
--navds-semantic-color-feedback-danger-background
);
--navds-confirmation-panel-color-background-error: var(
--navds-semantic-color-feedback-danger-background
--navds-global-color-red-50
);
--navds-confirmation-panel-color-checkbox-background-checked-hover: var(
--navds-global-color-green-700
@@ -33,7 +39,8 @@
flex-direction: column;
gap: var(--navds-spacing-4);
padding: var(--navds-spacing-4);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 1px solid var(--navds-confirmation-panel-color-border);
background-color: var(--navds-confirmation-panel-color-background);
transition: background-color linear 100ms;
}
+1 -1
View File
@@ -11,4 +11,4 @@
@import "switch.css";
@import "text-field.css";
@import "textarea.css";
@import "search-field.css";
@import "search.css";
+3 -3
View File
@@ -57,12 +57,12 @@
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow);
width: 1.5rem;
height: 1.5rem;
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
flex-shrink: 0;
}
.navds-radio__label::before {
border-radius: 50%;
border-radius: var(--navds-border-radius-full);
}
.navds-checkbox__content,
@@ -121,7 +121,7 @@
background-color: var(--navds-radio-checkbox-color-background);
width: 0.75rem;
height: 0.25rem;
border-radius: 1px;
border-radius: 1px; /* Custom value OK */
flex-shrink: 0;
}
-59
View File
@@ -1,59 +0,0 @@
:root {
--navds-search-field-color-shadow-error: var(
--navds-semantic-color-interaction-danger
);
--navds-search-field-color-border-error: var(
--navds-semantic-color-interaction-danger
);
--navds-search-field-color-clearbutton-border: var(
--navds-semantic-color-border
);
}
.navds-search-field__input-wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.navds-form-field--small .navds-search-field__input {
padding: 0.15rem;
min-height: 32px;
}
.navds-search-field__input-wrapper > *:not(:first-child):not(:last-child) {
border-radius: 0;
}
.navds-search-field__input-wrapper > :first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.navds-search-field__input-wrapper > :last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.navds-search-field__input-wrapper > :last-child:first-child {
border-radius: 4px;
}
.navds-search-field__input-wrapper :focus {
z-index: var(--navds-z-index-focus);
}
.navds-search-field__button,
.navds-search-field__clear-button {
flex-shrink: 0;
}
.navds-search-field--error
.navds-search-field__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-search-field-color-shadow-error) inset;
border-color: var(--navds-search-field-color-border-error);
}
.navds-search-field--disabled {
opacity: 0.3;
}
+158
View File
@@ -0,0 +1,158 @@
:root,
[data-theme="light"] {
--navds-search-color-text: var(--navds-semantic-color-text);
--navds-search-color-border: var(--navds-semantic-color-border);
--navds-search-color-border-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-search-color-clear-hover: var(--navds-global-color-blue-500);
}
[data-theme="dark"] {
--navds-search-color-text: var(--navds-semantic-color-text-inverted);
--navds-search-color-border: var(--navds-semantic-color-border-inverted);
--navds-search-color-border-hover: var(--navds-global-color-blue-200);
--navds-search-color-clear-hover: var(--navds-global-color-blue-200);
}
.navds-search {
display: flex;
flex-direction: column;
width: 100%;
}
.navds-search__wrapper-inner {
position: relative;
width: 100%;
}
.navds-search__wrapper {
display: inline-flex;
align-items: center;
}
.navds-search__input {
padding-right: var(--navds-spacing-10);
}
.navds-form-field--small .navds-search__input {
padding-right: var(--navds-spacing-8);
}
.navds-search__input--simple {
padding-left: var(--navds-spacing-11);
}
.navds-form-field--small .navds-search__input--simple {
padding-left: var(--navds-spacing-7);
}
.navds-search__input:not(.navds-search__input--simple) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.navds-search__search-icon {
position: absolute;
left: var(--navds-spacing-3);
top: 50%;
transform: translateY(-50%);
pointer-events: none;
font-size: 1.5rem;
}
.navds-form-field--small .navds-search__search-icon {
left: var(--navds-spacing-2);
font-size: 1rem;
}
.navds-search__button-clear {
position: absolute;
right: 0.75rem;
border-radius: var(--navds-border-radius-medium);
color: var(--navds-search-color-text);
height: 32px;
width: 32px;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
background: none;
border: none;
font-size: 1rem;
padding: 0;
}
.navds-form-field--small .navds-search__button-clear {
right: 0.5rem;
height: 24px;
width: 24px;
}
.navds-search__button-clear:hover {
color: var(--navds-search-color-clear-hover);
}
.navds-search__button-clear:focus {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-search__button-search {
flex-shrink: 0;
min-width: 64px;
min-height: 32px;
border-radius: 0;
border-top-right-radius: var(--navds-border-radius-medium);
border-bottom-right-radius: var(--navds-border-radius-medium);
}
.navds-form-field--small .navds-search__button-search svg {
font-size: 1rem;
}
.navds-form-field--small .navds-search__button-search {
min-width: 40px;
}
.navds-search__button-search.navds-button--secondary {
box-shadow: -1px 0 0 0 var(--navds-search-color-border) inset,
0 1px 0 0 var(--navds-search-color-border) inset,
0 -1px 0 0 var(--navds-search-color-border) inset;
}
.navds-search__button-search.navds-button--secondary:hover {
box-shadow: -1px 0 0 0 var(--navds-search-color-border-hover) inset,
0 1px 0 0 var(--navds-search-color-border-hover) inset,
0 -1px 0 0 var(--navds-search-color-border-hover) inset,
-1px 0 0 0 var(--navds-search-color-border-hover);
z-index: 1;
}
.navds-search__wrapper-inner:focus-within
+ .navds-search__button-search.navds-button--secondary:hover {
z-index: auto;
}
.navds-search__button-search.navds-button--secondary:focus {
box-shadow: 0 0 0 1px var(--navds-search-color-border) inset,
var(--navds-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus:hover {
box-shadow: 0 0 0 1px var(--navds-search-color-border-hover) inset,
var(--navds-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus:active {
box-shadow: 0 0 0 1px white inset, var(--navds-shadow-focus);
}
/* Focus layering */
.navds-search__input:focus,
.navds-search__button-clear,
.navds-search__button-search:focus {
z-index: 1;
}
+1 -1
View File
@@ -22,7 +22,7 @@
.navds-select__input {
appearance: none;
background-color: var(--navds-select-color-background);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 1px solid var(--navds-select-color-border);
width: 100%;
box-sizing: border-box;
+2 -2
View File
@@ -112,7 +112,7 @@
position: absolute;
top: var(--navds-spacing-3);
left: 0;
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -155,7 +155,7 @@
.navds-switch__thumb {
background-color: var(--navds-switch-color-thumb);
color: var(--navds-switch-color-thumb-icon);
border-radius: 2.5px;
border-radius: var(--navds-border-radius-small);
width: 20px;
height: 20px;
position: absolute;
+24 -4
View File
@@ -1,4 +1,6 @@
:root {
:root,
[data-theme="light"] {
--navds-text-field-color-text: var(--navds-semantic-color-text);
--navds-text-field-color-background: var(
--navds-semantic-color-component-background-light
);
@@ -17,19 +19,37 @@
--navds-semantic-color-component-background-alternate
);
--navds-text-field-color-text-disabled: var(--navds-semantic-color-text);
--navds-text-field-color-placeholder-text: var(
--navds-semantic-color-text-muted
);
}
[data-theme="dark"] {
--navds-text-field-color-text: var(--navds-semantic-color-text-inverted);
--navds-text-field-color-background: var(
--navds-semantic-color-component-background-dark
);
--navds-text-field-color-border: var(--navds-semantic-color-border-inverted);
--navds-text-field-color-border-hover: var(--navds-global-color-blue-200);
--navds-text-field-color-placeholder-text: var(--navds-global-color-gray-500);
}
.navds-text-field__input {
appearance: none;
padding: 0.5rem;
padding: var(--navds-spacing-2);
background-color: var(--navds-text-field-color-background);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 1px solid var(--navds-text-field-color-border);
min-height: 48px;
width: 100%;
color: var(--navds-text-field-color-text);
}
.navds-form-field--small > .navds-text-field__input {
.navds-text-field__input::placeholder {
color: var(--navds-text-field-color-placeholder-text);
}
.navds-form-field--small .navds-text-field__input {
padding: 0 0.25rem;
min-height: 32px;
}
+1 -1
View File
@@ -32,7 +32,7 @@
appearance: none;
padding: var(--navds-spacing-2);
background-color: var(--navds-textarea-color-background);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 1px solid var(--navds-textarea-color-border);
resize: none;
width: 100%;
+2 -2
View File
@@ -18,7 +18,7 @@
.navds-guide-panel__content {
background-color: var(--navds-guide-panel-color-background);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
border: 2px solid var(--navds-guide-panel-color-border);
min-height: 7.25rem;
padding: 1.5rem;
@@ -58,7 +58,7 @@
/* Guide illustration frame */
.navds-guide__illustration {
background: var(--navds-guide-panel-color-illustration-background);
border-radius: 50%;
border-radius: var(--navds-border-radius-full);
overflow: hidden;
}
+25 -30
View File
@@ -1,22 +1,21 @@
:root {
--navds-help-text-color-button-background: transparent;
--navds-help-text-color-icon: var(--navds-semantic-color-interaction-primary);
--navds-help-text-color-icon-hover: var(
--navds-help-text-color: var(--navds-semantic-color-interaction-primary);
--navds-help-text-color-hover: var(
--navds-semantic-color-component-background-light
);
--navds-help-text-color-icon-background-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-help-text-color-icon-shadow-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-help-text-color-icon-focus: var(
--navds-help-text-color-focus: var(
--navds-semantic-color-component-background-light
);
--navds-help-text-color-icon-background-focus: var(
--navds-help-text-color-background-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-help-text-color-icon-shadow-focus: var(--navds-semantic-color-focus);
--navds-help-text-color-background-focus: var(
--navds-semantic-color-interaction-primary
);
--navds-help-text-color-shadow-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-help-text-color-shadow-focus: var(--navds-semantic-color-focus);
--navds-help-text-color-popover-background: var(
--navds-semantic-color-feedback-info-background
);
@@ -27,34 +26,30 @@
padding: 0;
border: 0;
cursor: pointer;
background-color: var(--navds-help-text-color-button-background);
border-radius: 50%;
background-color: transparent;
border-radius: var(--navds-border-radius-full);
display: flex;
justify-content: center;
align-items: center;
color: var(--navds-help-text-color);
font-size: 1.5rem;
}
.navds-help-text__button:hover {
color: var(--navds-help-text-color-hover);
background: var(--navds-help-text-color-background-hover);
box-shadow: 0 0 0 2px var(--navds-help-text-color-shadow-hover);
}
.navds-help-text__button:focus {
outline: none;
color: var(--navds-help-text-color-focus);
background: var(--navds-help-text-color-background-focus);
box-shadow: 0 0 0 3px var(--navds-help-text-color-shadow-focus);
}
.navds-help-text__icon {
border-radius: 50%;
font-size: 1.5rem;
color: var(--navds-help-text-color-icon);
}
.navds-help-text__button:hover > .navds-help-text__icon {
color: var(--navds-help-text-color-icon-hover);
background: var(--navds-help-text-color-icon-background-hover);
box-shadow: 0 0 0 2px var(--navds-help-text-color-icon-shadow-hover);
}
.navds-help-text__button:focus > .navds-help-text__icon {
outline: none;
color: var(--navds-help-text-color-icon-focus);
background: var(--navds-help-text-color-icon-background-focus);
box-shadow: 0 0 0 3px var(--navds-help-text-color-icon-shadow-focus);
border-radius: var(--navds-border-radius-full);
}
.navds-help-text__popover > .navds-popover__arrow::before {
+7
View File
@@ -1,3 +1,4 @@
@charset "UTF-8";
@import "baseline/baseline.css";
@import "typography.css";
@import "grid.css";
@@ -13,13 +14,19 @@
@import "loader.css";
@import "menu.css";
@import "modal.css";
@import "pagination.css";
@import "popover.css";
@import "tag.css";
@import "tooltip.css";
@import "toggle-group.css";
@import "panel.css";
@import "link-panel.css";
@import "read-more.css";
@import "speech-bubble.css";
@import "step-indicator.css";
@import "stepper.css";
@import "table.css";
@import "tabs.css";
/* Navno spesific packages */
@import "page-header.css";
+1
View File
@@ -49,6 +49,7 @@
.navds-link svg {
color: var(--navds-link-color-icon);
flex-shrink: 0;
}
.navds-link:focus svg {
+1 -1
View File
@@ -11,7 +11,7 @@
.navds-modal {
background-color: var(--navds-modal-color-background);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
display: block;
position: relative;
overflow: auto;
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.15.3",
"version": "0.16.19",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
@@ -17,14 +17,15 @@
},
"main": "./dist/index.css",
"scripts": {
"build": "postcss --use postcss-import -o dist/index.css index.css",
"build": "postcss --use postcss-import postcss-combine-duplicated-selectors -o dist/index.css index.css",
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^0.8.1",
"@navikt/ds-tokens": "^0.8.7",
"normalize.css": "^8.0.1",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
"postcss-combine-duplicated-selectors": "10.0.3",
"postcss-import": "^14.0.2"
}
}
+122
View File
@@ -0,0 +1,122 @@
:root {
--navds-pagination-color-background-hover: var(
--navds-semantic-color-canvas-background
);
--navds-pagination-color-background-active: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-pagination-color-text-active: var(
--navds-semantic-color-text-inverted
);
--navds-pagination-color-background-selected: var(
--navds-semantic-color-interaction-primary
);
--navds-pagination-color-text-selected: var(
--navds-semantic-color-text-inverted
);
}
.navds-pagination {
display: flex;
}
.navds-pagination__list {
margin: 0;
padding: 0;
list-style: none;
display: flex;
gap: var(--navds-spacing-3);
}
.navds-pagination__ellipsis {
display: flex;
align-items: center;
justify-content: center;
width: var(--navds-spacing-8);
cursor: default;
}
.navds-pagination--small .navds-pagination__ellipsis {
width: var(--navds-spacing-6);
}
.navds-pagination__item {
display: flex;
cursor: pointer;
margin: 0;
text-decoration: none;
border: none;
background: none;
border-radius: var(--navds-border-radius-small);
padding: var(--navds-spacing-1) var(--navds-spacing-3);
}
.navds-pagination--small .navds-pagination__item {
padding: 2px var(--navds-spacing-2);
}
.navds-pagination__item:hover {
background-color: var(--navds-pagination-color-background-hover);
}
.navds-pagination__item:active {
background-color: var(--navds-pagination-color-background-active);
color: var(--navds-pagination-color-text-active);
}
.navds-pagination__item:focus {
box-shadow: inset 0 0 0 2px var(--navds-semantic-color-focus),
inset 0 0 0 3px white;
outline: none;
}
.navds-pagination__item[aria-current="true"] {
background-color: var(--navds-pagination-color-background-selected);
color: var(--navds-pagination-color-text-selected);
font-weight: var(--navds-font-weight-bold);
}
.navds-pagination__prev-next {
display: flex;
cursor: pointer;
margin: 0;
padding: 0;
border: none;
background: none;
text-decoration: underline;
color: var(--navds-semantic-color-link);
align-items: center;
gap: var(--navds-spacing-1);
border-radius: var(--navds-border-radius-small);
}
.navds-pagination__prev-next:focus {
outline: none;
box-shadow: inset 0 0 0 2px var(--navds-semantic-color-focus);
}
.navds-pagination__prev-next:disabled {
cursor: not-allowed;
opacity: 0.3;
}
.navds-pagination__prev-next-icon {
margin: 7px;
}
.navds-pagination--small .navds-pagination__prev-next-icon {
margin: var(--navds-spacing-1);
font-size: 1rem;
}
.navds-pagination__next-text {
padding-left: 0.75rem;
}
.navds-pagination__prev-text {
padding-right: 0.75rem;
}
.navds-pagination--invisible {
visibility: hidden;
}
+1 -1
View File
@@ -8,7 +8,7 @@
.navds-panel {
background-color: var(--navds-panel-color-background);
padding: var(--navds-spacing-4);
border-radius: 4px;
border-radius: var(--navds-border-radius-small);
border: 1px solid transparent;
}
+1 -1
View File
@@ -11,7 +11,7 @@
box-shadow: var(--navds-shadow-popover);
border: 1px solid;
border-color: var(--navds-popover-color-border);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
}
.navds-popover__content {
+52
View File
@@ -0,0 +1,52 @@
.navds-read-more {
cursor: pointer;
margin: 0;
padding: 0;
text-decoration: underline;
border: none;
background: none;
display: flex;
align-items: center;
gap: var(--navds-spacing-2);
color: var(--navds-semantic-color-link);
}
.navds-read-more:hover {
text-decoration: none;
}
.navds-read-more:focus {
outline: none;
color: var(--navds-link-color-text-focus);
text-decoration: none;
background-color: var(--navds-link-color-background-focus);
box-shadow: 0 0 0 2px var(--navds-semantic-color-focus);
}
.navds-read-more__expand-icon {
font-size: 1.25rem;
}
.navds-read-more--open > .navds-read-more__expand-icon {
transform: rotate(180deg);
}
.navds-read-more + .ReactCollapse--collapse {
transition: height 250ms cubic-bezier(0.4, 0, 0.2, 1);
padding-top: var(--navds-spacing-2);
}
.navds-read-more__content {
display: flex;
align-items: stretch;
gap: var(--navds-spacing-2);
}
.navds-read-more__content::before {
content: "";
display: block;
width: 2px;
background-color: var(--navds-semantic-color-border-muted);
margin: 0 9px;
flex-shrink: 0;
}
+3 -3
View File
@@ -38,7 +38,7 @@
align-items: center;
background: var(--navds-speechbubble-color-illustration-background);
color: var(--navds-speechbubble-color-illustration);
border-radius: 50%;
border-radius: var(--navds-border-radius-full);
display: flex;
flex-shrink: 0;
justify-content: center;
@@ -59,7 +59,7 @@
width: fit-content;
max-width: 37.5rem;
background-color: var(--navds-speechbubble-color-background);
border-radius: 12px;
border-radius: var(--navds-border-radius-xlarge);
border-bottom-left-radius: 2px;
display: flex;
flex-direction: column;
@@ -72,7 +72,7 @@
}
.navds-speechbubble--right .navds-speechbubble__bubble {
border-radius: 12px;
border-radius: var(--navds-border-radius-xlarge);
border-bottom-right-radius: 2px;
}
+2 -2
View File
@@ -72,7 +72,7 @@
width: 2rem;
height: 2rem;
margin: 0.5rem;
border-radius: 50%;
border-radius: var(--navds-border-radius-full);
align-items: center;
justify-content: center;
box-shadow: 0 0 0 1px var(--navds-step-indicator-color-step-number-shadow);
@@ -107,7 +107,7 @@
left: calc(-50% + 2rem);
display: block;
border-top: 2px solid var(--navds-step-indicator-color-step-line);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
pointer-events: none;
}
+99
View File
@@ -0,0 +1,99 @@
.navds-stepper {
display: flex;
flex-direction: column;
padding: 0;
margin: 0;
list-style: none;
}
/* Step */
.navds-stepper__step {
position: relative;
cursor: pointer;
padding: calc(2.25rem / 2) 0;
display: flex;
background: none;
border: none;
appearance: none;
width: 100%;
color: var(--navds-semantic-color-text);
text-decoration: none;
flex-shrink: 0;
}
.navds-stepper__step-number {
flex-shrink: 0;
display: flex;
width: 28px;
height: 28px;
margin: 0;
margin-right: var(--navds-spacing-3);
border-radius: var(--navds-border-radius-full);
align-items: center;
justify-content: center;
color: var(--navds-semantic-color-interaction-primary);
box-shadow: inset 0 0 0 2px var(--navds-semantic-color-interaction-primary);
background-color: var(--navds-semantic-color-component-background-light);
}
/* Step-states: focus, active, hover */
.navds-stepper__step-wrapper:hover
> .navds-stepper__step
> .navds-stepper__step-number {
background-color: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
}
.navds-stepper__step--active > .navds-stepper__step-number,
.navds-stepper__step-wrapper:hover
> .navds-stepper__step--active
> .navds-stepper__step-number {
color: var(--navds-semantic-color-text-inverted);
background-color: var(--navds-semantic-color-interaction-primary-selected);
box-shadow: inset 0 0 0 2px
var(--navds-semantic-color-interaction-primary-selected);
}
.navds-stepper__step:focus {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-stepper__step--active {
cursor: default;
}
/* Step label */
.navds-stepper__step-label {
margin-top: 2px;
color: var(--navds-semantic-color-interaction-primary);
text-align: start;
}
.navds-stepper__step:hover > .navds-stepper__step-label {
text-decoration: underline;
}
.navds-stepper__step--active > .navds-stepper__step-label {
color: black;
}
.navds-stepper__step--active:hover > .navds-stepper__step-label {
text-decoration: none;
}
/* Step Horizontal Lines */
.navds-stepper__step-wrapper:not(:last-child) > .navds-stepper__step::after {
content: "";
position: absolute;
top: calc(28px + 8px + (2.25rem / 2));
left: 13px;
height: calc(100% - 2.75rem);
display: block;
border-left: 2px solid var(--navds-semantic-color-border-muted);
border-radius: var(--navds-border-radius-medium);
pointer-events: none;
z-index: 1;
}
+141 -3
View File
@@ -16,8 +16,8 @@
}
.navds-table {
border-collapse: collapse;
width: 100%;
border-collapse: collapse;
display: table;
}
@@ -54,11 +54,21 @@
.navds-table__header-cell,
.navds-table__data-cell {
display: table-cell;
padding: var(--navds-spacing-4);
padding: var(--navds-spacing-4) var(--navds-spacing-3);
border-bottom: 1px solid var(--navds-table-cell-color-border);
text-align: left;
}
.navds-table__header-cell--align-right,
.navds-table__data-cell--align-right {
text-align: right;
}
.navds-table__header-cell--align-center,
.navds-table__data-cell--align-center {
text-align: center;
}
.navds-table__body .navds-table__row:hover .navds-table__header-cell,
.navds-table__body .navds-table__row:hover .navds-table__data-cell {
border-color: var(--navds-table-cell-color-border-hover);
@@ -66,7 +76,7 @@
.navds-table--small .navds-table__header-cell,
.navds-table--small .navds-table__data-cell {
padding: var(--navds-spacing-2);
padding: var(--navds-spacing-2) var(--navds-spacing-3);
}
.navds-table .navds-checkbox .navds-checkbox__input {
@@ -80,3 +90,131 @@
.navds-table .navds-checkbox .navds-checkbox__label {
padding: 0;
}
.navds-table__header-cell[aria-sort] {
padding: 0;
}
.navds-table__sort-button {
appearance: none;
background: none;
color: var(--navds-semantic-color-link);
border: none;
cursor: pointer;
margin: 0;
padding: var(--navds-spacing-4) var(--navds-spacing-3);
width: 100%;
display: flex;
gap: 0.5rem;
align-items: center;
line-height: inherit;
font-weight: inherit;
}
.navds-table--small .navds-table__sort-button {
padding: var(--navds-spacing-2) var(--navds-spacing-3);
}
.navds-table__sort-button:hover {
background-color: var(--navds-semantic-color-canvas-background);
}
.navds-table__sort-button:focus {
outline: none;
box-shadow: inset 0 0 0 2px var(--navds-semantic-color-focus);
}
.navds-table__header-cell[aria-sort="ascending"] .navds-table__sort-button,
.navds-table__header-cell[aria-sort="descending"] .navds-table__sort-button {
background-color: var(--navds-global-color-blue-50);
}
.navds-table__header-cell--align-right .navds-table__sort-button {
justify-content: end;
}
.navds-table__header-cell--align-center .navds-table__sort-button {
justify-content: center;
}
.navds-table__sort-button svg {
font-size: 1rem;
flex-shrink: 0;
}
.navds-table__expandable-row--open .navds-table__header-cell,
.navds-table__expandable-row--open .navds-table__data-cell {
border-color: var(--navds-semantic-color-border-muted);
}
.navds-table__expandable-row--open .navds-table__toggle-expand-cell--open {
border-color: transparent;
}
.navds-table__toggle-expand-cell {
padding: 0;
width: 56px;
}
.navds-table--small .navds-table__toggle-expand-cell {
padding: 0;
width: 36px;
}
.navds-table__toggle-expand-button {
all: unset;
display: flex;
align-items: center;
cursor: pointer;
padding: var(--navds-spacing-4);
}
.navds-table--small .navds-table__toggle-expand-button {
padding: var(--navds-spacing-2);
}
.navds-table__toggle-expand-button:focus {
box-shadow: inset var(--navds-shadow-focus);
}
.navds-table__expandable-icon {
font-size: 1.5rem;
}
.navds-table--small .navds-table__expandable-icon {
font-size: 1.25rem;
}
.navds-table__toggle-expand-button:hover .navds-table__expandable-icon,
.navds-table__expandable-icon--filled {
display: none;
}
.navds-table__toggle-expand-button:hover .navds-table__expandable-icon--filled {
display: block;
}
.navds-table__toggle-expand-cell--open .navds-table__expandable-icon {
transform: rotate(180deg);
}
.navds-table__expanded-row-cell {
padding: 0;
}
.navds-table__expanded-row-cell:empty {
display: none;
}
.navds-table__expanded-row-collapse {
transition: height 250ms cubic-bezier(0.4, 0, 0.2, 1);
border-bottom: 1px solid var(--navds-table-cell-color-border);
}
.navds-table__expanded-row-content {
padding: var(--navds-spacing-4) 4.25rem;
}
.navds-table--small .navds-table__expanded-row-content {
padding: var(--navds-spacing-2) var(--navds-spacing-12);
}
+109
View File
@@ -0,0 +1,109 @@
.navds-tabs__tablist-wrapper {
box-shadow: inset 0 -1px 0 0 var(--navds-global-color-gray-300);
width: 100%;
display: flex;
}
.navds-tabs__tablist {
display: flex;
max-width: 100%;
width: auto;
scroll-behavior: smooth;
-ms-overflow-style: none; /* for Internet Explorer, Edge */
scrollbar-width: none; /* for Firefox */
overflow-x: scroll;
}
.navds-tabs__tablist::-webkit-scrollbar {
display: none; /* for Chrome, Safari, and Opera */
}
.navds-tabs__scroll-button {
padding: var(--navds-spacing-3) var(--navds-spacing-4);
width: 44px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.navds-tabs__scroll-button--hidden {
visibility: hidden;
}
.navds-tabs__scroll-button svg {
font-size: 1.25rem;
flex-shrink: 0;
}
.navds-tabs--small .navds-tabs__scroll-button {
padding: 0.375rem var(--navds-spacing-4);
width: 32px;
}
.navds-tabs__tab {
min-height: 48px;
padding: var(--navds-spacing-3) var(--navds-spacing-4);
display: inline-flex;
justify-content: center;
align-items: center;
background: none;
border: none;
color: var(--navds-semantic-color-text-muted);
cursor: pointer;
}
.navds-tabs__tab:hover {
box-shadow: inset 0 -3px 0 0 var(--navds-global-color-gray-300);
}
.navds-tabs__tab[aria-selected="true"] {
box-shadow: inset 0 -3px 0 0 var(--navds-semantic-color-interaction-primary);
color: var(--navds-semantic-color-text);
}
.navds-tabs__tab:focus {
outline: none;
box-shadow: inset var(--navds-shadow-focus);
color: var(--navds-semantic-color-text);
}
.navds-tabs__tab-inner {
display: flex;
align-items: center;
gap: var(--navds-spacing-1);
}
.navds-tabs__tab-icon--top > .navds-tabs__tab-inner {
flex-direction: column;
gap: 0;
}
.navds-tabs__tab--small {
min-height: 32px;
padding: 0.375rem var(--navds-spacing-4);
}
.navds-tabs__tab-icon--top,
.navds-tabs__tab--small.navds-tabs__tab-icon--top {
padding: var(--navds-spacing-1) var(--navds-spacing-4);
}
.navds-tabs__tab svg,
.navds-tabs__tab--small.navds-tabs__tab--icon-only svg,
.navds-tabs__tab--small.navds-tabs__tab-icon--top svg {
font-size: 1.25rem;
}
.navds-tabs__tab--small svg {
font-size: 1rem;
}
.navds-tabs__tab--icon-only svg,
.navds-tabs__tab-icon--top svg {
font-size: 1.5rem;
}
.navds-tabs__tabpanel:focus {
outline: none;
}
+1 -1
View File
@@ -32,7 +32,7 @@
.navds-tag {
border: 1px solid;
border-color: var(--navds-tag-color-border);
border-radius: 4px;
border-radius: var(--navds-border-radius-medium);
background-color: var(--navds-tag-color-background);
display: inline-flex;
align-items: center;
+97
View File
@@ -0,0 +1,97 @@
:root {
--navds-toggle-group-color-background: var(
--navds-semantic-color-component-background-light
);
--navds-toggle-group-color-text: var(--navds-semantic-color-text);
--navds-toggle-group-color-border: var(--navds-semantic-color-divider);
--navds-toggle-group-color-background-hover: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
--navds-toggle-group-color-text-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-toggle-group-color-background-pressed: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-toggle-group-color-text-pressed: var(
--navds-semantic-color-text-inverted
);
}
.navds-toggle-group {
border-radius: 7px; /* Custom value OK */
background-color: var(--navds-toggle-group-color-background);
box-shadow: inset 0 0 0 1px var(--navds-toggle-group-color-border);
padding: calc(var(--navds-spacing-1) + 1px);
gap: var(--navds-spacing-1);
display: inline-grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
}
.navds-toggle-group__button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: var(--navds-spacing-3);
min-height: 48px;
border: none;
cursor: pointer;
background-color: var(--navds-toggle-group-color-background);
color: var(--navds-toggle-group-color-text);
border-radius: var(--navds-border-radius-small);
min-width: fit-content;
}
.navds-toggle-group__button:hover {
background-color: var(--navds-toggle-group-color-background-hover);
color: var(--navds-toggle-group-color-text-hover);
}
.navds-toggle-group__button:focus {
outline: none;
box-shadow: 0 0 0 1px var(--navds-toggle-group-color-background),
0 0 0 4px var(--navds-semantic-color-focus);
}
.navds-toggle-group__button:focus:hover[aria-pressed="false"] {
box-shadow: 0 0 0 1px var(--navds-toggle-group-color-background-hover),
0 0 0 4px var(--navds-semantic-color-focus);
}
.navds-toggle-group__button-inner {
display: flex;
align-items: center;
gap: var(--navds-spacing-2);
}
.navds-toggle-group__button-inner > * {
flex-shrink: 0;
}
.navds-toggle-group__button[aria-pressed="true"],
.navds-toggle-group__button[aria-checked="true"] {
background-color: var(--navds-toggle-group-color-background-pressed);
color: var(--navds-toggle-group-color-text-pressed);
}
.navds-toggle-group--small > .navds-toggle-group__button {
padding: 0.375rem;
min-height: 32px;
min-width: fit-content;
}
.navds-toggle-group__button > .navds-toggle-group__button-inner > svg {
font-size: 1.5rem;
}
.navds-toggle-group--small
> .navds-toggle-group__button
> .navds-toggle-group__button-inner
> svg {
font-size: 1.125rem;
}
.navds-toggle-group__label {
margin-bottom: 0.5rem;
}
+56
View File
@@ -0,0 +1,56 @@
@keyframes tooltipFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.navds-tooltip {
z-index: var(--navds-z-index-tooltip);
}
.navds-tooltip__inner {
background-color: var(--navds-semantic-color-component-background-inverted);
color: var(--navds-semantic-color-text-inverted);
border-radius: var(--navds-border-radius-small);
padding: 0 var(--navds-spacing-2);
align-items: center;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.05))
drop-shadow(0 1px 3px rgba(0, 0, 0, 0.1));
display: flex;
flex-direction: column;
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
animation-duration: 0.2s;
animation-name: tooltipFadeIn;
text-align: center;
}
.navds-tooltip__arrow {
height: 7px;
width: 7px;
transform: rotate(45deg);
z-index: -1;
background-color: var(--navds-semantic-color-component-background-inverted);
position: absolute;
}
.navds-tooltip__keys {
padding-bottom: var(--navds-spacing-1);
display: flex;
gap: var(--navds-spacing-1);
}
.navds-tooltip__key {
font-family: var(--navds-font-family);
background-color: var(--navds-global-color-gray-700);
color: var(--navds-semantic-color-text-inverted);
border-radius: var(--navds-border-radius-small);
padding: 0 var(--navds-spacing-1);
min-width: 18px;
height: 18px;
display: inline-flex;
align-items: center;
justify-content: center;
}
+22 -10
View File
@@ -43,14 +43,14 @@
},
{
"name": "Attachment",
"description": "",
"created_at": "2020-07-01T10:37:43.111Z",
"description": "2px-Original size",
"created_at": "2022-02-18T10:41:36.129Z",
"pageName": "Attachment"
},
{
"name": "AttachmentFilled",
"description": "",
"created_at": "2021-01-11T13:48:27.872Z",
"description": "2px-Original size",
"created_at": "2022-02-18T10:41:36.124Z",
"pageName": "Attachment"
},
{
@@ -708,15 +708,15 @@
"pageName": "Communication"
},
{
"name": "EmailOpen",
"description": "",
"created_at": "2020-07-01T10:37:42.632Z",
"name": "EmailOpened",
"description": "2px-Original size",
"created_at": "2022-02-18T10:41:36.018Z",
"pageName": "Communication"
},
{
"name": "EmailOpenFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.419Z",
"name": "EmailOpenedFilled",
"description": "2px-Original size",
"created_at": "2022-02-18T10:41:36.024Z",
"pageName": "Communication"
},
{
@@ -2399,6 +2399,18 @@
"created_at": "2020-07-01T10:37:42.692Z",
"pageName": "Arrow"
},
{
"name": "UpDown",
"description": "",
"created_at": "2022-03-16T13:47:53.004Z",
"pageName": "Arrow"
},
{
"name": "UpDownFilled",
"description": "",
"created_at": "2022-03-16T13:47:52.999Z",
"pageName": "Arrow"
},
{
"name": "UpFilled",
"description": "",
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "0.8.4",
"version": "0.8.10",
"private": false,
"description": "NAVs egne ikoner i SVG og React format",
"repository": {
@@ -26,10 +26,10 @@
"/meta.json"
],
"scripts": {
"create-package-json-pointers-to-esm": "node ../../../utilities/scripts/createPackageJsonsWithESMPointers.js",
"create-package-json-pointers-to-esm": "node ../../../scripts/createPackageJsonsWithESMPointers.js",
"create-icons": "svgr --out-dir src svg",
"clean": "rimraf src cjs esm",
"build": "yarn clean && yarn create-icons && tsc && tsc -p tsconfig.esm.json && yarn create-package-json-pointers-to-esm",
"build": "yarn clean && copyfiles util/* src && yarn create-icons && tsc && tsc -p tsconfig.esm.json && yarn create-package-json-pointers-to-esm",
"update": "ts-node figma/index.ts dotenv/config"
},
"dependencies": {
@@ -37,7 +37,7 @@
},
"peerDependencies": {
"@types/react": "^17.0.30",
"react": "^17.0.0"
"react": "^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@svgr/cli": "^5.5.0",
@@ -49,7 +49,7 @@
"dotenv": "^10.0.0",
"lodash.kebabcase": "^4.1.1",
"lodash.startcase": "4.4.0",
"react": "^16.8.0 || ^17.0.0",
"react": "^18.0.0",
"rimraf": "3.0.2",
"sharp": "0.29.1",
"ts-node": "^10.4.0"
+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.8634 1.00122C18.1639 0.974609 19.5426 1.3819 20.5704 2.35845C21.5981 3.33501 22.0267 4.64511 21.9987 5.88083C21.9709 7.10846 21.4908 8.35534 20.5704 9.22999L11.1693 18.163C10.6021 18.7019 9.81338 18.9683 9.05641 18.9838C8.29093 18.9995 7.45868 18.76 6.83035 18.163C6.20202 17.5659 5.95004 16.7751 5.96653 16.0478C5.98283 15.3285 6.26318 14.579 6.83035 14.0401L13.3388 7.85568C13.7382 7.47618 14.3857 7.47618 14.7851 7.85568C15.1845 8.23518 15.1845 8.85048 14.7851 9.22999L8.27667 15.4144C8.13723 15.5469 8.01819 15.7922 8.01145 16.0896C8.0049 16.3789 8.10622 16.6267 8.27667 16.7887C8.44712 16.9506 8.70788 17.0469 9.01237 17.0407C9.32537 17.0343 9.58355 16.9212 9.72299 16.7887L19.1241 7.85568C19.6168 7.38747 19.9355 6.64474 19.9538 5.83898C19.9719 5.0413 19.6939 4.27422 19.1241 3.73276C18.5542 3.19129 17.7469 2.92716 16.9075 2.94433C16.0595 2.96168 15.2778 3.26454 14.7851 3.73276L5.38403 12.6658C4.6945 13.321 4.13449 14.5364 4.05489 15.8977C3.9765 17.2386 4.37172 18.5754 5.38403 19.5373C7.5157 21.5628 10.484 21.5628 12.6156 19.5373L19.1519 13.3265C19.5513 12.947 20.1988 12.947 20.5982 13.3265C20.9976 13.706 20.9976 14.3213 20.5982 14.7008L14.0619 20.9116C11.1315 23.6961 6.86816 23.6961 3.93772 20.9116C2.41897 19.4685 1.91025 17.5412 2.01264 15.7899C2.11384 14.0591 2.81936 12.3541 3.93772 11.2914L13.3388 2.35845C14.2593 1.4838 15.5715 1.02766 16.8634 1.00122Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.377 3.30693C15.0823 1.56435 17.8563 1.56436 19.5616 3.30694C21.2551 5.03744 21.2551 7.83438 19.5616 9.56489L12.6369 16.641C11.424 17.8804 9.44839 17.8804 8.23551 16.641C7.03443 15.4136 7.03443 13.4325 8.23551 12.2052L12.5033 7.84413C12.8895 7.44941 13.5227 7.44256 13.9174 7.82884C14.3121 8.21512 14.319 8.84825 13.9327 9.24297L9.66493 13.604C9.22463 14.054 9.22463 14.7922 9.66493 15.2421C10.0934 15.68 10.779 15.68 11.2075 15.2421L18.1322 8.16605C19.0649 7.21294 19.0649 5.65888 18.1322 4.70578C17.2113 3.76474 15.7273 3.76474 14.8064 4.70577L6.06884 13.6344C4.64372 15.0907 4.64372 17.4606 6.06884 18.9168C7.48216 20.3611 9.76444 20.3611 11.1778 18.9168L11.185 18.9095L11.185 18.9095L20.2926 9.79323C20.6829 9.40252 21.3161 9.40222 21.7068 9.79255C22.0975 10.1829 22.0978 10.8161 21.7074 11.2068L12.6034 20.3196C10.4053 22.5614 6.83586 22.5601 4.63942 20.3157C2.45353 18.082 2.45353 14.4692 4.63942 12.2356L13.377 3.30693Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.3472 0.00138792C17.7614 -0.0288776 19.2813 0.434034 20.4223 1.56794L19.3387 2.6448L20.4223 1.56794C21.5633 2.70184 22.0291 4.21243 21.9986 5.61786C21.9684 7.01063 21.4486 8.445 20.4223 9.46495L11.0314 18.7978C10.358 19.467 9.43759 19.7854 8.57056 19.8039C7.69079 19.8227 6.71672 19.5352 5.97471 18.7978C5.23271 18.0604 4.94338 17.0923 4.96233 16.218C4.981 15.3563 5.30134 14.4416 5.97472 13.7724L12.4761 7.31122C13.0746 6.71649 14.0448 6.71649 14.6433 7.31122C15.2417 7.90596 15.2417 8.87022 14.6433 9.46495L8.14185 15.9261C8.10938 15.9584 8.03076 16.083 8.02641 16.2836C8.02234 16.4715 8.08594 16.5885 8.14185 16.6441C8.19777 16.6996 8.31553 16.7628 8.50458 16.7588C8.70636 16.7545 8.83176 16.6763 8.86423 16.6441L18.2552 7.31122C18.6406 6.92821 18.9187 6.28392 18.9345 5.55228C18.9501 4.8333 18.71 4.17373 18.2552 3.72167C17.8003 3.26961 17.1366 3.03104 16.4132 3.04652C15.677 3.06227 15.0287 3.33865 14.6433 3.72167L5.25234 13.0545C4.67063 13.6326 4.14756 14.7746 4.07345 16.1004C4.00113 17.3941 4.36759 18.6364 5.25234 19.5157C7.18223 21.4337 9.82386 21.4337 11.7538 19.5157L18.2829 13.0269C18.8814 12.4322 19.8516 12.4322 20.4501 13.0269C21.0485 13.6216 21.0485 14.5859 20.4501 15.1806L13.9209 21.6694C10.7941 24.7769 6.21196 24.7769 3.0852 21.6694C1.44161 20.036 0.9051 17.8683 1.01337 15.9314C1.11986 14.0266 1.86096 12.1174 3.0852 10.9008L12.4761 1.56794C13.5024 0.547983 14.9457 0.0313808 16.3472 0.00138792Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0C0.895431 0 0 0.89543 0 2V22C0 23.1046 0.89543 24 2 24H22C23.1046 24 24 23.1046 24 22V2C24 0.895431 23.1046 0 22 0H2ZM13.377 3.30693C15.0823 1.56435 17.8563 1.56436 19.5616 3.30694C21.2551 5.03744 21.2551 7.83438 19.5616 9.56489L12.6369 16.641C11.424 17.8804 9.44839 17.8804 8.23551 16.641C7.03443 15.4136 7.03443 13.4325 8.23551 12.2052L12.5033 7.84413C12.8895 7.44941 13.5227 7.44256 13.9174 7.82884C14.3121 8.21512 14.319 8.84825 13.9327 9.24297L9.66493 13.604C9.22463 14.054 9.22463 14.7922 9.66493 15.2421C10.0934 15.68 10.779 15.68 11.2075 15.2421L18.1322 8.16605C19.0649 7.21294 19.0649 5.65888 18.1322 4.70578C17.2113 3.76474 15.7273 3.76474 14.8064 4.70577L6.06884 13.6344C4.64372 15.0907 4.64372 17.4606 6.06884 18.9168C7.48216 20.3611 9.76444 20.3611 11.1778 18.9168L11.1845 18.91L11.1845 18.91L13.2429 16.8466C13.2588 16.8283 13.2754 16.8103 13.2929 16.7929L14.792 15.2937L20.2929 9.79289C20.6834 9.40237 21.3166 9.40237 21.7071 9.79289C22.0976 10.1834 22.0976 10.8166 21.7071 11.2071L16.208 16.7063L16.2072 16.707L12.6037 20.3192C10.4057 22.5614 6.83597 22.5603 4.63942 20.3157C2.45353 18.082 2.45353 14.4692 4.63942 12.2356L13.377 3.30693Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

-3
View File
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4.23607L2.4102 8.03097L12 13.2254L21.5898 8.03097L12 4.23607ZM0 7.80877V7L12 2L24 7V7.80878C24 7.87303 23.9969 7.93683 23.9909 8H24V19C24 20.6569 22.6569 22 21 22H3C1.34314 22 0 20.6569 0 19V8H0.00913671C0.00308106 7.93683 0 7.87303 0 7.80877ZM2 17.1315L7.83295 13.2428L2 10.0833V17.1315ZM9.82222 14.3204L2.11208 19.4605C2.27866 19.781 2.61376 20 3 20H21C21.3862 20 21.7213 19.781 21.8879 19.4605L14.1778 14.3204L12 15.5L9.82222 14.3204ZM22 10.0833V17.1315L16.1671 13.2428L22 10.0833Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 659 B

@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 15.5L24 9V7L12 2L0 7V9L12 15.5ZM15.833 15.4238L23.8477 20.7669C23.5468 21.4909 22.8329 22 22 22H2C1.16715 22 0.453196 21.4909 0.15234 20.767L8.16706 15.4238L12 17.5L15.833 15.4238ZM24 11V18.4648L17.8222 14.3463L24 11ZM0 11L6.17779 14.3463L0 18.4648V11Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 427 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 8.2L0.518081 7.32378L0 7.60873V8.2H1ZM23 8.2H24V7.60873L23.4819 7.32378L23 8.2ZM12 2.15L12.4819 1.27378L12 1.00873L11.5181 1.27378L12 2.15ZM12 15L11.5211 15.8779L12 16.1391L12.4789 15.8779L12 15ZM22 20H2V22H22V20ZM1.48192 9.07622L12.4819 3.02622L11.5181 1.27378L0.518081 7.32378L1.48192 9.07622ZM11.5181 3.02622L22.5181 9.07622L23.4819 7.32378L12.4819 1.27378L11.5181 3.02622ZM22 8.2V9H24V8.2H22ZM2 9V8.2H0V9H2ZM22 9V20H24V9H22ZM22.5211 8.1221L13.5211 13.0312L14.4789 14.787L23.4789 9.8779L22.5211 8.1221ZM13.5211 13.0312L11.5211 14.1221L12.4789 15.8779L14.4789 14.787L13.5211 13.0312ZM23.5605 19.1718L14.5605 13.0809L13.4395 14.7373L22.4395 20.8282L23.5605 19.1718ZM2 20V9H0V20H2ZM12.4789 14.1221L10.4789 13.0312L9.52115 14.787L11.5211 15.8779L12.4789 14.1221ZM10.4789 13.0312L1.47885 8.1221L0.521148 9.8779L9.52115 14.787L10.4789 13.0312ZM1.56048 20.8282L10.5605 14.7373L9.43952 13.0809L0.439522 19.1718L1.56048 20.8282ZM2 20H2H0C0 21.1046 0.895431 22 2 22V20ZM22 22C23.1046 22 24 21.1046 24 20H22V22Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.210623 7.51518L10.4732 13.0282L10.4789 13.0312L10.4789 13.0312L12 13.8609L13.5211 13.0312L13.5268 13.0281L13.5268 13.0282L23.7894 7.51518L12 1L0.210623 7.51518ZM24 9.67234L15.9314 14.0067L24 19.4557V9.67234ZM23.3783 21.4492L13.9446 15.0784L12.4789 15.8779L12 16.1391L11.5211 15.8779L10.0554 15.0784L0.621651 21.4492C0.980399 21.7905 1.46574 22 2 22H22C22.5343 22 23.0196 21.7905 23.3783 21.4492ZM0 19.4557L8.06862 14.0067L0 9.67234V19.4557Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 614 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.50256 5.46703L7.17181 6.69387C7.06015 7.10802 7 7.54543 7 8C7 10.7614 9.23858 13 12 13C14.7614 13 17 10.7614 17 8C17 7.54543 16.9398 7.10801 16.8282 6.69387L16.4974 5.46702L17.4675 4.64636C17.7964 4.3681 18 3.95882 18 3.5C18 2.67157 17.3284 2 16.5 2C16.0412 2 15.6319 2.20357 15.3536 2.53248L14.533 3.50256L13.3061 3.1718C12.892 3.06015 12.4546 3 12 3C11.5454 3 11.108 3.06015 10.6939 3.17181L9.46703 3.50256L8.64636 2.53248C8.3681 2.20357 7.95882 2 7.5 2C6.67157 2 6 2.67157 6 3.5C6 3.95882 6.20357 4.3681 6.53248 4.64636L7.50256 5.46703ZM19 8C19 9.09191 18.75 10.1254 18.3041 11.0464L19.3117 10.7765C20.9121 10.3476 22.5571 11.2974 22.9859 12.8978C23.4148 14.4982 22.465 16.1432 20.8646 16.572L19.2673 17H19.5C21.433 17 23 18.567 23 20.5C23 22.433 21.433 24 19.5 24H4.5C2.567 24 1 22.433 1 20.5C1 18.567 2.567 17 4.5 17H4.89138L3.29411 16.572C1.69371 16.1432 0.743963 14.4982 1.17279 12.8978C1.60161 11.2974 3.24662 10.3476 4.84702 10.7765L5.67251 10.9976C5.24127 10.089 5 9.07267 5 8C5 7.36803 5.08375 6.75562 5.24075 6.17326C4.48185 5.53124 4 4.57189 4 3.5C4 1.567 5.567 0 7.5 0C8.57189 0 9.53124 0.481847 10.1733 1.24075C10.7556 1.08375 11.368 1 12 1C12.632 1 13.2444 1.08375 13.8267 1.24075C14.4688 0.481845 15.4281 0 16.5 0C18.433 0 20 1.567 20 3.5C20 4.57189 19.5182 5.53124 18.7593 6.17326C18.9163 6.75562 19 7.36803 19 8ZM12 15C10.5061 15 9.26396 16.0939 9.03723 17.5241L8.96058 18.0077C9.51318 18.5435 9.99991 19.3532 9.99991 20.5C9.99991 21.065 9.89085 21.5702 9.73917 22H14.2608C14.1092 21.5702 14.0001 21.065 14.0001 20.5C14.0001 19.3532 14.4868 18.5435 15.0394 18.0077L14.9628 17.5241C14.736 16.0939 13.4939 15 12 15ZM19.5 22H16.4819C16.4454 21.9453 16.4069 21.8839 16.3683 21.8164C16.1761 21.4799 16.0001 21.0262 16.0001 20.5C16.0001 19.9689 16.2159 19.6312 16.4829 19.3953L17.4403 19.1469C17.8086 19.0514 18.1968 19 18.6 19H19.5C20.3284 19 21 19.6716 21 20.5C21 21.3284 20.3284 22 19.5 22ZM7.51806 22C7.55463 21.9453 7.59309 21.8839 7.63167 21.8164C7.82391 21.4799 7.99991 21.0262 7.99991 20.5C7.99991 19.9689 7.7841 19.6312 7.51715 19.3953L6.55975 19.1469C6.19139 19.0514 5.80317 19 5.4 19H4.5C3.67157 19 3 19.6716 3 20.5C3 21.3284 3.67157 22 4.5 22H7.51806ZM3.81175 14.6402L6.70952 15.4166C7.24299 15.5596 7.79133 15.243 7.93427 14.7095C8.07721 14.176 7.76063 13.6277 7.22716 13.4848L4.32939 12.7083C3.79592 12.5654 3.24758 12.8819 3.10464 13.4154C2.9617 13.9489 3.27828 14.4972 3.81175 14.6402ZM17.4492 15.4166L20.347 14.6402C20.8804 14.4972 21.197 13.9489 21.0541 13.4154C20.9111 12.8819 20.3628 12.5654 19.8293 12.7083L16.9316 13.4848C16.3981 13.6277 16.0815 14.176 16.2244 14.7095C16.3674 15.243 16.9157 15.5596 17.4492 15.4166ZM12 10C12.5523 10 13 9.55229 13 9C13 8.44771 12.5523 8 12 8C11.4477 8 11 8.44771 11 9C11 9.55229 11.4477 10 12 10Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.50256 5.46703L7.17181 6.69387C7.06015 7.10802 7 7.54543 7 8C7 10.7614 9.23858 13 12 13C14.7614 13 17 10.7614 17 8C17 7.54543 16.9398 7.10801 16.8282 6.69387L16.4974 5.46702L17.4675 4.64636C17.7964 4.3681 18 3.95882 18 3.5C18 2.67157 17.3284 2 16.5 2C16.0412 2 15.6319 2.20357 15.3536 2.53248L14.533 3.50256L13.3061 3.1718C12.892 3.06015 12.4546 3 12 3C11.5454 3 11.108 3.06015 10.6939 3.17181L9.46703 3.50256L8.64636 2.53248C8.3681 2.20357 7.95882 2 7.5 2C6.67157 2 6 2.67157 6 3.5C6 3.95882 6.20357 4.3681 6.53248 4.64636L7.50256 5.46703ZM19 8C19 9.09191 18.75 10.1254 18.3041 11.0464L19.3117 10.7765C20.9121 10.3476 22.5571 11.2974 22.9859 12.8978C23.4148 14.4982 22.465 16.1432 20.8646 16.572L19.2673 17H19.5C21.433 17 23 18.567 23 20.5C23 22.433 21.433 24 19.5 24H4.5C2.567 24 1 22.433 1 20.5C1 18.567 2.567 17 4.5 17H4.89138L3.29411 16.572C1.69371 16.1432 0.743963 14.4982 1.17279 12.8978C1.60161 11.2974 3.24662 10.3476 4.84702 10.7765L5.67251 10.9976C5.24127 10.089 5 9.07267 5 8C5 7.36803 5.08375 6.75562 5.24075 6.17326C4.48185 5.53124 4 4.57189 4 3.5C4 1.567 5.567 0 7.5 0C8.57189 0 9.53124 0.481847 10.1733 1.24075C10.7556 1.08375 11.368 1 12 1C12.632 1 13.2444 1.08375 13.8267 1.24075C14.4688 0.481845 15.4281 0 16.5 0C18.433 0 20 1.567 20 3.5C20 4.57189 19.5182 5.53124 18.7593 6.17326C18.9163 6.75562 19 7.36803 19 8ZM12 15C10.5061 15 9.26396 16.0939 9.03723 17.5241L8.96058 18.0077C9.51318 18.5435 9.99991 19.3532 9.99991 20.5C9.99991 21.065 9.89085 21.5702 9.73917 22H14.2608C14.1092 21.5702 14.0001 21.065 14.0001 20.5C14.0001 19.3532 14.4868 18.5435 15.0394 18.0077L14.9628 17.5241C14.736 16.0939 13.4939 15 12 15ZM19.5 22H16.4819C16.4454 21.9453 16.4069 21.8839 16.3683 21.8164C16.1761 21.4799 16.0001 21.0262 16.0001 20.5C16.0001 19.9689 16.2159 19.6312 16.4829 19.3953L17.4403 19.1469C17.8086 19.0514 18.1968 19 18.6 19H19.5C20.3284 19 21 19.6716 21 20.5C21 21.3284 20.3284 22 19.5 22ZM7.51806 22C7.55463 21.9453 7.59309 21.8839 7.63167 21.8164C7.82391 21.4799 7.99991 21.0262 7.99991 20.5C7.99991 19.9689 7.7841 19.6312 7.51715 19.3953L6.55975 19.1469C6.19139 19.0514 5.80317 19 5.4 19H4.5C3.67157 19 3 19.6716 3 20.5C3 21.3284 3.67157 22 4.5 22H7.51806ZM3.81175 14.6402L6.70952 15.4166C7.24299 15.5596 7.79133 15.243 7.93427 14.7095C8.07721 14.176 7.76063 13.6277 7.22716 13.4848L4.32939 12.7083C3.79592 12.5654 3.24758 12.8819 3.10464 13.4154C2.9617 13.9489 3.27828 14.4972 3.81175 14.6402ZM17.4492 15.4166L20.347 14.6402C20.8804 14.4972 21.197 13.9489 21.0541 13.4154C20.9111 12.8819 20.3628 12.5654 19.8293 12.7083L16.9316 13.4848C16.3981 13.6277 16.0815 14.176 16.2244 14.7095C16.3674 15.243 16.9157 15.5596 17.4492 15.4166ZM12 10C12.5523 10 13 9.55228 13 9C13 8.44771 12.5523 8 12 8C11.4477 8 11 8.44771 11 9C11 9.55228 11.4477 10 12 10Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.36562 5.9328C5.01344 5.6417 4 4.4392 4 3C4 1.34315 5.34315 0 7 0C8.4392 0 9.6417 1.01344 9.9328 2.36562C10.5773 2.1291 11.2735 2 12 2C12.7265 2 13.4228 2.1291 14.0672 2.36562C14.3583 1.01344 15.5608 0 17 0C18.6569 0 20 1.34315 20 3C20 4.4392 18.9866 5.6417 17.6344 5.9328C17.8709 6.57725 18 7.27355 18 8C18 9.55877 17.4056 10.9787 16.4311 12.0455L18.7614 11.4211C19.8283 11.1352 20.925 11.7684 21.2109 12.8353C21.4967 13.9022 20.8636 14.9989 19.7966 15.2848L16.6389 16.1309C16.8718 16.7083 17 17.3392 17 18V19.2774C17.4083 19.099 17.8593 19 18.3333 19H20.5C21.8807 19 23 20.1193 23 21.5C23 22.8807 21.8807 24 20.5 24H16.6667C16.0642 24 15.5364 23.6803 15.2436 23.2014C14.5478 23.7039 13.6931 24 12.7692 24H11.2308C10.3069 24 9.4522 23.7039 8.7564 23.2014C8.46361 23.6803 7.9358 24 7.33333 24H3.5C2.11929 24 1 22.8807 1 21.5C1 20.1193 2.11929 19 3.5 19H5.66667C6.14074 19 6.59169 19.099 7 19.2774V18C7 17.3976 7.10651 16.8202 7.30173 16.2854L3.5675 15.2848C2.50057 14.9989 1.8674 13.9022 2.15329 12.8353C2.43917 11.7684 3.53585 11.1352 4.60278 11.4211L7.79011 12.2751C6.68509 11.1869 6 9.67345 6 8C6 7.27355 6.1291 6.57725 6.36562 5.9328ZM12 10C12.5523 10 13 9.55229 13 9C13 8.44771 12.5523 8 12 8C11.4477 8 11 8.44771 11 9C11 9.55229 11.4477 10 12 10ZM14 18C14 19.6569 13.1046 21 12 21C10.8954 21 10 19.6569 10 18C10 16.3431 10.8954 15 12 15C13.1046 15 14 16.3431 14 18Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.36562 5.9328C5.01344 5.6417 4 4.4392 4 3C4 1.34315 5.34315 0 7 0C8.4392 0 9.6417 1.01344 9.9328 2.36562C10.5773 2.1291 11.2735 2 12 2C12.7265 2 13.4228 2.1291 14.0672 2.36562C14.3583 1.01344 15.5608 0 17 0C18.6569 0 20 1.34315 20 3C20 4.4392 18.9866 5.6417 17.6344 5.9328C17.8709 6.57725 18 7.27355 18 8C18 9.55877 17.4056 10.9787 16.4311 12.0455L18.7614 11.4211C19.8283 11.1352 20.925 11.7684 21.2109 12.8353C21.4967 13.9022 20.8636 14.9989 19.7966 15.2848L16.6389 16.1309C16.8718 16.7083 17 17.3392 17 18V19.2774C17.4083 19.099 17.8593 19 18.3333 19H20.5C21.8807 19 23 20.1193 23 21.5C23 22.8807 21.8807 24 20.5 24H16.6667C16.0642 24 15.5364 23.6803 15.2436 23.2014C14.5478 23.7039 13.6931 24 12.7692 24H11.2308C10.3069 24 9.4522 23.7039 8.7564 23.2014C8.46361 23.6803 7.9358 24 7.33333 24H3.5C2.11929 24 1 22.8807 1 21.5C1 20.1193 2.11929 19 3.5 19H5.66667C6.14074 19 6.59169 19.099 7 19.2774V18C7 17.3976 7.10651 16.8202 7.30173 16.2854L3.5675 15.2848C2.50057 14.9989 1.8674 13.9022 2.15329 12.8353C2.43917 11.7684 3.53585 11.1352 4.60278 11.4211L7.79011 12.2751C6.68509 11.1869 6 9.67345 6 8C6 7.27355 6.1291 6.57725 6.36562 5.9328ZM12 10C12.5523 10 13 9.55228 13 9C13 8.44771 12.5523 8 12 8C11.4477 8 11 8.44771 11 9C11 9.55228 11.4477 10 12 10ZM14 18C14 19.6569 13.1046 21 12 21C10.8954 21 10 19.6569 10 18C10 16.3431 10.8954 15 12 15C13.1046 15 14 16.3431 14 18Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9988 5.9571L5.99745 1.57383e-06L5.20444e-07 5.95319L1.40897 7.37263L4.99745 3.81063L4.99745 15.0028L6.99745 15.0028L6.99745 3.81064L10.5898 7.37654L11.9988 5.9571ZM12.0012 18.0429L18.0025 24L24 18.0468L22.591 16.6274L19.0025 20.1894L19.0025 8.99724L17.0025 8.99724L17.0025 20.1894L13.4102 16.6235L12.0012 18.0429Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 488 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.9988 5.9571L5.99746 1.57373e-06L2.42779e-06 5.95319L3.99745 5.9571L3.99745 15.0028L7.99745 15.0028L7.99745 5.9571L11.9988 5.9571ZM12 18.0457L18.0014 24.0028L23.9988 18.0496L20.0014 18.0457L20.0014 9.00001L16.0014 9.00001L16.0014 18.0457L12 18.0457Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0ZM12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM12 16C12.8284 16 13.5 16.6716 13.5 17.5C13.5 18.3284 12.8284 19 12 19C11.1716 19 10.5 18.3284 10.5 17.5C10.5 16.6716 11.1716 16 12 16ZM13 5V14H11V5H13Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C12.3788 0 12.725 0.214002 12.8944 0.552786L23.8944 22.5528C24.0494 22.8628 24.0329 23.2309 23.8507 23.5257C23.6684 23.8205 23.3466 24 23 24H1C0.653423 24 0.331557 23.8205 0.14935 23.5257C-0.0328564 23.2309 -0.0494204 22.8628 0.105574 22.5528L11.1056 0.552786C11.275 0.214002 11.6212 0 12 0ZM21.382 22L12 3.23607L2.61804 22H21.382ZM11 15V8H13V15H11ZM12 20C12.8284 20 13.5 19.3284 13.5 18.5C13.5 17.6716 12.8284 17 12 17C11.1716 17 10.5 17.6716 10.5 18.5C10.5 19.3284 11.1716 20 12 20Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 547 B

After

Width:  |  Height:  |  Size: 660 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0ZM12 16C12.8284 16 13.5 16.6716 13.5 17.5C13.5 18.3284 12.8284 19 12 19C11.1716 19 10.5 18.3284 10.5 17.5C10.5 16.6716 11.1716 16 12 16ZM13 5V14H11V5H13Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C12.3788 0 12.725 0.214002 12.8944 0.552786L23.8944 22.5528C24.0494 22.8628 24.0329 23.2309 23.8507 23.5257C23.6684 23.8205 23.3466 24 23 24H1C0.653423 24 0.331557 23.8205 0.14935 23.5257C-0.0328564 23.2309 -0.0494204 22.8628 0.105574 22.5528L11.1056 0.552786C11.275 0.214002 11.6212 0 12 0ZM11 15V8H13V15H11ZM13.5 18.5C13.5 19.3284 12.8284 20 12 20C11.1716 20 10.5 19.3284 10.5 18.5C10.5 17.6716 11.1716 17 12 17C12.8284 17 13.5 17.6716 13.5 18.5Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 624 B

+7 -7
View File
@@ -15,13 +15,13 @@ function defaultTemplate(
type: "ImportSpecifier",
imported: {
type: "Identifier",
name: "v4",
name: "useId",
},
},
],
source: {
type: "StringLiteral",
value: "uuid",
value: "./util/useId",
},
});
@@ -34,12 +34,12 @@ function defaultTemplate(
return typeScriptTpl.ast`
${imports}
${interfaces}
function ${componentName}(${props}) {
const titleId = _titleId ?? (title ?
"icon-title-" + v4() : undefined);
const ${componentName} = React.forwardRef((${props}) => {
let titleId: string | undefined = useId();
titleId = title ? _titleId ? _titleId : "title-" + titleId : undefined;
return ${jsx};
}
${exports}`;
});
export default ${componentName}`;
}
module.exports = defaultTemplate;
+1 -1
View File
@@ -4,5 +4,5 @@
"outDir": "./cjs",
"module": "commonjs"
},
"exclude": ["./figma", "./scripts", "**/*.stories.*"]
"exclude": ["./figma", "./util", "./scripts", "**/*.stories.*"]
}
+22
View File
@@ -0,0 +1,22 @@
import { useLayoutEffect, useState } from "react";
import { v4 } from "uuid";
const canUseDOM = (): boolean => {
return (
typeof window !== "undefined" &&
typeof window.document !== "undefined" &&
typeof window.document.createElement !== "undefined"
);
};
export const useClientLayoutEffect = canUseDOM() ? useLayoutEffect : () => {};
export const useId: (id?: string) => string = (id) => {
const [newId, setNewId] = useState<string | undefined>(undefined);
useClientLayoutEffect(() => {
setNewId(v4());
}, []);
return id ?? newId ?? "";
};
+17 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.16.7",
"version": "0.17.22",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
@@ -27,16 +27,19 @@
"/src"
],
"scripts": {
"create-package-json-pointers-to-esm": "node ../../../utilities/scripts/createPackageJsonsWithESMPointers.js",
"create-package-json-pointers-to-esm": "node ../../../scripts/createPackageJsonsWithESMPointers.js",
"clean": "rimraf cjs esm",
"build": "yarn run clean && tsc && tsc -p tsconfig.esm.json && yarn create-package-json-pointers-to-esm",
"watch": "tsc --watch -p tsconfig.esm.json",
"test": "jest"
},
"dependencies": {
"@floating-ui/react-dom": "0.6.0",
"@material-ui/core": "^4.12.3",
"@navikt/ds-icons": "^0.8.4",
"@navikt/ds-icons": "^0.8.10",
"@popperjs/core": "^2.10.1",
"@radix-ui/react-tabs": "0.1.5",
"@radix-ui/react-toggle-group": "0.1.5",
"classnames": "^2.2.6",
"react-collapse": "^5.1.0",
"react-merge-refs": "^1.1.0",
@@ -45,23 +48,25 @@
"uuid": "^8.3.2"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.0",
"@testing-library/user-event": "^13.2.1",
"@types/faker": "^5.5.8",
"@testing-library/jest-dom": "^5.16.0",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^14.0.0",
"@types/faker": "5.5.8",
"@types/jest": "^27.0.1",
"@types/react-collapse": "^5.0.1",
"@types/react-modal": "^3.13.1",
"@types/styled-components": "^5.1.14",
"copyfiles": "^2.4.1",
"faker": "^5.5.3",
"jest": "^27.2.0",
"react-router-dom": "^6.1.0",
"faker": "5.5.3",
"jest": "^27.5.0",
"react-router-dom": "^6.3.0",
"rimraf": "3.0.2",
"styled-components": "^5.3.1",
"ts-jest": "^27.0.5"
"swr": "^1.1.2",
"ts-jest": "^27.1.0"
},
"peerDependencies": {
"@types/react": "^17.0.30",
"react": "^17.0.0"
"react": "^17.0.0 || ^18.0.0"
}
}
@@ -5,7 +5,7 @@ import AccordionItem from "./AccordionItem";
import { Accordion } from ".";
export default {
title: "ds-react/accordion",
title: "ds-react/Accordion",
component: Accordion,
subcomponents: {
AccordionItem,
@@ -14,77 +14,89 @@ export default {
},
};
export const All = () => {
const Content = () => (
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit occaecat nisi qui
nostrud sit consectetur consectetur officia nostrud ullamco. Est ex duis
proident nostrud elit qui laborum anim minim eu eiusmod. Veniam in nostrud
sunt tempor velit incididunt sint ex dolor qui velit id eu. Deserunt magna
sunt velit in. Est exercitation id cillum qui do. Minim adipisicing nostrud
commodo proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit mollit
velit.Ut consequat commodo minim occaecat id pariatur. Nisi enim tempor
laborum commodo. Tempor sit quis nostrud eu cupidatat sunt commodo
reprehenderit irure deserunt eiusmod ipsum. Exercitation quis commodo cillum
eiusmod eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
);
export const Default = (props) => {
const [open, setOpen] = useState(false);
const Item = () =>
props.controlled ? (
<Accordion.Item
open={open}
renderContentWhenClosed={props.renderContentWhenClosed}
>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Content />
</Accordion.Item>
) : (
<Accordion.Item renderContentWhenClosed={props.renderContentWhenClosed}>
<Accordion.Header>Accordion header text</Accordion.Header>
<Content />
</Accordion.Item>
);
return (
<>
<h1>Accordion</h1>
<h2>Controlled</h2>
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
<h2>Un-controlled</h2>
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</>
<Accordion>
{[...Array(props.nItems ? props.nItems : 2)].map((_, y) => (
<Item key={y} />
))}
</Accordion>
);
};
Default.args = {
controlled: false,
renderContentWhenClosed: false,
nItems: 2,
};
export const Controlled = () => {
const [open, setOpen] = useState(false);
const [open2, setOpen2] = useState(false);
return (
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Content />
</Accordion.Item>
<Accordion.Item open={open2}>
<Accordion.Header onClick={() => setOpen2(!open2)}>
Accordion header text
</Accordion.Header>
<Content />
</Accordion.Item>
</Accordion>
);
};
export const Uncontrolled = () => (
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Content />
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Content />
</Accordion.Item>
</Accordion>
);
+3 -3
View File
@@ -1,11 +1,11 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import {
ErrorFilled,
WarningFilled,
InformationFilled,
SuccessFilled,
WarningFilled,
} from "@navikt/ds-icons";
import cl from "classnames";
import React, { forwardRef } from "react";
import { BodyLong } from "..";
export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
+85 -95
View File
@@ -1,9 +1,9 @@
import React from "react";
import { Alert } from ".";
import { BodyLong, Heading } from "..";
import { BodyLong, Heading as DsHeading } from "..";
export default {
title: "ds-react/alert",
title: "ds-react/Alert",
component: Alert,
};
@@ -14,111 +14,101 @@ const variants: Array<"error" | "warning" | "info" | "success"> = [
"success",
];
export const All = () => {
export const Default = (props) => (
<Alert
variant={props.variant}
size={props.size}
fullWidth={props.fullWidth}
inline={props.inline}
>
{props.children}
</Alert>
);
Default.args = {
variant: "info",
children: "Id elit esse enim reprehenderit enim nisi veniam nostrud.",
};
export const Small = () => {
return (
<>
<h1>Alert</h1>
<div className="colgap">
{variants.map((variant, i) => (
<Alert key={variant} variant={variant}>
<Alert key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
<h2>Small</h2>
<div>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Alert fullWidth</h2>
</div>
);
};
export const FullWidth = () => {
return (
<div className="colgap">
{variants.map((variant, i) => (
<Alert fullWidth key={variant} variant={variant}>
<Alert key={variant} variant={variant} fullWidth>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
<h2>Small</h2>
<div>
{variants.map((variant, i) => (
<Alert fullWidth key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Inline</h2>
<div>
{variants.map((variant, i) => (
<Alert inline key={variant} variant={variant}>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Inline small</h2>
<div>
{variants.map((variant, i) => (
<Alert inline key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Med Heading</h2>
<div>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant}>
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong spacing>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
<Heading level="4" size="xsmall" spacing>
Ullamco eiusmod Lorem eiusmod eu.
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
</Alert>
))}
</div>
<h2>Med Heading small</h2>
<div>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} size="small">
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong spacing>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
<Heading level="4" size="xsmall" spacing>
Ullamco eiusmod Lorem eiusmod eu.
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
</Alert>
))}
</div>
</>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} fullWidth size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
);
};
export const Inline = () => {
return (
<div className="colgap">
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} inline>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} inline size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
);
};
export const Heading = () => {
return (
<div className="colgap">
<Alert variant="info">
<DsHeading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</DsHeading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
sint commodo consequat eu aute.
</BodyLong>
</Alert>
<Alert variant="info" size="small">
<DsHeading spacing size="xsmall" level="3">
Aliquip duis est in commodo pariatur
</DsHeading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
sint commodo consequat eu aute.
</BodyLong>
</Alert>
</div>
);
};
+7 -3
View File
@@ -19,7 +19,7 @@ export interface ButtonProps
* Changes padding, height and font-size
* @default "medium"
*/
size?: "medium" | "small";
size?: "medium" | "small" | "xsmall";
/**
* Prevent the user from interacting with the button: it cannot be pressed or focused.
* @note Avoid using if possible for accessibility purposes
@@ -43,6 +43,7 @@ const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
size = "medium",
loading = false,
disabled,
style,
...rest
},
ref
@@ -76,13 +77,16 @@ const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
"navds-button--loading": widthOverride,
}
)}
style={{ width: widthOverride }}
style={{
...style,
width: widthOverride,
}}
disabled={disabled ?? widthOverride ? true : undefined}
>
<BodyShort
as="span"
className="navds-button__inner"
size={size}
size={size === "medium" ? "medium" : "small"}
aria-live="polite"
>
{widthOverride ? <Loader size={size} /> : children}
+143 -123
View File
@@ -1,30 +1,29 @@
import React, { useState } from "react";
import { Star } from "@navikt/ds-icons";
import React from "react";
import { Button } from "./index";
import { Success } from "@navikt/ds-icons";
export default {
title: "ds-react/button",
title: "ds-react/Button",
component: Button,
parameters: {
chromatic: { delay: 300 },
},
argTypes: {
variant: {
control: {
type: "radio",
options: ["primary", "secondary", "tertiary", "danger"],
},
},
size: {
control: {
type: "radio",
options: ["medium", "small"],
},
},
},
};
const Section = ({ children }) => (
<div
style={{
display: "flex",
gap: 16,
gridAutoFlow: "column",
justifyContent: "start",
padding: 24,
paddingLeft: 0,
}}
>
{children}
</div>
);
const variants: Array<"primary" | "secondary" | "tertiary" | "danger"> = [
"primary",
"secondary",
@@ -39,111 +38,132 @@ const varSwitch = {
danger: "Danger",
};
export const All = () => {
const [loadingState, setLoadingState] = useState(true);
const [content, setContent] = useState<string>("");
const toggleLoading = () => {
setLoadingState(!loadingState);
};
export const Default = (props) => {
return (
<div style={{ paddingLeft: "1rem" }}>
<h1>Button</h1>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
{varSwitch[variant]}
</Button>
))}
</Section>
<h2>disabled</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} disabled>
{varSwitch[variant]}
</Button>
))}
</Section>
<h2>As link</h2>
<Section>
{variants.map((variant) => (
<Button as="a" key={variant} variant={variant} href="the-link">
{varSwitch[variant]}
</Button>
))}
</Section>
<h2>Small</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
{varSwitch[variant]}
</Button>
))}
</Section>
<h2>Button w/icon</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
{variant} <Success />
</Button>
))}
</Section>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span className="navds-sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
<h2>Small w/icon</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<Success /> {variant}
</Button>
))}
</Section>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<span className="navds-sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
<h2>Button w/loader</h2>
<Button onClick={toggleLoading}>Toggle loaders</Button>
<Button onClick={() => setContent((content) => `${content} wat`)}>
Change content
</Button>
<Section>
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
loading={loadingState}
onClick={toggleLoading}
>
{content || varSwitch[variant]}
</Button>
))}
</Section>
<h2>Small w/loader</h2>
<Section>
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
size="small"
loading={loadingState}
onClick={toggleLoading}
>
{varSwitch[variant]}
</Button>
))}
</Section>
</div>
<Button variant={props.variant} size={props.size} loading={props.loading}>
{props.icon ? <Star /> : null}
{props.children}
{props.icon ? <Star /> : null}
</Button>
);
};
Default.args = {
icon: false,
loading: false,
children: "Knapp",
};
export const Small = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
{varSwitch[variant]}
</Button>
))}
</div>
);
export const XSmall = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="xsmall">
{varSwitch[variant]}
</Button>
))}
</div>
);
export const Loading = () => (
<div className="colgap">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading>
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading size="small">
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading size="xsmall">
{varSwitch[variant]}
</Button>
))}
</div>
</div>
);
export const Icon = () => (
<div className="colgap">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<Star />
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<Star />
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="xsmall">
<Star />
</Button>
))}
</div>
</div>
);
export const IconWText = () => (
<div className="colgap">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<Star />
{varSwitch[variant]}
<Star />
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<Star />
{varSwitch[variant]}
<Star />
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="xsmall">
<Star />
{varSwitch[variant]}
<Star />
</Button>
))}
</div>
</div>
);
export const Link = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} as="a" href="#thecakeisalie">
{varSwitch[variant]}
</Button>
))}
</div>
);
@@ -1,7 +1,7 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { MicroCard } from "../index.ts";
<Meta title="ds-react/card/intro" />
<Meta title="ds-react(deprecated)/card/intro" />
# Hvordan ta i bruk card
@@ -2,7 +2,7 @@ import React from "react";
import { MicroCard } from "../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
title: "ds-react/card",
title: "ds-react(deprecated)/card",
component: MicroCard,
} as Meta;
@@ -10,7 +10,7 @@ export interface ConfirmationPanelProps extends Partial<CheckboxProps> {
/**
* Checkbox label
*/
label: string;
label: React.ReactNode;
/**
* Checked state for checkbox
*/
+1 -1
View File
@@ -19,7 +19,7 @@ export interface SelectProps
/**
* Label for select
*/
label: string;
label: React.ReactNode;
/**
* If enabled shows the label and description for screenreaders only
*/
@@ -6,11 +6,12 @@ import { Checkbox, CheckboxGroup } from ".";
const firstArgumentOfFirstCall = (fn: jest.Mock) => fn.mock.calls[0][0];
test("checkbox group chains onChange calls", () => {
test("checkbox group chains onChange calls", async () => {
const onGroupChange = jest.fn();
const onChange = jest.fn();
const value = faker.datatype.string();
const label = faker.datatype.string();
const user = userEvent.setup();
render(
<CheckboxGroup legend="legend" onChange={onGroupChange}>
@@ -20,7 +21,7 @@ test("checkbox group chains onChange calls", () => {
</CheckboxGroup>
);
userEvent.click(screen.getByLabelText(label));
await user.click(screen.getByLabelText(label));
expect(onGroupChange).toBeCalledTimes(1);
expect(onGroupChange).toBeCalledWith([value]);
@@ -36,21 +37,24 @@ describe("Checkbox handles controlled-state correctly", () => {
</CheckboxGroup>
);
test("Checkbox is still checked after click when controlled", () => {
test("Checkbox is still checked after click when controlled", async () => {
const user = userEvent.setup();
render(<CheckboxComponent value={["value1", "value2"]} />);
userEvent.click(screen.getByLabelText("label1"));
userEvent.click(screen.getByLabelText("label2"));
await user.click(screen.getByLabelText("label1"));
await user.click(screen.getByLabelText("label2"));
expect((screen.getByLabelText("label1") as HTMLInputElement).checked).toBe(
true
);
expect((screen.getByLabelText("label2") as HTMLInputElement).checked).toBe(
true
);
});
test("onChange called with expected values", () => {
test("onChange called with expected values", async () => {
const onGroupChange = jest.fn();
const user = userEvent.setup();
render(
<CheckboxComponent
@@ -59,11 +63,11 @@ describe("Checkbox handles controlled-state correctly", () => {
/>
);
userEvent.click(screen.getByLabelText("label1"));
await user.click(screen.getByLabelText("label1"));
expect(onGroupChange).lastCalledWith(["value2"]);
userEvent.click(screen.getByLabelText("label2"));
await user.click(screen.getByLabelText("label2"));
expect(onGroupChange).lastCalledWith(["value1"]);
});
@@ -6,7 +6,7 @@ import { BodyShort, Detail, omit } from "../..";
export interface CheckboxProps
extends Omit<FormFieldProps, "errorId">,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "value"> {
/**
* Checkbox has error
* @default false
@@ -23,7 +23,7 @@ export interface CheckboxProps
/**
* The value of the HTML element.
*/
value?: string;
value?: any;
/**
* Specify whether the Checkbox is in an indeterminate state
* @default false
@@ -55,6 +55,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
"error",
"description",
"hideLabel",
"indeterminate",
])}
{...inputProps}
type="checkbox"
@@ -3,9 +3,9 @@ import cl from "classnames";
import { Fieldset, FieldsetProps, FieldsetContext } from "..";
export interface CheckboxGroupState {
readonly defaultValue?: readonly string[];
readonly value?: readonly string[];
toggleValue(value: string): void;
readonly defaultValue?: readonly any[];
readonly value?: readonly any[];
toggleValue(value: any): void;
}
export const CheckboxGroupContext = createContext<CheckboxGroupState | null>(
@@ -13,7 +13,10 @@ export const CheckboxGroupContext = createContext<CheckboxGroupState | null>(
);
export interface CheckboxGroupProps
extends Omit<FieldsetProps, "onChange" | "errorPropagation"> {
extends Omit<
FieldsetProps,
"onChange" | "errorPropagation" | "defaultValue"
> {
/**
* Checkboxes
*/
@@ -21,15 +24,15 @@ export interface CheckboxGroupProps
/**
* Controlled state for group
*/
value?: string[];
value?: any[];
/**
* Default checked checkboxes on render
*/
defaultValue?: string[];
defaultValue?: any[];
/**
* Returns current checked checkboxes in group
*/
onChange?: (value: string[]) => void;
onChange?: (value: any[]) => void;
}
const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
@@ -39,10 +42,10 @@ const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
) => {
const fieldset = useContext(FieldsetContext);
const [state, setState] = useState<string[]>([]);
const [state, setState] = useState<any[]>(defaultValue ?? []);
const handleChange = (v: string) => {
const newValue = value ? value : state;
const toggleValue = (v: any) => {
const newValue = value ?? state;
const newState = newValue.includes(v)
? newValue.filter((x) => x !== v)
: [...newValue, v];
@@ -65,7 +68,7 @@ const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
value={{
value,
defaultValue,
toggleValue: (value: string) => handleChange(value),
toggleValue,
}}
>
<div className="navds-checkboxes">{children}</div>
@@ -0,0 +1,178 @@
import React, { useState } from "react";
import { Checkbox, CheckboxGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
title: "ds-react/Form/Checkbox",
component: Checkbox,
subcomponents: {
CheckboxGroup,
},
} as Meta;
export const Default = (props) => {
const [state, setState] = useState(["checkbox1"]);
return (
<CheckboxGroup
legend={props.legend}
description={props.description}
value={props.controlled ? state : undefined}
onChange={props.controlled ? setState : undefined}
hideLegend={props.hideLegend}
error={props.errorGroup ? "Errormelding" : undefined}
{...props}
>
<Checkbox
value="checkbox1"
indeterminate={props.indeterminate}
hideLabel={props.hideLabel}
>
{props.children || "Apple"}
</Checkbox>
<Checkbox
value="checkbox2"
error={props.errorSingle}
description={
props.checkboxDescription ? "Orange description" : undefined
}
indeterminate={props.indeterminate}
hideLabel={props.hideLabel}
>
{props.children || "Orange"}
</Checkbox>
<Checkbox
value="checkbox3"
indeterminate={props.indeterminate}
hideLabel={props.hideLabel}
>
{props.children || "Banana"}
</Checkbox>
<Checkbox
value="checkbox4"
indeterminate={props.indeterminate}
hideLabel={props.hideLabel}
>
{props.children || "Melon"}
</Checkbox>
</CheckboxGroup>
);
};
Default.args = {
controlled: false,
legend: "Legend-tekst",
checkboxDescription: false,
hideLegend: false,
errorSingle: false,
children: "",
description: "",
};
export const Group = () => (
<CheckboxGroup legend="Group legend" defaultValue={["tekst2"]}>
<Checkbox value="tekst">Checkboxtekst</Checkbox>
<Checkbox value="tekst2">Checkboxtekst</Checkbox>
</CheckboxGroup>
);
export const GroupError = () => (
<CheckboxGroup
legend="Group legend"
defaultValue={["tekst2"]}
error="Group errormelding"
>
<Checkbox value="tekst">Checkboxtekst</Checkbox>
<Checkbox value="tekst2">Checkboxtekst</Checkbox>
</CheckboxGroup>
);
export const GroupSmall = () => (
<CheckboxGroup legend="Group legend" defaultValue={["tekst2"]} size="small">
<Checkbox value="tekst">Checkboxtekst</Checkbox>
<Checkbox value="tekst2">Checkboxtekst</Checkbox>
</CheckboxGroup>
);
export const GroupDescription = () => (
<CheckboxGroup
legend="Group legend"
defaultValue={["tekst2"]}
description="Group description"
>
<Checkbox value="tekst">Checkboxtekst</Checkbox>
<Checkbox value="tekst2">Checkboxtekst</Checkbox>
</CheckboxGroup>
);
export const Single = () => (
<div className="colspan">
<Checkbox value="tekst">Checkboxtekst</Checkbox>
<Checkbox value="tekst" defaultChecked>
Checkboxtekst
</Checkbox>
</div>
);
export const SingleSmall = () => (
<div className="colspan">
<Checkbox value="tekst" size="small">
Checkboxtekst
</Checkbox>
<Checkbox value="tekst" defaultChecked size="small">
Checkboxtekst
</Checkbox>
</div>
);
export const SingleDescription = () => (
<div className="colspan">
<Checkbox value="tekst" description="checkboxdescription">
Checkboxtekst
</Checkbox>
<Checkbox value="tekst" defaultChecked description="checkboxdescription">
Checkboxtekst
</Checkbox>
</div>
);
export const SingleError = () => (
<div className="colspan">
<Checkbox value="tekst" error>
Checkboxtekst
</Checkbox>
<Checkbox value="tekst" defaultChecked error>
Checkboxtekst
</Checkbox>
</div>
);
export const Indeterminate = () => {
const [checked, setChecked] = useState([true, false]);
return (
<>
<Checkbox
checked={checked[0] && checked[1]}
indeterminate={checked[0] !== checked[1]}
onChange={(e) => setChecked([e.target.checked, e.target.checked])}
>
Parent
</Checkbox>
<div style={{ paddingLeft: "2rem" }}>
<Checkbox
checked={checked[0]}
onChange={(e) => setChecked([e.target.checked, checked[1]])}
>
Child 1
</Checkbox>
<Checkbox
checked={checked[1]}
onChange={(e) => setChecked([checked[0], e.target.checked])}
>
Child 2
</Checkbox>
</div>
</>
);
};
@@ -1,203 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Checkbox, CheckboxGroup } from "../index";
<Meta title="ds-react/form/checkbox/intro" />
# Hvordan ta i bruk Checkbox
```jsx
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
Label å checkbox settes her da med children
## Description
Man kan både sette en description på CheckboxGroup og selve checkbox
```jsx
<CheckboxGroup legend="Culpa cupidatat" description="Exercitation do labore">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## Errors
Feilmeldinger kan bare settes på gruppa
```jsx
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
Enkelt-checkboxer tar en `boolean` error prop
```jsx
<Checkbox value="Apple" error>
Apple
</Checkbox>
```
<Canvas>
<Checkbox value="Apple" error>
Apple
</Checkbox>
</Canvas>
## Sizing
Checkboxer har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
```jsx
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" error="Boksen må være valgt">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## defaultValues
```jsx
<CheckboxGroup legend="Mollit eiusmod" defaultValue={["Orange", "Melon"]}>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" defaultValue={["Orange", "Melon"]}>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## hideLegend
Ved bruk av `hideLegend` på CheckboxGroup kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## hideLabel
Ved bruk av `hideLabel` kan man lettere ta i bruk checkbox internt i eks tabeller.
```jsx
<Checkbox value="Orange" hideLabel>
Orange
</Checkbox>
```
<Canvas>
<Checkbox value="Orange" hideLabel>
Orange
</Checkbox>
</Canvas>
## Disabled
Ved bruk av `disabled` kan man både disabled enkelte checkboxer eller checkboxgruppen.
NOTE: Husk at disabled bør unngås!
```jsx
<CheckboxGroup legend="Mollit eiusmod" disabled>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple" disabled>Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<div>
<CheckboxGroup legend="Mollit eiusmod" disabled>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple" disabled>
Apple
</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</div>
</Canvas>
@@ -1,106 +0,0 @@
import React, { useState } from "react";
import { Checkbox, CheckboxGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
title: "ds-react/form/checkbox",
component: Checkbox,
} as Meta;
export const Indeterminate = () => {
const [checked, setChecked] = useState([true, false]);
return (
<>
<Checkbox
checked={checked[0] && checked[1]}
indeterminate={checked[0] !== checked[1]}
onChange={(e) => setChecked([e.target.checked, e.target.checked])}
>
Parent
</Checkbox>
<div style={{ paddingLeft: "2rem" }}>
<Checkbox
checked={checked[0]}
onChange={(e) => setChecked([e.target.checked, checked[1]])}
>
Child 1
</Checkbox>
<Checkbox
checked={checked[1]}
onChange={(e) => setChecked([checked[0], e.target.checked])}
>
Child 2
</Checkbox>
</div>
</>
);
};
export const All = () => {
const Checkboxes = (props) => (
<CheckboxGroup
legend="Mollit eiusmod"
description="Exercitation do labore"
{...props}
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Banana" description={<div>Laborum ad</div>}>
Banana
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
);
return (
<>
<h1>Checkbox</h1>
<h2>Single checkbox</h2>
<Checkbox value="Apple">Apple</Checkbox>
<h3>Desription</h3>
<Checkbox value="Apple" description="Laborum ad" defaultChecked>
Apple
</Checkbox>
<h3>Error</h3>
<Checkbox value="Apple" error>
Apple
</Checkbox>
<Checkbox value="Apple" error defaultChecked>
Orange
</Checkbox>
<h3>Hide label</h3>
<Checkbox value="Apple" hideLabel description="Laborum ad">
Apple
</Checkbox>
<h3>Disabled</h3>
<Checkbox value="Apple" disabled>
Apple
</Checkbox>
<Checkbox value="Orange" description="Laborum ad" disabled defaultChecked>
Orange
</Checkbox>
<h3>Indeterminate</h3>
<Checkbox value="Apple" indeterminate>
Apple
</Checkbox>
<Checkbox value="Orange" indeterminate size="small">
Orange
</Checkbox>
<h2>Checkbox group</h2>
<Checkboxes />
<h3>Error</h3>
<Checkboxes error="Dette er en feilmelding" />
<h3>Small</h3>
<Checkboxes size="small" />
<h3>Small + error</h3>
<Checkboxes size="small" error="Dette er en feilmelding" />
<h3>Default value</h3>
<Checkboxes defaultValue={["Orange", "Melon"]} />
<h3>Disabled</h3>
<Checkboxes disabled />
</>
);
};
@@ -33,14 +33,14 @@ const useCheckbox = ({ children, ...props }: CheckboxProps) => {
inputProps: {
...inputProps,
checked: checkboxGroup?.value
? checkboxGroup.value.includes(props.value as string)
? checkboxGroup.value.includes(props.value)
: props.checked,
defaultChecked: checkboxGroup?.defaultValue
? checkboxGroup.defaultValue.includes(props.value as string)
? checkboxGroup.defaultValue.includes(props.value)
: props.defaultChecked,
onChange: (e) => {
props.onChange && props.onChange(e);
checkboxGroup && checkboxGroup.toggleValue(props.value as string);
checkboxGroup && checkboxGroup.toggleValue(props.value);
},
},
};
@@ -0,0 +1,42 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { ErrorSummary } from "..";
export default {
title: "ds-react/Form/Errorsummary",
component: ErrorSummary,
argTypes: {
headingTag: {
control: {
type: "text",
},
},
size: {
control: {
type: "radio",
options: ["medium", "small"],
},
},
},
} as Meta;
export const Default = (props) => (
<ErrorSummary
heading="Feiloppsummering komponent"
headingTag={props.headingTag || "h2"}
size={props.size ?? undefined}
>
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
);
export const Small = () => (
<ErrorSummary heading="Feiloppsummering komponent" size="small">
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
);
@@ -1,54 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { ErrorSummary } from "../index";
<Meta title="ds-react/form/errorsummary/intro" />
# Hvordan ta i bruk ErrorSummary
`href` på `ErrorSummary.Item` linker til id som er satt på skjema-elementer.
```jsx
<ErrorSummary heading="Eiusmod est cillum mollit pariatur deserunt">
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
```
<Canvas>
<ErrorSummary heading="Eiusmod est cillum mollit pariatur deserunt">
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
</Canvas>
## Custom headingTag
`headingTag` lar deg sette heading til en annen html-tag en default "h2"
```jsx
<ErrorSummary
heading="Eiusmod est cillum mollit pariatur deserunt"
headingTag="h3"
>
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
```
<Canvas>
<ErrorSummary
heading="Eiusmod est cillum mollit pariatur deserunt"
headingTag="h3"
>
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
</Canvas>
@@ -1,28 +0,0 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { ErrorSummary } from "..";
export default {
title: "ds-react/form/errorsummary",
component: ErrorSummary,
} as Meta;
export const All = () => {
return (
<>
<h1>Error summary</h1>
<ErrorSummary heading="Feiloppsummering komponent" headingTag="h4">
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
<h2>size small</h2>
<ErrorSummary size="small" heading="Feiloppsummering komponent">
<ErrorSummary.Item href="#1">Checkbox må fylles ut</ErrorSummary.Item>
<ErrorSummary.Item href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummary.Item>
</ErrorSummary>
</>
);
};
+1 -1
View File
@@ -10,7 +10,7 @@ export {
FieldsetProps,
} from "./Fieldset";
export { Radio, RadioGroup, RadioGroupProps, RadioProps } from "./radio";
export { SearchField, SearchFieldProps } from "./search-field";
export { Search, SearchProps, SearchClearEvent } from "./search";
export { default as Select, SelectProps } from "./Select";
export { default as Switch, SwitchProps } from "./Switch";
export { ErrorSummary, ErrorSummaryProps } from "./error-summary";
@@ -31,7 +31,9 @@ describe("Controlled RadioGroup", () => {
});
describe("Uncontrolled RadioGroup", () => {
test("handles state correctly", () => {
test("handles state correctly", async () => {
const user = userEvent.setup();
render(<Group />);
const input1 = screen.getByLabelText(label1) as HTMLInputElement;
@@ -40,13 +42,14 @@ describe("Uncontrolled RadioGroup", () => {
expect(input1.checked).toBe(false);
expect(input2.checked).toBe(false);
userEvent.click(screen.getByLabelText(label2));
await user.click(screen.getByLabelText(label2));
expect(input1.checked).toBe(false);
expect(input2.checked).toBe(true);
});
test("handles defaultValue correctly", () => {
test("handles defaultValue correctly", async () => {
const user = userEvent.setup();
render(<Group defaultValue={value1} />);
const input1 = screen.getByLabelText(label1) as HTMLInputElement;
@@ -55,7 +58,7 @@ describe("Uncontrolled RadioGroup", () => {
expect(input1.checked).toBe(true);
expect(input2.checked).toBe(false);
userEvent.click(screen.getByLabelText(label2));
await user.click(screen.getByLabelText(label2));
expect(input1.checked).toBe(false);
expect(input2.checked).toBe(true);
+2 -2
View File
@@ -6,7 +6,7 @@ import { useRadio } from "./useRadio";
export interface RadioProps
extends Omit<FormFieldProps, "error" | "errorId">,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "value"> {
/**
* Label for radio
*/
@@ -14,7 +14,7 @@ export interface RadioProps
/**
* The value of the HTML element
*/
value: string;
value: any;
}
const Radio = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
@@ -5,9 +5,9 @@ import { useId } from "../..";
export interface RadioGroupContextProps {
name: string;
defaultValue?: string;
value?: string;
onChange: (value: string) => void;
defaultValue?: any;
value?: any;
onChange: (value: any) => void;
required?: boolean;
}
@@ -16,7 +16,10 @@ export const RadioGroupContext = React.createContext<RadioGroupContextProps | nu
);
export interface RadioGroupProps
extends Omit<FieldsetProps, "onChange" | "errorPropagation"> {
extends Omit<
FieldsetProps,
"onChange" | "errorPropagation" | "defaultValue"
> {
/**
* Collection of <Radio>-elements
*/
@@ -28,15 +31,15 @@ export interface RadioGroupProps
/**
* Default checked radiobutton
*/
defaultValue?: string;
defaultValue?: any;
/**
* Controlled state for Radiobutton
*/
value?: string;
value?: any;
/**
* Returns current checked radiobutton in group
*/
onChange?: (value: string) => void;
onChange?: (value: any) => void;
/**
* Tells Fieldset if group is required
*/
@@ -0,0 +1,82 @@
import React, { useState } from "react";
import { Radio, RadioGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
title: "ds-react/Form/Radio",
component: Radio,
subcomponents: {
RadioGroup,
},
} as Meta;
export const Default = (props) => {
const [state, setState] = useState("radio1");
return (
<RadioGroup
legend={props.legend}
description={props.description}
value={props.controlled ? state : undefined}
onChange={props.controlled ? setState : undefined}
hideLegend={props.hideLegend}
error={props.errorGroup ? "Errormelding" : undefined}
{...props}
>
<Radio value="radio1">{props.children || "Apple"}</Radio>
<Radio
value="radio2"
description={props.radioDescription ? "Orange description" : undefined}
>
{props.children || "Orange"}
</Radio>
<Radio value="radio3">{props.children || "Banana"}</Radio>
<Radio value="radio4">{props.children || "Melon"}</Radio>
</RadioGroup>
);
};
Default.args = {
controlled: false,
legend: "Legend-tekst",
radioDescription: false,
hideLegend: false,
children: "",
description: "",
};
export const Group = () => (
<RadioGroup legend="Group legend" defaultValue={"tekst2"}>
<Radio value="tekst">Radiotekst</Radio>
<Radio value="tekst2">Radiotekst</Radio>
</RadioGroup>
);
export const GroupError = () => (
<RadioGroup
legend="Group legend"
defaultValue={"tekst2"}
error="Group errormelding"
>
<Radio value="tekst">Radiotekst</Radio>
<Radio value="tekst2">Radiotekst</Radio>
</RadioGroup>
);
export const GroupSmall = () => (
<RadioGroup legend="Group legend" defaultValue={"tekst2"} size="small">
<Radio value="tekst">Radiotekst</Radio>
<Radio value="tekst2">Radiotekst</Radio>
</RadioGroup>
);
export const GroupDescription = () => (
<RadioGroup
legend="Group legend"
defaultValue={"tekst2"}
description="Group description"
>
<Radio value="tekst">Radiotekst</Radio>
<Radio value="tekst2">Radiotekst</Radio>
</RadioGroup>
);
@@ -1,173 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Radio, RadioGroup } from "../index";
<Meta title="ds-react/form/radio/intro" />
# Hvordan ta i bruk Radio
```jsx
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
Label å Radio settes her da med children
## Description
Man kan både sette en description på RadioGroup og selve Radio
```jsx
<RadioGroup legend="Culpa cupidatat" description="Exercitation do labore">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Errors
Feilmeldinger kan bare settes på gruppa
```jsx
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Sizing
Radioknapper har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
```jsx
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" error="Boksen må være valgt">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## defaultValue
```jsx
<RadioGroup legend="Mollit eiusmod" defaultValue="Orange">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" defaultValue="Orange">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## hideLegend
Ved bruk av `hideLegend` på RadioGroup kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<RadioGroup legend="Mollit eiusmod" hideLegend>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" hideLegend>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Disabled
Ved bruk av `disabled` kan man både disabled enkelte Radioer eller Radiogruppen.
NOTE: Husk at disabled bør unngås!
```jsx
<RadioGroup legend="Mollit eiusmod" disabled>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<RadioGroup legend="Mollit eiusmod" >
<Radio value="Apple" disabled>Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<div>
<RadioGroup legend="Mollit eiusmod" disabled>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple" disabled>
Apple
</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</div>
</Canvas>
@@ -1,53 +0,0 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { RadioGroup, Radio } from "../index";
export default {
title: "ds-react/form/radio",
component: RadioGroup,
} as Meta;
export const All = () => {
const Radios = (props) => (
<RadioGroup
legend="Mollit eiusmod"
description={<div>"Exercitation do labore"</div>}
{...props}
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Orange" description={<div>Laborum ad</div>}>
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
);
return (
<>
<h1>Radio group</h1>
<Radios />
<h2>Error</h2>
<Radios error="Dette er en feilmelding" />
<h2>Small</h2>
<Radios size="small" />
<h2>Small + error</h2>
<Radios size="small" error="Dette er en feilmelding" />
<h2>Default value</h2>
<Radios defaultValue="Orange" />
<h2>Disabled</h2>
<RadioGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Radio value="Apple" disabled>
Apple
</Radio>
<Radio value="Orange" description="Laborum ad" disabled>
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>Disabled group</h2>
<Radios disabled />
</>
);
};
@@ -1,132 +0,0 @@
import cl from "classnames";
import React, { forwardRef } from "react";
import { BodyShort, Label, omit } from "../..";
import ErrorMessage from "../ErrorMessage";
import { FormFieldProps, useFormField } from "../useFormField";
import SearchFieldButton, { SearchFieldButtonType } from "./SearchFieldButton";
import SearchFieldClearButton, {
SearchFieldClearButtonType,
} from "./SearchFieldClearButton";
import SearchFieldInput, { SearchFieldInputType } from "./SearchFieldInput";
export interface SearchFieldContextProps {
inputProps: {
id: string;
"aria-invalid": boolean;
"aria-describedby"?: string;
disabled?: boolean;
};
size?: "medium" | "small";
}
export const SearchFieldContext = React.createContext<SearchFieldContextProps | null>(
null
);
export interface SearchFieldProps
extends FormFieldProps,
React.HTMLAttributes<HTMLDivElement> {
/**
* SearchFieldInput & SearchFieldButton
*/
children: React.ReactNode;
/**
* If enabled shows the label and description for screenreaders only
*/
hideLabel?: boolean;
/**
* SearchField label
*/
label: React.ReactNode;
}
interface SearchFieldComponent
extends React.ForwardRefExoticComponent<
SearchFieldProps & React.RefAttributes<HTMLDivElement>
> {
Button: SearchFieldButtonType;
Clear: SearchFieldClearButtonType;
Input: SearchFieldInputType;
}
const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
(props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useFormField(props, "searchfield");
const {
className,
hideLabel,
children,
label,
description,
error,
...rest
} = props;
return (
<div
ref={ref}
{...omit(rest, ["id", "error", "errorId", "size", "disabled"])}
className={cl(
className,
"navds-form-field",
`navds-form-field--${size ?? "medium"}`,
"navds-search-field",
{
"navds-search-field--error": hasError,
"navds-search-field--disabled": !!inputProps.disabled,
}
)}
>
<Label
htmlFor={inputProps.id}
size={size}
as="label"
className={cl("navds-text-field__label", {
"navds-sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
as="div"
className={cl("navds-text-field__description", {
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
<div className="navds-search-field__input-wrapper">
<SearchFieldContext.Provider
value={{
inputProps,
size,
}}
>
{children}
</SearchFieldContext.Provider>
</div>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{error}</ErrorMessage>}
</div>
</div>
);
}
) as SearchFieldComponent;
SearchField.Button = SearchFieldButton;
SearchField.Clear = SearchFieldClearButton;
SearchField.Input = SearchFieldInput;
export default SearchField;
@@ -1,47 +0,0 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { SearchFieldContext } from "./SearchField";
import { Button, ButtonProps } from "../..";
export interface SearchFieldButtonProps extends Omit<ButtonProps, "size"> {
/**
* Button text
* @example <Search /> <span>Søk</span>
*/
children: React.ReactNode;
/**
* Changes design and interactions
* @default "primary"
*/
variant?: "primary" | "secondary";
}
export type SearchFieldButtonType = React.ForwardRefExoticComponent<
SearchFieldButtonProps & React.RefAttributes<HTMLButtonElement>
>;
const SearchFieldButton: SearchFieldButtonType = forwardRef(
({ className, variant = "primary", disabled, ...rest }, ref) => {
const searchField = useContext(SearchFieldContext);
if (searchField === null) {
console.warn("SearchFieldButton has to be wrapped in <SearchField />");
return null;
}
const { size, inputProps } = searchField;
return (
<Button
ref={ref}
className={cl(className, "navds-search-field__button")}
{...rest}
size={size}
variant={variant}
disabled={disabled ?? inputProps?.disabled}
/>
);
}
);
export default SearchFieldButton;
@@ -1,49 +0,0 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { SearchFieldContext } from "./SearchField";
import { Button, ButtonProps } from "../..";
export interface SearchFieldClearButtonProps extends Omit<ButtonProps, "size"> {
/**
* Button text
* @example <Close /> <span>Søk</span>
*/
children: React.ReactNode;
/**
* Changes design and interactions
* @default "secondary"
*/
variant?: "primary" | "secondary";
}
export type SearchFieldClearButtonType = React.ForwardRefExoticComponent<
SearchFieldClearButtonProps & React.RefAttributes<HTMLButtonElement>
>;
const SearchFieldClearButton: SearchFieldClearButtonType = forwardRef(
({ className, variant = "secondary", disabled, ...rest }, ref) => {
const searchField = useContext(SearchFieldContext);
if (searchField === null) {
console.warn(
"SearchFieldClearButton has to be wrapped in <SearchField />"
);
return null;
}
const { size, inputProps } = searchField;
return (
<Button
{...rest}
ref={ref}
className={cl(className, "navds-search-field__clear-button")}
size={size}
variant={variant}
disabled={disabled ?? inputProps?.disabled}
/>
);
}
);
export default SearchFieldClearButton;
@@ -1,42 +0,0 @@
import React, { forwardRef, InputHTMLAttributes, useContext } from "react";
import cl from "classnames";
import { SearchFieldContext } from "./SearchField";
export interface SearchFieldInputProps
extends InputHTMLAttributes<HTMLInputElement> {}
export type SearchFieldInputType = React.ForwardRefExoticComponent<
SearchFieldInputProps & React.RefAttributes<HTMLInputElement>
>;
const SearchFieldInput: SearchFieldInputType = forwardRef(
({ className, ...rest }, ref) => {
const searchField = useContext(SearchFieldContext);
if (searchField === null) {
console.warn("SearchFieldInput has to be wrapped in <SearchField />");
return null;
}
const { size, inputProps } = searchField;
return (
<input
{...rest}
{...inputProps}
type="search"
role="searchbox"
ref={ref}
className={cl(
className,
"navds-search-field__input",
"navds-text-field__input",
"navds-body-short",
`navds-body-${size ?? "medium"}`
)}
/>
);
}
);
export default SearchFieldInput;
@@ -1,2 +0,0 @@
export { default as SearchField, SearchFieldProps } from "./SearchField";
export * from "./SearchField";
@@ -1,25 +0,0 @@
import React, { useState } from "react";
import { Close, Search } from "@navikt/ds-icons";
import { SearchField } from "../index";
export const Example = ({ size = "medium" }: { size: "medium" | "small" }) => {
const [value, setValue] = useState("");
return (
<SearchField size={size} label="Skriv i søkefeltet for å vise clearbutton">
<SearchField.Input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
{!!value && (
<SearchField.Clear onClick={() => setValue("")}>
<Close />
Tøm
</SearchField.Clear>
)}
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
);
};
@@ -1,156 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { SearchField } from "../index";
import { Example } from "./search-field-example.tsx";
import { Search } from "@navikt/ds-icons";
<Meta title="ds-react/form/search-field/intro" />
# Hvordan ta i bruk SearchField
## Viktig
Komponenten er ikke testet eller gått gjennom et design-review, så anbefalses og vente med å ta den i bruk.
## Bruk
```jsx
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
</Canvas>
## hideLabel
`hideLabel` proppen kan brukes for å vise label + description for bare skjermlesere.
Vi har satt `label` som required siden man vil bruke den i sammenheng med denne proppen for bedre UU.
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
</Canvas>
## Sizing
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="small"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="small"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
</Canvas>
## Errors
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
error="Error message"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
error="Error message"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
</Canvas>
## ClearButton
Man kan bruke `SearchField.Clear` for å håndtere clearing av value i `<input />`. For å bruke denne
kreves det da at `SearchField.Input` er controlled slik at man styrer state selv slik som eksemplet under.
Hvis man bare ønsker at den bare skal vises når bruker har begynt å skrive, anbefaler vi bare å rendre
den når inputvalue ikke er empty.
```jsx
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
<SearchField.Input value={value} onChange={(e) => setValue(e.target.value)} />
{!!value && (
<SearchField.Clear onClick={() => setValue("")}>
<Close /> Tøm
</SearchField.Clear>
)}
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
```
<Canvas>
<div>
<Example />
<Example size="small" />
</div>
</Canvas>
@@ -1,199 +0,0 @@
import React, { useState } from "react";
import { Meta } from "@storybook/react/types-6-0";
import { Close, Search } from "@navikt/ds-icons";
import { SearchField } from "../index";
import { Fieldset } from "../..";
export default {
title: "ds-react/form/search-field",
component: SearchField,
} as Meta;
export const All = () => {
const [show, setShow] = useState(false);
return (
<>
<h1>SearchField</h1>
<SearchField
label="Mollit eiusmod"
description={<div>Ea cupidatat eu sunt commodo</div>}
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
<SearchField.Input />
</SearchField>
<h1>SearchField w clearsearch</h1>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField.Input />
<SearchField.Clear>
<Close />
</SearchField.Clear>
<SearchField.Button onClick={() => setShow(!show)}>
<Search /> Søk
</SearchField.Button>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
<SearchField.Clear>
<Close /> Tøm
</SearchField.Clear>
<SearchField.Input />
</SearchField>
<h2>Hidelabel</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
<SearchField.Input />
</SearchField>
<h2>SearchField small</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchField.Button>
<Search />
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
<SearchField.Input />
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchField.Input />
<SearchField.Button>
<Search />
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchField.Button>
<Search />
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
<SearchField.Clear>
<Close /> Tøm
</SearchField.Clear>
<SearchField.Input />
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchField.Input />
<SearchField.Clear>
<Close /> Tøm
</SearchField.Clear>
<SearchField.Button>
<Search />
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
</SearchField>
<h2>SearchField w error</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
>
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
<SearchField.Input />
</SearchField>
<h2>SearchField in Fieldset</h2>
<Fieldset legend="Filter" error="Fieldset-error-msg">
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
hideLabel
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
<SearchField.Input />
</SearchField>
</Fieldset>
<h2>Disabled </h2>
<SearchField
disabled
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
<Fieldset legend="Filter" disabled>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
>
<SearchField.Input />
<SearchField.Button>
<Search /> Søk
</SearchField.Button>
</SearchField>
</Fieldset>
</>
);
};
@@ -0,0 +1,231 @@
import { Close, Search as SearchIcon } from "@navikt/ds-icons";
import cl from "classnames";
import React, {
forwardRef,
InputHTMLAttributes,
useCallback,
useRef,
useState,
} from "react";
import mergeRefs from "react-merge-refs";
import { BodyShort, Label, omit, useEventListener } from "../..";
import { FormFieldProps } from "../useFormField";
import SearchButton, { SearchButtonType } from "./SearchButton";
import { useSearch } from "./useSearch";
export type SearchClearEvent =
| {
trigger: "Click";
event: React.MouseEvent<HTMLButtonElement, MouseEvent>;
}
| { trigger: "Escape"; event: React.KeyboardEvent<HTMLDivElement> };
export interface SearchProps
extends Omit<FormFieldProps, "error" | "errorId">,
Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange"> {
children?: React.ReactNode;
/**
* Search label
* @info Will be hidden by default, is required for accessibility reasons.
*/
label: React.ReactNode;
/**
* Shows label and description for screenreaders-only
* @default true
*/
hideLabel?: boolean;
/**
* Callback for value-change in input
*/
onChange?: (value: string) => void;
/**
* Callback for <Search.Button/> click or onSubmit in form
*/
onSearch?: (value: string | number | readonly string[]) => void;
/**
* Callback for click on clear-button or Escape keydown
*/
onClear?: (e: SearchClearEvent) => void;
/**
* aria-label on clear button
* @default "Tøm"
*/
clearButtonLabel?: string;
/**
* If false, removes clear-button option from input.
* @default true
*/
clearButton?: boolean;
/**
* Changes button-variant
* @default "primary"
*/
variant?: "primary" | "secondary" | "simple";
}
interface SearchComponent
extends React.ForwardRefExoticComponent<
SearchProps & React.RefAttributes<HTMLDivElement>
> {
Button: SearchButtonType;
}
export interface SearchContextProps {
disabled?: boolean;
size: "medium" | "small";
variant: "primary" | "secondary" | "simple";
onSearch: () => void;
}
export const SearchContext = React.createContext<SearchContextProps | null>(
null
);
const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
const { inputProps, size = "medium", inputDescriptionId } = useSearch(
props,
"searchfield"
);
const {
className,
hideLabel = true,
label,
description,
value,
clearButtonLabel,
onClear,
clearButton = true,
children,
onSearch,
variant = "primary",
defaultValue,
onChange,
...rest
} = props;
const searchRef = useRef<HTMLInputElement | null>(null);
const mergedRef = mergeRefs([searchRef, ref]);
const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
const handleChange = useCallback(
(v: string) => {
value === undefined && setInternalValue(v);
onChange?.(v);
},
[onChange, value]
);
const handleClear = useCallback(
(event: SearchClearEvent) => {
onClear?.(event);
handleChange("");
searchRef.current && searchRef.current?.focus?.();
},
[handleChange, onClear]
);
useEventListener(
"keydown",
useCallback(
(e) => {
if (e.key === "Escape") {
e.preventDefault();
handleClear({ trigger: "Escape", event: e });
}
},
[handleClear]
),
wrapperRef
);
return (
<div
ref={setWrapperRef}
className={cl(
className,
"navds-form-field",
`navds-form-field--${size}`,
"navds-search",
{
"navds-search--disabled": !!inputProps.disabled,
}
)}
>
<Label
htmlFor={inputProps.id}
size={size}
as="label"
className={cl("navds-text-field__label", {
"navds-sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
as="div"
className={cl("navds-text-field__description", {
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
<div className="navds-search__wrapper">
<div className="navds-search__wrapper-inner">
{variant === "simple" && (
<SearchIcon aria-hidden className="navds-search__search-icon" />
)}
<input
ref={mergedRef}
{...omit(rest, ["size"])}
{...inputProps}
value={value ?? internalValue}
onChange={(e) => handleChange(e.target.value)}
type="search"
role="searchbox"
className={cl(
className,
"navds-search__input",
`navds-search__input--${variant}`,
"navds-text-field__input",
"navds-body-short",
`navds-body-${size}`
)}
/>
{(value ?? internalValue) && clearButton && (
<button
type="button"
onClick={(e) => handleClear({ trigger: "Click", event: e })}
className="navds-search__button-clear"
>
<span className="navds-sr-only">
{clearButtonLabel ? clearButtonLabel : "Tøm"}
</span>
<Close aria-hidden />
</button>
)}
</div>
<SearchContext.Provider
value={{
size,
disabled: inputProps.disabled,
variant,
onSearch: () => onSearch?.(value ?? internalValue),
}}
>
{children ? children : variant !== "simple" && <SearchButton />}
</SearchContext.Provider>
</div>
</div>
);
}) as SearchComponent;
Search.Button = SearchButton;
export default Search;
@@ -0,0 +1,51 @@
import { Search } from "@navikt/ds-icons";
import cl from "classnames";
import React, { forwardRef, useContext } from "react";
import { Button, ButtonProps } from "../..";
import { SearchContext } from "./Search";
export interface SearchButtonProps
extends Omit<ButtonProps, "size" | "children" | "variant"> {
/**
* Text set before <Search/> icon
*/
children?: React.ReactNode;
}
export type SearchButtonType = React.ForwardRefExoticComponent<
SearchButtonProps & React.RefAttributes<HTMLButtonElement>
>;
const SearchButton: SearchButtonType = forwardRef(
({ className, children, disabled, onClick, ...rest }, ref) => {
const context = useContext(SearchContext);
if (context === null) {
console.warn("<Search.Button> has to be wrapped in <Search />");
return null;
}
const { size, variant, onSearch } = context;
return (
<Button
type="submit"
{...rest}
ref={ref}
size={size}
variant={variant === "secondary" ? "secondary" : "primary"}
className={cl("navds-search__button-search", className)}
disabled={context?.disabled ?? disabled}
onClick={(e) => {
onSearch?.();
onClick?.(e);
}}
>
<Search aria-hidden />
{children ? children : <span className="navds-sr-only">Søk</span>}
</Button>
);
}
);
export default SearchButton;
@@ -0,0 +1 @@
export { default as Search, SearchProps, SearchClearEvent } from "./Search";
@@ -0,0 +1,142 @@
import { Meta } from "@storybook/react/types-6-0";
import React, { useState } from "react";
import { Search } from "../index";
export default {
title: "ds-react/Form/Search",
component: Search,
argTypes: {
clearButton: {
control: {
type: "boolean",
},
},
size: {
control: {
type: "radio",
options: ["medium", "small"],
},
},
variant: {
control: {
type: "radio",
options: ["primary", "secondary", "simple"],
},
},
},
} as Meta;
export const Default = (props) => {
const [state, setState] = useState("");
return (
<div data-theme={props.darkmode ? "dark" : "light"}>
<Search
value={props.controlled ? state : undefined}
onChange={props.controlled ? setState : null}
onSearch={(v) => console.log({ onSearch: v })}
label="Søk"
size={props.size}
clearButton={props.clearButton}
variant={props.variant}
hideLabel={props.hideLabel}
/>
</div>
);
};
Default.args = {
controlled: false,
darkmode: false,
hideLabel: true,
};
export const Small = () => (
<div className="rowgap">
<div className="colgap">
<Search label="Søk" size="small" />
<Search label="Søk" variant="secondary" size="small" />
<Search label="Søk" variant="simple" size="small" />
</div>
<div className="colgap" data-theme="dark">
<Search label="Søk" size="small" />
<Search label="Søk" variant="secondary" size="small" />
<Search label="Søk" variant="simple" size="small" />
</div>
</div>
);
export const Variants = () => (
<div className="rowgap">
<div className="colgap">
<Search label="Søk" />
<Search label="Søk" variant="secondary" />
<Search label="Søk" variant="simple" />
</div>
<div className="colgap" data-theme="dark">
<Search label="Søk" />
<Search label="Søk" variant="secondary" />
<Search label="Søk" variant="simple" />
</div>
</div>
);
export const Placeholder = () => (
<div className="rowgap">
<div className="colgap">
<Search label="Søk" placeholder="Søk" />
</div>
<div className="colgap" data-theme="dark">
<Search label="Søk" placeholder="Søk" />
</div>
</div>
);
export const Text = () => (
<div className="rowgap">
<div className="colgap">
<Search label="Søk" value="Søketekst" />
<Search label="Søk" variant="secondary" value="Søketekst" />
<Search label="Søk" variant="simple" value="Søketekst" />
</div>
<div className="colgap" data-theme="dark">
<Search label="Søk" value="Søketekst" />
<Search label="Søk" variant="secondary" value="Søketekst" />
<Search label="Søk" variant="simple" value="Søketekst" />
</div>
</div>
);
export const WLabel = () => (
<div className="rowgap">
<div className="colgap">
<Search label="Label søk" variant="simple" hideLabel={false} />
<Search
label="Label søk"
description="Description søk"
variant="simple"
hideLabel={false}
/>
</div>
<div className="colgap" data-theme="dark">
<Search label="Label søk" variant="simple" hideLabel={false} />
<Search
label="Label søk"
description="Description søk"
variant="simple"
hideLabel={false}
/>
</div>
</div>
);
export const NoClearButton = () => (
<div className="colgap">
<Search label="Label søk" clearButton={false} value="søketekst" />
<Search
label="Label søk"
variant="simple"
clearButton={false}
value="søketekst"
/>
</div>
);
@@ -0,0 +1,31 @@
import cl from "classnames";
import { useContext } from "react";
import { useId } from "../../index";
import { FieldsetContext } from "../index";
import { FormFieldProps } from "../useFormField";
export const useSearch = (props: FormFieldProps, prefix: string) => {
const { size } = props;
const fieldset = useContext(FieldsetContext);
const genId = useId();
const id = props.id ?? `${prefix}-${genId}`;
const inputDescriptionId = `${prefix}-description-${genId}`;
const disabled = fieldset?.disabled || props.disabled;
return {
inputDescriptionId,
size: size ?? fieldset?.size ?? "medium",
inputProps: {
id,
"aria-describedby":
cl(props["aria-describedby"], {
[inputDescriptionId]: !!props?.description,
}) || undefined,
disabled,
},
};
};
@@ -1,12 +1,12 @@
.navds-story-cell {
border-radius: 0.25rem;
border-radius: var(--navds-border-radius-medium);
background: white;
padding: 1rem;
}
.navds-story-content-container {
display: flex;
border-radius: 0.25rem;
border-radius: var(--navds-border-radius-medium);
justify-content: center;
align-items: center;
margin-bottom: 1.5rem;
+11 -23
View File
@@ -1,6 +1,6 @@
import { Helptext as HelpTextIcon } from "@navikt/ds-icons";
import cl from "classnames";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import React, { forwardRef, useRef, useState } from "react";
import mergeRefs from "react-merge-refs";
import { Popover, PopoverProps } from "..";
@@ -21,53 +21,41 @@ const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
placement = "top",
strategy = "absolute",
title = "hjelp",
onClick,
...rest
},
ref
) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
const mergedRef = mergeRefs([buttonRef, ref]);
const [popoverRef, setPopoverRef] = useState<HTMLDivElement | null>(null);
const wrapperRef = useRef<HTMLDivElement | null>(null);
const [open, setOpen] = useState(false);
useEffect(() => {
open && popoverRef?.focus?.();
}, [open, popoverRef]);
const handleClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
setOpen((x) => !x);
rest.onClick && rest.onClick(e);
};
return (
<div className="navds-help-text" ref={wrapperRef}>
<div className="navds-help-text">
<button
{...rest}
ref={mergedRef}
onClick={(e) => handleClick(e)}
onClick={(e) => {
setOpen((x) => !x);
onClick?.(e);
}}
className={cl(className, "navds-help-text__button")}
type="button"
aria-expanded={open}
aria-haspopup="dialog"
title={title}
>
<HelpTextIcon className="navds-help-text__icon" />
<span className="navds-sr-only">{title}</span>
<HelpTextIcon className="navds-help-text__icon" title={title} />
</button>
<Popover
ref={setPopoverRef}
onClose={() => setOpen(false)}
className="navds-help-text__popover"
open={open}
role="tooltip"
anchorEl={buttonRef.current}
placement={placement}
strategy={strategy}
>
<Popover.Content>{children}</Popover.Content>
<Popover.Content className="navds-body-short">
{children}
</Popover.Content>
</Popover>
</div>
);
@@ -0,0 +1,28 @@
import React from "react";
import { TextField, HelpText } from "..";
export default {
title: "ds-react/help-text",
component: HelpText,
};
export const All = () => {
return (
<>
<h1>HelpText</h1>
<HelpText title="show tooltip">
Id ullamco excepteur elit fugiat labore.
</HelpText>
<TextField
label={
<div style={{ display: "flex", gap: 8 }}>
Text field label
<HelpText title="show tooltip">
Id ullamco excepteur elit fugiat labore.
</HelpText>
</div>
}
></TextField>
</>
);
};
@@ -1,35 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { HelpText } from "../../index";
import { Success } from "@navikt/ds-react";
<Meta title="ds-react/help-text/intro" />
# Hvordan ta i bruk HelpText
```jsx
<HelpText>Exercitation esse minim esse mollit ex magna.</HelpText>
```
<Canvas>
<div style={{ padding: "5rem" }}>
<HelpText>Exercitation esse minim esse mollit ex magna.</HelpText>
</div>
</Canvas>
# Egen title
Husk å endre på "title" slik at skjermlesere får tydeligere informasjon
```jsx
<HelpText title="vis hjelpetekst angående søknad">
Exercitation esse minim esse mollit ex magna.
</HelpText>
```
<Canvas>
<div style={{ padding: "5rem" }}>
<HelpText title="vis hjelpetekst angående søknad">
Exercitation esse minim esse mollit ex magna.
</HelpText>
</div>
</Canvas>
Loaded 100 of 173 files, more files were not shown because too many files have changed in this diff. Show more