Compare commits

..
Author SHA1 Message Date
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
github-actions[bot] 00259c629b Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.7
 - @navikt/ds-react-internal@0.11.7
2022-02-16 14:18:21 +00:00
Ken 6124812ba8 [FIX] Bedre alt-tekster for ikoner i Alert (#1425) 2022-02-16 15:10:33 +01:00
github-actions[bot] 5f6bd160d6 Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.6
 - @navikt/ds-react-internal@0.11.6
2022-02-14 09:49:45 +00:00
Andreas Nordahl b876ffb607 [fix] add specific table types (#1422) 2022-02-14 10:42:08 +01:00
Ken 6886cf7a67 Delay on button-story for chromatic (#1417) 2022-02-11 13:03:43 +01:00
github-actions[bot] a9e58e7bb2 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.3
2022-02-11 08:22:17 +00:00
Ken 861803f5ae [fix] hover farge-fix (#1418) 2022-02-11 09:15:12 +01:00
github-actions[bot] 5d383b754f Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.4
 - @navikt/ds-react@0.16.5
 - @navikt/ds-react-internal@0.11.5
2022-02-10 15:23:35 +00:00
Andreas Nordahl a8dc377870 [fix] update icons (#1416) 2022-02-10 16:15:16 +01:00
github-actions[bot] ead0378644 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.3
 - @navikt/ds-react@0.16.4
 - @navikt/ds-react-internal@0.11.4
2022-02-08 15:50:02 +00:00
KenandKenAJoh 10a6bc18c4 [FIX] Ikonsynk Figma (#1414)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2022-02-08 16:42:29 +01:00
github-actions[bot] 68d4b60f0e Lerna versionbump [ci skip]
- @navikt/ds-react@0.16.3
 - @navikt/ds-react-internal@0.11.3
2022-02-08 15:11:06 +00:00
Karl O 106e37bc54 [FIX] allow passing aria props to react-modal in modal (#1412) 2022-02-08 16:02:50 +01:00
github-actions[bot] 78080293d3 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.2
 - @navikt/ds-react@0.16.2
 - @navikt/ds-react-internal@0.11.2
2022-02-08 13:03:24 +00:00
KenandKenAJoh d511210582 [fix] Ikoner synket fra figma (#1411)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2022-02-08 13:55:36 +01:00
github-actions[bot] 78b103bb3e Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.2
2022-02-08 10:36:10 +00:00
Ken 9c78338164 [fix] fikset tokens css (#1410) 2022-02-08 11:29:01 +01:00
github-actions[bot] 08c9069879 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.1
 - @navikt/ds-react@0.16.1
 - @navikt/ds-tailwind@0.1.2
 - @navikt/ds-react-internal@0.11.1
2022-02-07 13:05:59 +00:00
Ken 3ab1645994 [fix] fjernet failed import i typo story 2022-02-07 13:49:10 +01:00
Ken a64fc8905d fikset tailwind versjon 2022-02-07 13:40:53 +01:00
Ken 5d83818c1b yarn lock 2022-02-07 13:40:53 +01:00
github-actions[bot] 1148825a99 Lerna versionbump [ci skip]
- @navikt/ds-css@0.15.0
 - @navikt/ds-react@0.16.0
 - @navikt/ds-react-internal@0.11.0
2022-02-07 12:32:00 +00:00
Ken 778b1a4932 [FEATURE] Fjernet 2xlarge Heading, mobilskalering (#1401) 2022-02-07 13:24:18 +01:00
github-actions[bot] 74b77c0bba Lerna versionbump [ci skip]
- @navikt/ds-css@0.14.2
 - @navikt/ds-tailwind@0.1.1
 - @navikt/ds-tokens@0.8.1
2022-02-07 11:37:49 +00:00
Ken 5fc4ea483d [FIX] Tailwind config i ds-tokens (#1397)
* satt opp filstruktur

* json fil med formaterte tokens

* forenklet build

* satt opp data for tailwind

* la til gitignore

* fikset gitignore

* colors test

* ferdig tailwind config

* satt opp gitignore

* slettet git fil

* flyttet gitignore

* flettet tw.config

* comments

* fikset var prefix

* oppdatert build-script

* tailwind pakke

* flyttet tailwind pakke

* fjernet npmignore

* oppdatert src i package json

* fikset config

* flyttet theme under extended

* fjernet console.log

* fikset tsconfig?

* flyttet colors ut av extend

* tsconfig fix v ts-ignore

* sikrer riktig bygg-rekkefølge

* force token build
2022-02-07 12:30:21 +01:00
github-actions[bot] d002c03647 Lerna versionbump [ci skip]
- @navikt/ds-react@0.15.3
 - @navikt/ds-react-internal@0.10.3
2022-02-02 11:41:48 +00:00
larseirikhansen da1ffe8318 [FIX] HelpText Popover scroll (#1406)
* FIX: HelpText Popover scroll

* edge case in case focus() does not exist on ref
2022-02-02 12:33:23 +01:00
github-actions[bot] 0128f5a467 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.8.1
 - @navikt/ds-react@0.15.2
 - @navikt/ds-react-internal@0.10.2
2022-01-31 14:20:25 +00:00
KenandKenAJoh 0a61ab629a [FIX] Ikonsynk Figma (#1405)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2022-01-31 15:13:25 +01:00
github-actions[bot] 4ea5face0c Lerna versionbump [ci skip]
- @navikt/ds-css@0.14.1
 - @navikt/ds-react@0.15.1
 - @navikt/ds-react-internal@0.10.1
2022-01-28 11:54:39 +00:00
Andreas NordahlandKen 248a83221a [fix] Indeterminate checkbox (#1404)
* functional

* styles

* flyttet global token til root

Co-authored-by: Ken <ken.aleksander@gmail.com>
2022-01-28 12:47:01 +01:00
github-actions[bot] eceaa7e659 Lerna versionbump [ci skip]
- @navikt/ds-css@0.14.0
 - @navikt/ds-icons@0.8.0
 - @navikt/ds-react@0.15.0
 - @navikt/ds-react-internal@0.10.0
2022-01-28 09:24:05 +00:00
KenandAndreas Nordahl 811c0024c5 [FEATURE] AccordionMenu -> Menu
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-01-28 10:17:16 +01:00
Andreas Nordahl aaefaddb13 Purge doc stories (#1403) 2022-01-27 17:31:53 +01:00
github-actions[bot] f464347f6e Lerna versionbump [ci skip]
- @navikt/ds-css@0.13.0
 - @navikt/ds-tokens@0.8.0
2022-01-27 09:54:20 +00:00
github-actions[bot]andKenAJoh 6608d01c1e [FEATURE] Tokens sync Figma (#1402)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2022-01-27 10:47:08 +01:00
github-actions[bot] 335bc62922 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.14
 - @navikt/ds-react@0.14.15
 - @navikt/ds-react-internal@0.9.15
2022-01-22 17:20:09 +00:00
Ken 3c230d8f4c [FIX] Accordion: Figma 3.0 Beta sync (#1390) 2022-01-22 18:12:10 +01:00
Ken 5bb7de3b4c [ci skip] readme link fix 2022-01-22 18:09:47 +01:00
github-actions[bot] 9597c24328 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.13
 - @navikt/ds-react@0.14.14
 - @navikt/ds-react-internal@0.9.14
2022-01-21 13:57:29 +00:00
Ken 2642c2914e [FIX] loading-state på Switch bli nå disabled (#1396) 2022-01-21 14:50:02 +01:00
github-actions[bot] 74d0b0cf1f Lerna versionbump [ci skip]
- @navikt/ds-icons@0.7.3
 - @navikt/ds-react@0.14.13
 - @navikt/ds-react-internal@0.9.13
2022-01-21 13:29:24 +00:00
Ken 55ca4d26a7 [FIX] Oppdatert ikoner og bygg (#1394) 2022-01-21 14:21:14 +01:00
github-actions[bot] 474ea81bbd Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.12
 - @navikt/ds-react@0.14.12
 - @navikt/ds-react-internal@0.9.12
2022-01-21 08:44:31 +00:00
Ken ae8ee87897 [FIX] sr-only -> navds-sr-only (#1393) 2022-01-21 09:37:17 +01:00
Ken ecf96dac16 [ci skip] oppdatert contributing 2022-01-19 10:12:07 +01:00
Ken 982e1dce2c [ci skip] contributors i readme 2022-01-19 09:58:41 +01:00
Ken f910ca1c15 Update README.md 2022-01-18 19:41:57 +01:00
Ken 1c161d1403 [ci skip] Legger til enringslogg-lenke i Readme 2022-01-18 19:21:34 +01:00
Ken 279c89195e Update CHANGELOG.md 2022-01-18 19:17:48 +01:00
github-actions[bot] 260085f026 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.11
2022-01-18 14:04:13 +00:00
Ken c70a3a78e8 [FIX] Textfield: CSS-sync med figma 3.0 beta (#1391) 2022-01-18 14:56:06 +01:00
github-actions[bot] 236feb37e8 Lerna versionbump [ci skip]
- @navikt/ds-react@0.14.11
 - @navikt/ds-react-internal@0.9.11
2022-01-17 18:45:21 +00:00
Ken 29ea9f4cb3 [FIX] Modal: optional closebutton, button variant="tertiary" (#1389) 2022-01-17 19:37:51 +01:00
github-actions[bot] ebb04c4a56 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.10
 - @navikt/ds-react@0.14.10
 - @navikt/ds-react-internal@0.9.10
2022-01-17 14:30:00 +00:00
438c844221 [fix] Add loading state for Button component (#1376) (#1383)
* Add loading state for Button component (#1376)

* add loading prop

* hide content when loading, spinner not centered

* change button loading state with useEffect

* add button component back in

* use a new ref

* add variants for loader buttons

* set loading in state

* add toggle button

* add toggle button

* hide small buttons

* add description for isLoading prop

* move story section to bottom

* destructure imports

* use react-merge-refs

* import useState

* refactor

* refactor

* only set boolean in state

* remove width style when loader removed

* fix slight movement due to rounding width

* adjust loader size to button

* fix button width logic

* useLayoutEffect instead of useEffect for button with handling

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

* loading button is now disabled. also aria-live=polite

* loading button in story toggles loading

* remove aria-live prop

* rename isLoading to be consistent with Switch

* Update @navikt/core/react/src/button/Button.tsx

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

* move button specific loader style

* stories

* aria-live is back

Co-authored-by: Bjørn Harbo Dahle <bdahle@hey.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2022-01-17 15:22:12 +01:00
Ken 656de64a4d [ci skip] Oppdatert Storybook, bedre dev-løsning (#1388) 2022-01-17 12:58:03 +01:00
dependabot[bot] 777f3ec95b Bump follow-redirects from 1.14.6 to 1.14.7 (#1385)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 10:42:43 +01:00
github-actions[bot] adebf90f68 Lerna versionbump [ci skip]
- @navikt/ds-react@0.14.9
 - @navikt/ds-css-internal@0.7.1
 - @navikt/ds-react-internal@0.9.9
2022-01-14 11:02:32 +00:00
Andreas Nordahl 77fc400688 [fix] disabled dropdown item style (#1387) 2022-01-14 11:54:56 +01:00
Ken 004dfb90f1 fikset console errors i Switch 2022-01-14 09:22:31 +01:00
github-actions[bot] 327c92131b Lerna versionbump [ci skip]
- @navikt/ds-react@0.14.8
 - @navikt/ds-react-internal@0.9.8
2022-01-13 14:59:04 +00:00
Ken 6b1f395df8 [FIX] Kan endre posisjonerings-strategi for Popover (#1386) 2022-01-13 15:51:16 +01:00
github-actions[bot] 381adf6cb1 Lerna versionbump [ci skip]
- @navikt/ds-react@0.14.7
 - @navikt/ds-react-internal@0.9.7
2022-01-13 10:42:48 +00:00
Ken 47ef162268 [FIX] aria-hidden på LinkPanel ikon (#1384) 2022-01-13 11:34:42 +01:00
github-actions[bot] d9359d1a86 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.9
 - @navikt/ds-react@0.14.6
 - @navikt/ds-react-internal@0.9.6
2022-01-11 11:08:28 +00:00
Ken b08d922689 [FIX] Oppdatert Switch design (#1380) 2022-01-11 12:01:11 +01:00
github-actions[bot] 3db81c9b79 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.8
 - @navikt/ds-react@0.14.5
 - @navikt/ds-react-internal@0.9.5
2022-01-10 13:53:12 +00:00
Andreas NordahlandKen be26724b07 [fix] aria-hidden on select chevron (#1379)
* aria-hidden on select chevron

* Update @navikt/core/react/src/form/Select.tsx

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

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2022-01-10 14:44:34 +01:00
95ac6ebf3c [FIX] StepIndicator (Stegindikator) for ds-react/ds-css (#1361)
* Stegindikator migrering (#1352)

Co-authored-by: bdahle <bdahle@hey.com>

* satt opp stepindicator med step

* oppdatert stepindicator api

* påbegynt styling av step-indicator

* lint fix

* oppdatert step-indicator

* refactored css completely

* fikset text-decoration for hover state

* fjernet autoresponsive prop

* mdx story for step-indicator

* implemenetert autoResponsive

* renamet autoRepsonsive -> responsive

* fikset responsive dok

* interaktivt step-indicator story

* flyttet tokens opp til root i css

* syntax fix

* router story and onChange optional

* oopsie

* Opprydding i Repo, flytting av gammel kode til nytt repo (#1372)

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

* [FEATURE] Fix icon names (#1375)

* [ci skip] update readme

* bedre disabled handling, mindre number med samme klikkflate

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: bdahle <bdahle@hey.com>
2022-01-07 11:48:33 +01:00
164 changed files with 8472 additions and 4725 deletions

No files matched your search

+11 -1
View File
@@ -1,10 +1,16 @@
const getStories = () => {
return process.env.stories
? [`../@navikt/**/${process.env.stories}.stories.@(js|jsx|ts|tsx|mdx)`]
: ["../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)"];
};
module.exports = {
webpackFinal: async (config, { configType }) => {
config.devServer = { stats: "errors-only" };
return config;
},
devServer: { stats: "errors-only" },
stories: ["../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)"],
stories: () => getStories(),
addons: [
"@storybook/addon-docs",
"@storybook/addon-a11y",
@@ -24,4 +30,8 @@ module.exports = {
},
},
],
core: {
builder: "webpack5",
},
staticDirs: ["./public"],
};
+5
View File
@@ -1,5 +1,10 @@
import "@navikt/ds-css/index.css";
import "@navikt/ds-css-internal/index.css";
import { initialize, mswDecorator } from "msw-storybook-addon";
initialize();
export const decorators = [mswDecorator];
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
+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);
});
}
-105
View File
@@ -1,105 +0,0 @@
:root {
--navds-accordion-menu-color-text: var(--navds-semantic-color-link);
--navds-accordion-menu-color-text-focus: var(--navds-semantic-color-text);
--navds-accordion-menu-color-background-hover: var(
--navds-global-color-blue-50
);
--navds-accordion-menu-color-text-active: var(--navds-semantic-color-text);
--navds-accordion-menu-outline-focus: var(--navds-semantic-color-focus);
}
.navds-accordion-menu__list {
list-style: none;
margin: 0;
padding: 0;
font-weight: var(--navds-font-weight-bold);
}
.navds-accordion-menu-collapsable__button {
cursor: pointer;
background-color: transparent;
border: none;
font: inherit;
text-align: inherit;
margin: 0;
padding: 0;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: var(--navds-font-weight-bold);
color: var(--navds-accordion-menu-color-text);
text-decoration: underline;
}
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable__button {
display: flex;
padding: var(--navds-spacing-3) var(--navds-spacing-4);
text-decoration: none;
}
.navds-accordion-menu-collapsable__expand-icon {
font-size: 1.5rem;
color: var(--navds-accordion-menu-color);
flex-shrink: 0;
margin-left: var(--navds-spacing-2);
}
.navds-accordion-menu-collapsable--open
> .navds-accordion-menu-collapsable__button
> .navds-accordion-menu-collapsable__expand-icon {
transform: rotate(180deg);
}
.navds-accordion-menu-collapsable .navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-8);
}
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-12);
}
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-16);
}
.navds-accordion-menu-item:focus,
.navds-accordion-menu-collapsable__button:focus {
outline: 3px solid var(--navds-accordion-menu-outline-focus);
outline-offset: -3px;
color: var(--navds-accordion-menu-color-text-focus);
}
.navds-accordion-menu-collapsable__button:focus
> .navds-accordion-menu-collapsable__expand-icon {
color: var(--navds-accordion-menu-color-focus);
}
.navds-accordion-menu-item:hover,
.navds-accordion-menu-collapsable__button:hover {
background-color: var(--navds-accordion-menu-color-background-hover);
}
.navds-accordion-menu-item--active {
box-shadow: inset 0.5rem 0 var(--navds-semantic-color-link);
color: var(--navds-accordion-menu-color-text-active);
text-decoration: none;
}
+46 -24
View File
@@ -4,11 +4,16 @@
---navds-semantic-color-component-background-light
);
--navds-accordion-color-text-hover: var(--navds-semantic-color-link);
--navds-accordion-color-border: var(--navds-semantic-color-border-muted);
--navds-accordion-color-border-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-accordion-color-border-focus: var(
---navds-semantic-color-component-background-light
--navds-accordion-color-text-open: var(--navds-semantic-color-text);
--navds-accordion-color-text-open-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-accordion-color-background-open: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
}
@@ -20,16 +25,53 @@
background: var(--navds-accordion-color-background);
}
.navds-accordion__header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--navds-spacing-4);
padding: var(--navds-spacing-4) var(--navds-spacing-3);
margin: 0;
text-align: left;
background: transparent;
cursor: pointer;
border: none;
border-bottom: 2px solid var(--navds-accordion-color-border);
}
.navds-accordion__header:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
border-color: var(--navds-accordion-color-border-focus);
}
.navds-accordion__header:hover {
color: var(--navds-accordion-color-text-hover);
border-color: var(--navds-accordion-color-border-hover);
text-decoration: underline;
}
.navds-accordion__item--open > .navds-accordion__header {
background-color: var(--navds-accordion-color-background-open);
color: var(--navds-accordion-color-text-open);
border-color: transparent;
}
.navds-accordion__item--open > .navds-accordion__header:hover {
border-color: transparent;
color: var(--navds-accordion-color-text-open-hover);
}
.navds-accordion__content {
color: var(--navds-accordion-color-text);
padding: var(--navds-spacing-5) var(--navds-spacing-3) var(--navds-spacing-10);
border-bottom: 2px solid var(--navds-accordion-color-border);
}
.navds-accordion__item--open
> .navds-accordion__header:hover
+ *
.navds-accordion__content {
border-color: var(--navds-accordion-color-border-hover);
}
.navds-accordion__expand-icon {
@@ -42,26 +84,6 @@
transform: rotateZ(180deg);
}
.navds-accordion__header {
padding: var(--navds-spacing-4) var(--navds-spacing-3);
background: transparent;
text-align: left;
border: none;
width: 100%;
margin: 0;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #a0a0a0;
gap: var(--navds-spacing-4);
}
.navds-accordion__content {
color: var(--navds-accordion-color-text);
padding: var(--navds-spacing-5) var(--navds-spacing-3) var(--navds-spacing-10);
}
.navds-accordion__expand-icon--filled {
display: none;
}
+24 -3
View File
@@ -74,6 +74,10 @@
--navds-button-color-danger-border-focus: var(
--navds-semantic-color-component-background-light
);
/* Loader */
--navds-loader-color-on-button-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-on-button-foreground: currentColor;
}
.navds-button {
@@ -95,6 +99,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);
@@ -111,7 +120,8 @@
font-size: 1.5rem;
}
.navds-button--small svg {
.navds-button--small svg,
.navds-button--xsmall svg {
font-size: 1.25rem;
}
@@ -255,7 +265,18 @@
**************************/
.navds-button:disabled {
opacity: 0.3;
cursor: not-allowed;
transform: none;
}
.navds-button:disabled:not(.navds-button--loading) {
opacity: 0.3;
}
.navds-button .navds-loader .navds-loader__foreground {
stroke: var(--navds-loader-color-on-button-foreground);
}
.navds-button--primary .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
+1 -1
View File
@@ -14,7 +14,7 @@
}
/* Applied when hideLegend is applied to fieldset */
.navds-fieldset > .sr-only + :not(:first-child):not(:empty) {
.navds-fieldset > .navds-sr-only + :not(:first-child):not(:empty) {
margin-top: 0;
}
+2 -2
View File
@@ -4,7 +4,7 @@
}
/* Applied when hideLabel is applied to form-element */
.navds-form-field > .sr-only + :not(:first-child):not(:empty),
.navds-form-field > .sr-only + input:not(:first-child) {
.navds-form-field > .navds-sr-only + :not(:first-child):not(:empty),
.navds-form-field > .navds-sr-only + input:not(:first-child) {
margin-top: 0;
}
+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";
+38 -8
View File
@@ -1,7 +1,8 @@
:root {
--navds-radio-checkbox-color-background: var(
--navds-semantic-color-canvas-background-light
--navds-semantic-color-component-background-light
);
--navds-radio-checkbox-color-text: var(--navds-semantic-color-text);
--navds-radio-checkbox-color-background-hover: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
@@ -73,7 +74,7 @@
.navds-checkbox__description,
.navds-radio__description {
color: var(--navds-color-text-primary);
color: var(--navds-radio-checkbox-color-text);
}
.navds-checkbox--small > .navds-checkbox__input,
@@ -107,6 +108,29 @@
var(--navds-shadow-focus);
}
.navds-checkbox__input:indeterminate + .navds-checkbox__label::before {
box-shadow: none;
background-color: var(--navds-radio-checkbox-color-background-checked);
}
.navds-checkbox__input:indeterminate + .navds-checkbox__label::after {
content: "";
position: absolute;
top: 50%;
transform: translate(0.375rem, -50%);
background-color: var(--navds-radio-checkbox-color-background);
width: 0.75rem;
height: 0.25rem;
border-radius: 1px;
flex-shrink: 0;
}
.navds-checkbox--small
.navds-checkbox__input:indeterminate
+ .navds-checkbox__label::after {
transform: translate(0.25rem, -50%);
}
.navds-checkbox__input:checked + .navds-checkbox__label::before {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMyAxMCI+ICAgIDxnPiAgICA8cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNCwxMGMtMC40LDAtMC44LTAuMS0xLjEtMC40TDAuNCw3LjFDMC4xLDYuOCwwLDYuNCwwLDZzMC4yLTAuOCwwLjUtMS4xQzEsNC40LDIsNC40LDIuNSw0LjlMNCw2LjRsNi40LTYgICAgQzEwLjgsMC4xLDExLjEsMCwxMS41LDBjMC40LDAsMC44LDAuMiwxLDAuNWMwLjYsMC42LDAuNSwxLjYtMC4xLDIuMXYwTDUsOS42QzQuNyw5LjksNC40LDEwLDQsMTB6IE0xMS44LDEuOUwxMS44LDEuOSAgICBDMTEuOCwxLjksMTEuOCwxLjksMTEuOCwxLjl6IE0xMS4yLDEuMUMxMS4yLDEuMSwxMS4yLDEuMSwxMS4yLDEuMUwxMS4yLDEuMXoiLz4gICAgPC9nPjwvc3ZnPg==);
background-position: 6px center;
@@ -121,7 +145,7 @@
+ .navds-checkbox__label::before {
background-position: 4px center;
}
.navds-checkbox__input:indeterminate:focus + .navds-checkbox__label::before,
.navds-checkbox__input:checked:focus + .navds-checkbox__label::before {
box-shadow: inset 0 0 0 1px white, var(--navds-shadow-focus);
}
@@ -142,28 +166,34 @@
color: var(--navds-radio-checkbox-color-label-hover);
}
.navds-checkbox__input:hover:not(:disabled):not(:checked):not(:focus)
.navds-checkbox__input:hover:not(:disabled):not(:checked):not(:indeterminate):not(:focus)
+ .navds-checkbox__label::before,
.navds-radio__input:hover:not(:disabled):not(:checked):not(:focus)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-hover);
}
.navds-checkbox__input:hover:not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio__input:hover:not(:disabled):not(:checked)
+ .navds-radio__label::before {
background-color: var(--navds-radio-checkbox-color-background-hover);
}
.navds-checkbox--error
> .navds-checkbox__input:not(:hover):not(:disabled):not(:checked)
> .navds-checkbox__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:not(:hover):not(:disabled):not(:checked)
> .navds-radio__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-error);
}
.navds-checkbox--error
> .navds-checkbox__input:focus:not(:hover):not(:disabled):not(:checked)
> .navds-checkbox__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked)
> .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-error),
var(--navds-shadow-focus);
-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;
}
+123
View File
@@ -0,0 +1,123 @@
:root {
--navds-search-color-border: var(--navds-semantic-color-border);
--navds-search-color-border-hover: var(
--navds-semantic-color-interaction-primary
);
}
.navds-search {
display: flex;
flex-direction: column;
}
.navds-search__wrapper-inner {
position: relative;
}
.navds-search__wrapper {
display: inline-flex;
align-items: center;
}
.navds-search__input {
padding-right: var(--navds-spacing-12);
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.navds-form-field--small .navds-search__input {
min-height: 32px;
padding: 0.15rem;
padding-right: var(--navds-spacing-8);
}
.navds-search__button-clear {
position: absolute;
right: 0.75rem;
border-radius: var(--navds-border-radius-medium);
color: var(--navds-semantic-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-global-color-blue-500);
}
.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--tertiary {
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--tertiary: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--tertiary:hover {
z-index: auto;
}
.navds-search__button-search.navds-button--tertiary:focus {
box-shadow: 0 0 0 1px var(--navds-search-color-border) inset,
var(--navds-shadow-focus);
}
.navds-search__button-search.navds-button--tertiary: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--tertiary: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;
}
+52 -15
View File
@@ -1,14 +1,17 @@
:root {
--navds-switch-color-label: var(--navds-color-text-primary);
--navds-switch-color-label: var(--navds-semantic-color-text);
--navds-switch-color-label-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-switch-color-track-background: var(--navds-semantic-color-text-muted);
--navds-switch-color-track-background-checked: var(
--navds-semantic-color-interaction-primary
--navds-semantic-color-feedback-success-border
);
--navds-switch-color-track-background-hover: var(
--navds-global-color-gray-800
);
--navds-switch-color-track-background-hover-checked: var(
--navds-semantic-color-interaction-primary-hover
--navds-semantic-color-feedback-success-icon
);
--navds-switch-color-track-shadow-inner-focus: var(
--navds-semantic-color-component-background-light
@@ -16,8 +19,12 @@
--navds-switch-color-thumb: var(
--navds-semantic-color-component-background-light
);
--navds-switch-color-thumb-icon: var(--navds-semantic-color-text-muted);
--navds-switch-color-thumb-icon-checked: var(
--navds-semantic-color-feedback-success-border
);
--navds-switch-color-thumb-loader-checked: var(
--navds-semantic-color-interaction-primary
--navds-semantic-color-feedback-success-border
);
}
@@ -27,6 +34,10 @@
width: fit-content;
}
.navds-switch--right {
width: auto;
}
.navds-switch--small {
position: relative;
min-height: 32px;
@@ -61,11 +72,22 @@
padding: 0.75rem 0 0.75rem 3.25rem;
}
.navds-switch--right > .navds-switch__label-wrapper > .navds-switch__content {
padding: 0.75rem 3.25rem 0.75rem 0;
}
.navds-switch--small > .navds-switch__label-wrapper > .navds-switch__content {
padding: calc(var(--navds-spacing-2) - 2px) 0
calc(var(--navds-spacing-2) - 2px) 3.25rem;
}
.navds-switch--right.navds-switch--small
> .navds-switch__label-wrapper
> .navds-switch__content {
padding: calc(var(--navds-spacing-2) - 2px) 3.25rem
calc(var(--navds-spacing-2) - 2px) 0;
}
.navds-switch--with-description,
.navds-switch--small
> .navds-switch__label-wrapper
@@ -73,7 +95,8 @@
padding-bottom: 0;
}
.navds-switch__input:hover ~ .navds-switch__label-wrapper {
.navds-switch__input:hover ~ .navds-switch__label-wrapper,
.navds-switch__label-wrapper:hover {
color: var(--navds-switch-color-label-hover);
}
@@ -89,7 +112,7 @@
position: absolute;
top: var(--navds-spacing-3);
left: 0;
border-radius: var(--navds-spacing-4);
border-radius: 4px;
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -97,10 +120,20 @@
top: var(--navds-spacing-1);
}
.navds-switch--right > .navds-switch__input,
.navds-switch--right > .navds-switch__track {
right: 0;
left: auto;
}
.navds-switch__input:checked ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-checked);
}
.navds-switch__input:hover ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-hover);
}
.navds-switch__input:hover:checked ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-hover-checked);
}
@@ -121,7 +154,8 @@
/* Thumb */
.navds-switch__thumb {
background-color: var(--navds-switch-color-thumb);
border-radius: 50%;
color: var(--navds-switch-color-thumb-icon);
border-radius: 2.5px;
width: 20px;
height: 20px;
position: absolute;
@@ -136,16 +170,19 @@
.navds-switch__input:checked ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(20px);
color: var(--navds-switch-color-thumb-icon-checked);
}
.navds-switch__input:hover ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(2px);
}
@media (hover: hover) and (pointer: fine) {
.navds-switch__input:hover ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(2px);
}
.navds-switch__input:checked:hover
~ .navds-switch__track
> .navds-switch__thumb {
transform: translateX(18px);
.navds-switch__input:checked:hover
~ .navds-switch__track
> .navds-switch__thumb {
transform: translateX(18px);
}
}
.navds-switch__input:disabled:hover
@@ -173,7 +210,7 @@
appearance: none;
}
.navds-switch--disabled {
.navds-switch--disabled:not(.navds-switch--loading) {
opacity: 0.3;
}
+11 -2
View File
@@ -1,4 +1,5 @@
:root {
--navds-text-field-color-text: var(--navds-semantic-color-text);
--navds-text-field-color-background: var(
--navds-semantic-color-component-background-light
);
@@ -24,13 +25,14 @@
padding: 0.5rem;
background-color: var(--navds-text-field-color-background);
border-radius: 4px;
border: 2px solid var(--navds-text-field-color-border);
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 {
padding: 0 0.15rem;
padding: 0 0.25rem;
min-height: 32px;
}
@@ -52,6 +54,13 @@
*/
.navds-text-field--error > .navds-text-field__input:not(:hover):not(:disabled) {
border-color: var(--navds-text-field-color-border-error);
box-shadow: 0 0 0 1px var(--navds-text-field-color-border-error);
}
.navds-text-field--error
> .navds-text-field__input:focus:not(:hover):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-text-field-color-border-error),
var(--navds-shadow-focus);
}
/* Disabled handling */
+5 -1
View File
@@ -1,9 +1,9 @@
@charset "UTF-8";
@import "baseline/baseline.css";
@import "typography.css";
@import "grid.css";
@import "accordion.css";
@import "accordion-menu.css";
@import "alert.css";
@import "button.css";
@import "content-container.css";
@@ -12,12 +12,16 @@
@import "help-text.css";
@import "link.css";
@import "loader.css";
@import "menu.css";
@import "modal.css";
@import "pagination.css";
@import "popover.css";
@import "tag.css";
@import "toggle-group.css";
@import "panel.css";
@import "link-panel.css";
@import "speech-bubble.css";
@import "step-indicator.css";
@import "table.css";
/* Navno spesific packages */
-23
View File
@@ -12,8 +12,6 @@
);
--navds-loader-color-inverted-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-transparent-background: transparent;
--navds-loader-color-on-button-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-on-button-foreground: currentColor;
}
.navds-loader {
@@ -78,27 +76,6 @@
width: 1rem;
}
/*
* Button spesific styling
*/
.navds-button .navds-loader .navds-loader__foreground {
stroke: var(--navds-loader-color-on-button-foreground);
}
.navds-button:hover .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button:active .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button--primary .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
@keyframes loader-rotate {
100% {
transform: rotate(360deg);
+102
View File
@@ -0,0 +1,102 @@
:root {
--navds-menu-color-text: var(--navds-semantic-color-link);
--navds-menu-color-text-hover: var(--navds-semantic-color-text);
--navds-menu-color-text-focus: var(--navds-semantic-color-text);
--navds-menu-color-background-hover: var(--navds-global-color-blue-50);
--navds-menu-color-text-active: var(--navds-semantic-color-text);
--navds-menu-outline-focus: var(--navds-semantic-color-focus);
}
.navds-menu__list {
list-style: none;
margin: 0;
padding: 0;
padding: 0 0.5rem;
}
.navds-menu__list--inner {
padding: 0;
}
.navds-menu-collapse__button {
cursor: pointer;
background-color: transparent;
border: none;
font: inherit;
text-align: inherit;
margin: 0;
width: 100%;
justify-content: space-between;
align-items: center;
font-weight: var(--navds-font-weight-bold);
color: var(--navds-menu-color-text);
}
.navds-menu-item,
.navds-menu-collapse__button {
font-weight: var(--navds-font-weight-bold);
display: flex;
padding: var(--navds-spacing-3) var(--navds-spacing-2);
text-decoration: none;
}
.navds-menu-item:focus,
.navds-menu-collapse__button:focus {
outline: 3px solid var(--navds-menu-outline-focus);
outline-offset: -3px;
color: var(--navds-menu-color-text-focus);
}
.navds-menu-collapse__button:focus > .navds-menu-collapse__expand-icon {
color: var(--navds-menu-color-focus);
}
.navds-menu-item:hover,
.navds-menu-collapse__button:hover {
background-color: var(--navds-menu-color-background-hover);
color: var(--navds-menu-color-text-hover);
}
.navds-menu-item--active {
box-shadow: -0.5rem 0 var(--navds-semantic-color-link);
color: var(--navds-menu-color-text-active);
text-decoration: none;
}
/* Collapse icon */
.navds-menu-collapse__expand-icon {
font-size: 1.5rem;
flex-shrink: 0;
margin-left: var(--navds-spacing-2);
}
.navds-menu-collapse__expand-icon--filled,
.navds-menu-collapse__button:hover > .navds-menu-collapse__expand-icon {
display: none;
}
.navds-menu-collapse__button:hover > .navds-menu-collapse__expand-icon--filled {
display: block;
}
.navds-menu-collapse--open
> .navds-menu-collapse__button
> .navds-menu-collapse__expand-icon {
transform: rotate(180deg);
}
/* Nesting levels */
.navds-menu__list[data-depth="1"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="1"] .navds-menu-item {
padding-left: var(--navds-spacing-6);
}
.navds-menu__list[data-depth="2"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="2"] .navds-menu-item {
padding-left: var(--navds-spacing-10);
}
.navds-menu__list[data-depth="3"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="3"] .navds-menu-item {
padding-left: var(--navds-spacing-14);
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.12.7",
"version": "0.16.1",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
@@ -21,7 +21,7 @@
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^0.7.1",
"@navikt/ds-tokens": "^0.8.4",
"normalize.css": "^8.0.1",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
+118
View File
@@ -0,0 +1,118 @@
: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: 2px;
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: 2px;
}
.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;
}
+202
View File
@@ -0,0 +1,202 @@
:root {
--navds-step-indicator-color-step-line: var(--navds-semantic-color-divider);
--navds-step-indicator-color-step-text: var(--navds-semantic-color-text);
--navds-step-indicator-color-step-label: var(
--navds-semantic-color-interaction-primary
);
--navds-step-indicator-color-step-number-background: var(
--navds-semantic-color-canvas-background-light
);
--navds-step-indicator-color-step-number-background-finished: var(
--navds-semantic-color-canvas-background
);
--navds-step-indicator-color-step-number-shadow: var(
--navds-semantic-color-border
);
--navds-step-indicator-color-step-number-shadow-active: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-step-indicator-color-step-number-shadow-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-step-indicator-color-step-number-background-active: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-step-indicator-color-step-number-text-active: var(
--navds-semantic-color-text-inverted
);
--navds-step-indicator-color-step-number-shadow-inset: var(
--navds-semantic-color-component-background-light
);
}
/* StepIndicator */
.navds-step-indicator {
display: flex;
align-items: flex-start;
padding: 0;
margin: 0;
}
/* Step */
.navds-step-indicator__step-wrapper {
padding: 0 var(--navds-spacing-2);
flex: 1;
position: relative;
list-style: none;
min-width: 10rem;
}
.navds-step-indicator__step-wrapper--hidelabel {
min-width: 5rem;
}
.navds-step-indicator__step {
display: flex;
align-items: center;
flex-direction: column;
padding: 0;
background: none;
border: none;
appearance: none;
width: 100%;
flex-shrink: 1;
color: var(--navds-step-indicator-color-step-text);
text-decoration: none;
cursor: pointer;
}
.navds-step-indicator__step-number {
flex-shrink: 0;
display: flex;
width: 2rem;
height: 2rem;
margin: 0.5rem;
border-radius: 50%;
align-items: center;
justify-content: center;
box-shadow: 0 0 0 1px var(--navds-step-indicator-color-step-number-shadow);
background-color: var(--navds-step-indicator-color-step-number-background);
}
.navds-step-indicator__step-wrapper:first-child
> .navds-step-indicator__step
> .navds-step-indicator__step-number {
padding-right: 0;
}
.navds-step-indicator__step-wrapper:last-child
> .navds-step-indicator__step
> .navds-step-indicator__step-number {
padding-left: 0;
}
.navds-step-indicator__step-label {
width: 100%;
margin-top: var(--navds-spacing-4);
text-align: center;
color: var(--navds-step-indicator-color-step-label);
text-decoration: underline;
}
.navds-step-indicator__step-line {
flex: 1 1 100%;
position: absolute;
top: 1.5rem;
right: calc(50% + 2rem);
left: calc(-50% + 2rem);
display: block;
border-top: 2px solid var(--navds-step-indicator-color-step-line);
border-radius: 4px;
pointer-events: none;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-label {
color: var(--navds-step-indicator-color-step-text);
font-weight: bold;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-number {
background-color: var(
--navds-step-indicator-color-step-number-background-active
);
color: var(--navds-step-indicator-color-step-number-text-active);
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
width: 2.5rem;
height: 2.5rem;
margin: 0.25rem;
}
.navds-step-indicator__step:focus {
outline: none;
}
.navds-step-indicator__step:hover > .navds-step-indicator__step-label {
text-decoration: none;
}
.navds-step-indicator__step.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-label {
text-decoration: underline;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-label,
.navds-step-indicator__step--active.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-label {
text-decoration: none;
}
.navds-step-indicator__step:hover > .navds-step-indicator__step-number {
background: var(--navds-step-indicator-color-step-number-background);
box-shadow: 0 0 0 2px
var(--navds-step-indicator-color-step-number-shadow-hover);
}
.navds-step-indicator__step--active:hover > .navds-step-indicator__step-number {
background-color: var(
--navds-step-indicator-color-step-number-background-active
);
color: var(--navds-step-indicator-color-step-number-text-active);
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
}
.navds-step-indicator__step:focus > .navds-step-indicator__step-number {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-step-indicator__step--active:focus > .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px inset
var(--navds-step-indicator-color-step-number-shadow-inset),
var(--navds-shadow-focus);
}
.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px var(--navds-step-indicator-color-step-number-shadow);
}
.navds-step-indicator__step--disabled.navds-step-indicator__step--active:disabled
> .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
}
/* Finished state */
.navds-step-indicator__step--finished > .navds-step-indicator__step-number,
.navds-step-indicator__step--finished.navds-step-indicator__step--disabled
> .navds-step-indicator__step-number {
background: var(--navds-step-indicator-color-step-number-background-finished);
}
/* Disabled */
.navds-step-indicator__step--disabled > .navds-step-indicator__step-number,
.navds-step-indicator__step--disabled > .navds-step-indicator__step-label {
opacity: 0.3;
}
.navds-step-indicator__step--disabled {
cursor: not-allowed;
}
+64 -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,54 @@
.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;
}
+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;
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: 2px;
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;
}
+24 -11
View File
@@ -4,34 +4,47 @@
margin: 0;
}
.navds-heading--2xlarge {
.navds-heading--xlarge {
font-size: var(--navds-font-size-heading-2xlarge);
letter-spacing: -0.01em;
line-height: var(--navds-font-line-height-heading-2xlarge);
}
.navds-heading--2xlarge.navds-typo--spacing {
.navds-heading--xlarge.navds-typo--spacing {
margin-bottom: var(--navds-spacing-5);
}
.navds-heading--xlarge {
.navds-heading--large {
font-size: var(--navds-font-size-heading-xlarge);
letter-spacing: -0.008em;
line-height: var(--navds-font-line-height-heading-xlarge);
}
.navds-heading--xlarge.navds-typo--spacing {
.navds-heading--large.navds-typo--spacing {
margin-bottom: var(--navds-spacing-4);
}
.navds-heading--large {
font-size: var(--navds-font-size-heading-large);
letter-spacing: -0.004em;
line-height: var(--navds-font-line-height-heading-large);
}
/* Mobile scale */
@media (max-width: 480px) {
.navds-heading--xlarge {
font-size: var(--navds-font-size-heading-xlarge);
letter-spacing: -0.008em;
line-height: var(--navds-font-line-height-heading-xlarge);
}
.navds-heading--large.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
.navds-heading--xlarge.navds-typo--spacing {
margin-bottom: var(--navds-spacing-4);
}
.navds-heading--large {
font-size: var(--navds-font-size-heading-large);
letter-spacing: -0.004em;
line-height: var(--navds-font-line-height-heading-large);
}
.navds-heading--large.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
}
.navds-heading--medium {
+4 -3
View File
@@ -22,9 +22,10 @@ export const getPublishedIcons = async () => {
throw e;
});
return data?.meta?.components?.filter(
(component: any) => component?.containing_frame?.pageName !== "🔆Pictogram"
);
return data?.meta?.components?.filter((component: any) => {
const page = component?.containing_frame?.pageName;
return page !== "🔆Pictogram" && page !== "🧩Placeholder";
});
};
/**
@@ -2,7 +2,7 @@ import React from "react";
import { storiesOf } from "@storybook/react";
import isChromatic from "chromatic/isChromatic";
import * as Icons from "../src";
import * as Icons from "./src";
export default {
title: "ds-icons/Ikoner",
argTypes: {
+84
View File
@@ -743,6 +743,18 @@
"created_at": "2021-01-11T13:37:55.499Z",
"pageName": "Status"
},
{
"name": "Eu",
"description": "",
"created_at": "2022-02-08T11:45:47.104Z",
"pageName": "International"
},
{
"name": "EuFilled",
"description": "",
"created_at": "2022-02-08T11:45:47.109Z",
"pageName": "International"
},
{
"name": "Expand",
"description": "",
@@ -857,6 +869,18 @@
"created_at": "2021-01-11T13:37:55.491Z",
"pageName": "File"
},
{
"name": "FileError",
"description": "",
"created_at": "2022-01-27T12:48:37.583Z",
"pageName": "File"
},
{
"name": "FileErrorFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.605Z",
"pageName": "File"
},
{
"name": "FileFilled",
"description": "",
@@ -875,6 +899,30 @@
"created_at": "2021-04-26T09:24:37.951Z",
"pageName": "File"
},
{
"name": "FileProgressFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.592Z",
"pageName": "File"
},
{
"name": "Files",
"description": "",
"created_at": "2022-01-27T12:48:37.567Z",
"pageName": "File"
},
{
"name": "FileSuccess",
"description": "",
"created_at": "2022-01-27T12:48:37.575Z",
"pageName": "File"
},
{
"name": "FileSuccessFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.598Z",
"pageName": "File"
},
{
"name": "FillForms",
"description": "",
@@ -893,6 +941,18 @@
"created_at": "2020-07-01T10:37:42.891Z",
"pageName": "Interface"
},
{
"name": "Filter2",
"description": "",
"created_at": "2022-01-14T09:16:08.202Z",
"pageName": "Interface"
},
{
"name": "Filter2Filled",
"description": "",
"created_at": "2022-01-14T09:16:08.197Z",
"pageName": "Interface"
},
{
"name": "FilterFilled",
"description": "",
@@ -959,6 +1019,30 @@
"created_at": "2021-01-28T14:00:38.520Z",
"pageName": "Fyrstikkalleen"
},
{
"name": "FullscreenEnter",
"description": "",
"created_at": "2022-02-10T15:01:12.614Z",
"pageName": "Interface"
},
{
"name": "FullscreenEnterFilled",
"description": "",
"created_at": "2022-02-10T15:01:12.604Z",
"pageName": "Interface"
},
{
"name": "FullscreenExit",
"description": "",
"created_at": "2022-02-10T15:01:12.597Z",
"pageName": "Interface"
},
{
"name": "FullscreenExitFilled",
"description": "",
"created_at": "2022-02-10T15:01:12.608Z",
"pageName": "Interface"
},
{
"name": "Glass",
"description": "",
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "0.7.2",
"version": "0.8.4",
"private": false,
"description": "NAVs egne ikoner i SVG og React format",
"repository": {
@@ -42,6 +42,7 @@
"devDependencies": {
"@svgr/cli": "^5.5.0",
"@types/lodash.startcase": "^4.4.6",
"@types/rimraf": "3.0.2",
"@types/uuid": "^8.3.1",
"axios": "^0.21.3",
"copyfiles": "^2.4.1",
@@ -1,23 +0,0 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-icons/Kom i gang" />
# Ta i bruk ikonpakken `@navikt/ds-icons`
Alle ikoner kan bli funnet her https://design.nav.no/designsystem/resources/icons
## Oppsett
```bash
yarn add @navikt/ds-icons
```
```jsx
Import { Expand } from `@navikt/ds-icons`;
<Expand
title="Åpne meny"
/>
```
Note: Det kan være tilfeller der oppsettet ditt ikke har støtte for SVG, og det må da legges til manuelt i eks en webpack config basert på hva som blir brukt.
+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="M19.4858 7.11515C20.7324 5.94459 20.7324 4.04674 19.4858 2.87619C18.2838 1.74743 16.3616 1.70712 15.1081 2.75525L14.9716 2.87619L3.6862 13.4736L3.52649 13.6301C1.61004 15.5902 1.66328 18.6389 3.6862 20.5385C5.70912 22.4381 8.95584 22.4881 11.0432 20.6885L11.2098 20.5385L22.4953 9.94113L24 11.3541L12.7146 21.9515L12.5304 22.1187C9.61022 24.6816 5.02951 24.6259 2.18147 21.9515C-0.666561 19.2771 -0.725895 14.9757 2.00347 12.2335L2.18147 12.0606L13.4669 1.4632C15.5445 -0.487732 18.913 -0.487732 20.9905 1.4632C23.0135 3.36279 23.0667 6.41157 21.1503 8.37164L20.9905 8.52814L9.7051 19.1255L9.56865 19.2465C8.31517 20.2946 6.39296 20.2543 5.19092 19.1255C3.98889 17.9968 3.94596 16.1918 5.06214 15.0147L5.19092 14.8866L16.4764 4.28917L17.9811 5.70216L6.69565 16.2996L6.61297 16.3867C6.28225 16.7789 6.30981 17.3502 6.69565 17.7126C7.08149 18.0749 7.68993 18.1008 8.10757 17.7902L8.20038 17.7126L19.4858 7.11515Z" fill="#262626"/>
<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"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.5 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="M19.4858 7.11888C20.7324 5.94771 20.7324 4.04887 19.4858 2.87769C18.2838 1.74835 16.3616 1.70802 15.1081 2.75669L14.9716 2.87769L3.6862 13.4807L3.52649 13.6372C1.61004 15.5983 1.66328 18.6487 3.6862 20.5493C4.61095 21.4181 5.79143 21.9002 7 21.9956V22H24V24L7 24C5.24586 23.9013 3.52179 23.2223 2.18147 21.963C-0.666561 19.2872 -0.725895 14.9835 2.00347 12.2399L2.18147 12.0669L13.4669 1.46396C15.5445 -0.487988 18.913 -0.487988 20.9905 1.46396C23.0135 3.36455 23.0667 6.41493 21.1503 8.37603L20.9905 8.53261L9.7051 19.1356L9.56865 19.2566C8.31517 20.3053 6.39296 20.2649 5.19092 19.1356C3.98889 18.0062 3.94596 16.2003 5.06214 15.0226L5.19092 14.8944L16.4764 4.29142L17.9811 5.70515L6.69565 16.3081L6.61297 16.3953C6.28225 16.7877 6.30981 17.3593 6.69565 17.7219C7.08149 18.0844 7.68993 18.1103 8.10757 17.7995L8.20038 17.7219L19.4858 7.11888Z" fill="#262626"/>
<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"/>
</svg>

Before

Width:  |  Height:  |  Size: 1015 B

After

Width:  |  Height:  |  Size: 1.6 KiB

+10
View File
@@ -0,0 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.6836 0.585361C11.7435 0.401105 12.0041 0.401105 12.064 0.585362L12.5383 2.04506C12.5651 2.12746 12.6419 2.18325 12.7286 2.18325H14.2632C14.4569 2.18325 14.5375 2.43117 14.3807 2.54505L13.1391 3.44712C13.069 3.49805 13.0397 3.58833 13.0664 3.67074L13.5407 5.13034C13.6006 5.3146 13.3897 5.46783 13.233 5.35394L11.9914 4.45183C11.9213 4.4009 11.8263 4.4009 11.7563 4.45183L10.5146 5.35397C10.3578 5.46785 10.1469 5.31462 10.2068 5.13036L10.6811 3.67074C10.7079 3.58833 10.6785 3.49805 10.6084 3.44712L9.36682 2.54505C9.21008 2.43117 9.29063 2.18325 9.48438 2.18325H11.0191C11.1057 2.18325 11.1825 2.12746 11.2093 2.04506L11.6836 0.585361Z" fill="#262626"/>
<path d="M3.72187 3.991C3.63391 3.81837 3.81823 3.63404 3.99086 3.72199L5.38403 4.43175C5.46122 4.47108 5.55497 4.45623 5.61623 4.39497L6.72162 3.28964C6.85862 3.15264 7.09089 3.271 7.06057 3.46236L6.81595 5.00634C6.80239 5.09192 6.84548 5.1765 6.92269 5.21584L8.31573 5.92562C8.48835 6.01358 8.44758 6.27105 8.25622 6.30136L6.71211 6.54594C6.62654 6.55949 6.55942 6.62661 6.54587 6.71219L6.30129 8.25637C6.27098 8.44773 6.01351 8.48851 5.92555 8.31588L5.21577 6.92284C5.17643 6.84564 5.09185 6.80254 5.00627 6.8161L3.46232 7.06072C3.27095 7.09104 3.1526 6.85877 3.2896 6.72177L4.39497 5.61639C4.45624 5.55513 4.47109 5.46137 4.43175 5.38417L3.72187 3.991Z" fill="#262626"/>
<path d="M0.585361 12.2186C0.401105 12.1587 0.401105 11.898 0.585362 11.8381L2.15739 11.3273C2.23979 11.3005 2.29558 11.2238 2.29558 11.1371V9.48437C2.29558 9.29062 2.54351 9.21007 2.65739 9.36682L3.62879 10.704C3.67971 10.7741 3.76999 10.8034 3.8524 10.7767L5.42439 10.2659C5.60866 10.206 5.76189 10.4169 5.64799 10.5737L4.6764 11.9108C4.62546 11.9809 4.62546 12.0758 4.6764 12.1459L5.64802 13.4831C5.76191 13.6398 5.60869 13.8507 5.42442 13.7909L3.85239 13.2801C3.76999 13.2533 3.67971 13.2827 3.62879 13.3528L2.65739 14.6899C2.54351 14.8467 2.29558 14.7661 2.29558 14.5724V12.9196C2.29558 12.8329 2.23979 12.7562 2.15739 12.7294L0.585361 12.2186Z" fill="#262626"/>
<path d="M3.99086 20.0891C3.81823 20.177 3.63391 19.9927 3.72186 19.8201L4.43169 18.4269C4.47103 18.3497 4.45618 18.2559 4.39492 18.1947L3.28959 17.0893C3.15259 16.9523 3.27096 16.72 3.46232 16.7503L5.00638 16.995C5.09197 17.0086 5.17655 16.9655 5.21589 16.8883L5.92553 15.4953C6.01348 15.3226 6.27096 15.3634 6.30128 15.5548L6.54591 17.0989C6.55947 17.1845 6.62659 17.2516 6.71216 17.2651L8.25628 17.5097C8.44763 17.54 8.48841 17.7975 8.31579 17.8854L6.92289 18.5952C6.8457 18.6346 6.80261 18.7191 6.81616 18.8047L7.06069 20.3488C7.09099 20.5401 6.85872 20.6585 6.72173 20.5215L5.61627 19.416C5.55501 19.3548 5.46126 19.3399 5.38406 19.3793L3.99086 20.0891Z" fill="#262626"/>
<path d="M12.064 23.1204C12.0041 23.3047 11.7435 23.3047 11.6836 23.1205L11.2092 21.6608C11.1824 21.5784 11.1056 21.5226 11.019 21.5226H9.4844C9.29066 21.5226 9.2101 21.2746 9.36685 21.1608L10.6085 20.2587C10.6786 20.2078 10.7079 20.1175 10.6812 20.0351L10.2068 18.5756C10.1469 18.3914 10.3578 18.2381 10.5146 18.352L11.7563 19.254C11.8264 19.3049 11.9213 19.3049 11.9914 19.254L13.233 18.352C13.3897 18.2381 13.6006 18.3914 13.5407 18.5756L13.0665 20.0351C13.0397 20.1175 13.069 20.2078 13.1391 20.2587L14.3807 21.1608C14.5375 21.2746 14.4569 21.5226 14.2632 21.5226H12.7285C12.6418 21.5226 12.565 21.5784 12.5383 21.6608L12.064 23.1204Z" fill="#262626"/>
<path d="M20.0891 19.8201C20.177 19.9928 19.9927 20.1771 19.8201 20.0892L18.427 19.3794C18.3498 19.3401 18.2561 19.3549 18.1948 19.4162L17.0893 20.5217C16.9523 20.6587 16.72 20.5403 16.7503 20.3489L16.995 18.8047C17.0085 18.7191 16.9654 18.6345 16.8882 18.5952L15.4953 17.8855C15.3227 17.7975 15.3634 17.54 15.5548 17.5097L17.0989 17.2652C17.1845 17.2516 17.2516 17.1845 17.2651 17.0989L17.5097 15.5548C17.54 15.3634 17.7975 15.3226 17.8854 15.4953L18.5952 16.8883C18.6345 16.9655 18.7191 17.0086 18.8047 16.9951L20.3487 16.7504C20.5401 16.72 20.6584 16.9523 20.5214 17.0893L19.416 18.1949C19.3547 18.2562 19.3399 18.3499 19.3792 18.4271L20.0891 19.8201Z" fill="#262626"/>
<path d="M23.4144 11.8382C23.5987 11.8981 23.5987 12.1588 23.4145 12.2187L21.8424 12.7295C21.76 12.7563 21.7042 12.8331 21.7042 12.9197V14.5726C21.7042 14.7663 21.4563 14.8469 21.3424 14.6901L20.3709 13.3528C20.3199 13.2827 20.2297 13.2534 20.1473 13.2802L18.5754 13.791C18.3912 13.8508 18.2379 13.64 18.3518 13.4832L19.3233 12.146C19.3743 12.0759 19.3743 11.981 19.3233 11.9109L18.3518 10.5737C18.2379 10.4169 18.3912 10.206 18.5754 10.2659L20.1473 10.7767C20.2297 10.8035 20.32 10.7742 20.371 10.7041L21.3424 9.36682C21.4563 9.21007 21.7042 9.29062 21.7042 9.48437V11.1373C21.7042 11.2239 21.76 11.3007 21.8424 11.3275L23.4144 11.8382Z" fill="#262626"/>
<path d="M19.82 3.72203C19.9927 3.63407 20.177 3.8184 20.089 3.99102L19.3792 5.38419C19.3399 5.46139 19.3547 5.55514 19.416 5.61641L20.5214 6.72179C20.6584 6.85879 20.54 7.09107 20.3487 7.06075L18.8045 6.81606C18.719 6.8025 18.6344 6.8456 18.595 6.92281L17.8854 8.31578C17.7975 8.48842 17.54 8.44765 17.5097 8.25629L17.2651 6.71221C17.2515 6.62664 17.1844 6.55952 17.0988 6.54596L15.5547 6.30132C15.3634 6.271 15.3226 6.01354 15.4952 5.92558L16.8882 5.21585C16.9654 5.17652 17.0085 5.09194 16.9949 5.00635L16.7503 3.46238C16.72 3.27102 16.9522 3.15266 17.0892 3.28965L18.1948 4.39506C18.2561 4.45632 18.3498 4.47116 18.427 4.43183L19.82 3.72203Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 5.3 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="M0 2C0 0.89543 0.895431 0 2 0H22C23.1046 0 24 0.895431 24 2V22C24 23.1046 23.1046 24 22 24H2C0.89543 24 0 23.1046 0 22V2ZM11.6942 1.58536C11.754 1.4011 12.0147 1.40111 12.0746 1.58536L12.4898 2.86313C12.5166 2.94553 12.5934 3.00132 12.68 3.00132H14.0233C14.2171 3.00132 14.2976 3.24925 14.1409 3.36313L13.054 4.15276C12.9839 4.20369 12.9546 4.29397 12.9814 4.37637L13.3966 5.65405C13.4564 5.83831 13.2455 5.99154 13.0888 5.87766L12.0019 5.08798C11.9318 5.03705 11.8369 5.03705 11.7668 5.08798L10.6799 5.87768C10.5231 5.99156 10.3123 5.83833 10.3721 5.65407L10.7873 4.37637C10.8141 4.29397 10.7848 4.20369 10.7147 4.15276L9.6278 3.36313C9.47105 3.24925 9.55161 3.00132 9.74535 3.00132H11.0888C11.1754 3.00132 11.2522 2.94553 11.279 2.86313L11.6942 1.58536ZM4.704 4.43512C4.53138 4.34717 4.34706 4.5315 4.43502 4.70413L5.05696 5.92473C5.0963 6.00193 5.08145 6.09568 5.02018 6.15695L4.05175 7.12538C3.91475 7.26238 4.03311 7.49465 4.22447 7.46433L5.57715 7.25002C5.66273 7.23646 5.74731 7.27955 5.78664 7.35676L6.40849 8.57722C6.49645 8.74985 6.75392 8.70907 6.78423 8.51772L6.99851 7.16483C7.01207 7.07925 7.07919 7.01213 7.16476 6.99858L8.51758 6.7843C8.70894 6.75399 8.74972 6.49652 8.57709 6.40856L7.35662 5.78671C7.27941 5.74737 7.23632 5.66279 7.24988 5.57721L7.4642 4.22451C7.49452 4.03315 7.26225 3.91479 7.12524 4.05178L6.1568 5.02018C6.09553 5.08144 6.00179 5.09629 5.92459 5.05696L4.704 4.43512ZM1.58536 12.2163C1.40111 12.1564 1.40111 11.8957 1.58536 11.8358L2.9661 11.3872C3.0485 11.3604 3.10429 11.2836 3.10429 11.197V9.74534C3.10429 9.55159 3.35223 9.47104 3.4661 9.6278L4.31929 10.8023C4.37021 10.8724 4.46049 10.9017 4.5429 10.8749L5.9236 10.4263C6.10787 10.3664 6.26109 10.5773 6.1472 10.7341L5.29384 11.9085C5.24291 11.9786 5.24291 12.0735 5.29384 12.1436L6.14722 13.3181C6.26111 13.4748 6.10789 13.6857 5.92363 13.6258L4.5429 13.1772C4.46049 13.1505 4.37022 13.1798 4.31929 13.2499L3.4661 14.4243C3.35222 14.5811 3.10429 14.5005 3.10429 14.3068V12.8551C3.10429 12.7685 3.0485 12.6917 2.9661 12.6649L1.58536 12.2163ZM4.43501 19.1228C4.34705 19.2954 4.53138 19.4798 4.704 19.3918L5.92462 18.7699C6.00182 18.7306 6.09557 18.7454 6.15684 18.8067L7.12535 19.7752C7.26234 19.9122 7.49461 19.7938 7.46431 19.6025L7.25008 18.2497C7.23652 18.1641 7.27961 18.0796 7.35681 18.0402L8.57716 17.4184C8.74977 17.3304 8.70899 17.0729 8.51764 17.0426L7.1648 16.8283C7.07923 16.8148 7.01212 16.7477 6.99856 16.6621L6.78423 15.3093C6.75391 15.1179 6.49643 15.0771 6.40848 15.2498L5.78675 16.4702C5.74742 16.5474 5.66283 16.5905 5.57724 16.577L4.22447 16.3626C4.03311 16.3323 3.91475 16.5645 4.05174 16.7015L5.02013 17.67C5.0814 17.7312 5.09624 17.825 5.05691 17.9022L4.43501 19.1228ZM12.0746 22.1451C12.0147 22.3293 11.754 22.3293 11.6942 22.1451L11.2789 20.8673C11.2521 20.7849 11.1753 20.7291 11.0887 20.7291H9.74537C9.55163 20.7291 9.47107 20.4812 9.62782 20.3673L10.7147 19.5777C10.7848 19.5268 10.8142 19.4365 10.7874 19.3541L10.3722 18.0765C10.3123 17.8923 10.5232 17.739 10.6799 17.8529L11.7668 18.6425C11.8369 18.6934 11.9318 18.6934 12.0019 18.6425L13.0888 17.8529C13.2455 17.739 13.4564 17.8923 13.3965 18.0765L12.9814 19.3541C12.9546 19.4365 12.9839 19.5268 13.054 19.5777L14.1409 20.3673C14.2976 20.4812 14.2171 20.7291 14.0233 20.7291H12.6799C12.5933 20.7291 12.5165 20.7849 12.4897 20.8673L12.0746 22.1451ZM19.1228 19.3919C19.2954 19.4798 19.4798 19.2955 19.3918 19.1229L18.7699 17.9024C18.7305 17.8252 18.7454 17.7314 18.8066 17.6702L19.7752 16.7016C19.9121 16.5646 19.7938 16.3323 19.6024 16.3626L18.2497 16.577C18.1641 16.5905 18.0795 16.5475 18.0402 16.4702L17.4184 15.2498C17.3304 15.0771 17.0729 15.1179 17.0426 15.3093L16.8283 16.6621C16.8148 16.7477 16.7477 16.8148 16.6621 16.8284L15.3093 17.0426C15.1179 17.073 15.0772 17.3304 15.2498 17.4184L16.4702 18.0402C16.5474 18.0795 16.5905 18.1641 16.5769 18.2497L16.3626 19.6026C16.3322 19.794 16.5645 19.9123 16.7015 19.7753L17.6701 18.8068C17.7313 18.7456 17.8251 18.7307 17.9023 18.77L19.1228 19.3919ZM22.4146 11.8359C22.5988 11.8958 22.5988 12.1565 22.4146 12.2164L21.0338 12.665C20.9514 12.6918 20.8956 12.7686 20.8956 12.8552V14.3069C20.8956 14.5007 20.6477 14.5812 20.5338 14.4245L19.6805 13.25C19.6296 13.1798 19.5393 13.1505 19.4569 13.1773L18.0763 13.6259C17.8921 13.6858 17.7389 13.4749 17.8527 13.3182L18.706 12.1437C18.757 12.0736 18.757 11.9787 18.706 11.9086L17.8527 10.7341C17.7388 10.5773 17.8921 10.3664 18.0763 10.4263L19.457 10.875C19.5394 10.9017 19.6297 10.8724 19.6806 10.8023L20.5338 9.6278C20.6477 9.47104 20.8956 9.55159 20.8956 9.74534V11.1971C20.8956 11.2838 20.9514 11.3605 21.0338 11.3873L22.4146 11.8359ZM19.3918 4.70416C19.4797 4.53153 19.2954 4.34721 19.1228 4.43517L17.9023 5.05703C17.8251 5.09637 17.7314 5.08152 17.6701 5.02027L16.7015 4.05179C16.5645 3.9148 16.3322 4.03316 16.3625 4.22452L16.5769 5.57722C16.5904 5.6628 16.5473 5.74738 16.4701 5.78672L15.2497 6.40853C15.0771 6.49648 15.1179 6.75395 15.3092 6.78427L16.6621 6.9986C16.7476 7.01216Line truncated
</svg>

After

Width:  |  Height:  |  Size: 5.3 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="M14.4142 0H2V22H12V20H4V2H12V7H17V14H19V4.58579L14.4142 0ZM16.5858 5L14 2.41421V5H16.5858ZM18 17.5858L21.2929 14.2929L22.7071 15.7071L19.4142 19L22.7071 22.2929L21.2929 23.7071L18 20.4142L14.7071 23.7071L13.2929 22.2929L16.5858 19L13.2929 15.7071L14.7071 14.2929L18 17.5858Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 445 B

@@ -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="M2 0V22H11.5L14.5 19L11 15.5L14.5 12L18 15.5L19 14.5V4.5L14.5 0H2ZM13.5 5V2L16.5 5H13.5ZM13.2929 22.2929L16.5858 19L13.2929 15.7071L14.7071 14.2929L18 17.5858L21.2929 14.2929L22.7071 15.7071L19.4142 19L22.7071 22.2929L21.2929 23.7071L18 20.4142L14.7071 23.7071L13.2929 22.2929Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 448 B

+1 -2
View File
@@ -1,4 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 23V10C2 9.44772 2.44772 9 3 9H11.5556C12.1078 9 12.5556 9.44772 12.5556 10V12H21C21.5523 12 22 12.4477 22 13V23C22 23.5523 21.5523 24 21 24H3C2.44772 24 2 23.5523 2 23Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 0H20V10H14V9C14 7.89543 13.1046 7 12 7H4V0ZM8 5H16V3H8V5Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 0H4V7H12C13.1046 7 14 7.89543 14 9V10H20V0ZM16 5H8V3H16V5ZM2 10V23C2 23.5523 2.44772 24 3 24H21C21.5523 24 22 23.5523 22 23V13C22 12.4477 21.5523 12 21 12H12.5556V10C12.5556 9.44772 12.1078 9 11.5556 9H3C2.44772 9 2 9.44772 2 10Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 430 B

After

Width:  |  Height:  |  Size: 404 B

@@ -0,0 +1,3 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 22V0H14.5L19 4.5V11H17.3135C11.6605 11 8.31543 17.3293 11.5 22H2ZM13.5 2V5H16.5L13.5 2ZM20.2122 20.7723C18.8453 22.1391 16.6293 22.1391 15.2624 20.7723C13.8956 19.4054 13.8956 17.1893 15.2624 15.8225C16.6293 14.4557 18.8453 14.4557 20.2122 15.8225L20.3897 16H19V18H24.0406V13L22.0406 13V14.8225L21.6264 14.4083C19.4785 12.2604 15.9961 12.2604 13.8482 14.4083C11.7003 16.5562 11.7003 20.0386 13.8482 22.1865C15.9961 24.3344 19.4785 24.3344 21.6264 22.1865L20.2122 20.7723Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 645 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 fill-rule="evenodd" clip-rule="evenodd" d="M2 0H14.4142L19 4.58579V16H17V7H12V2H4V20H11V22H2V0ZM14 2.41421L16.5858 5H14V2.41421ZM22.2689 14.3177L16.0317 21.0004L13.7593 18.3492L12.2407 19.6508L15.9683 23.9996L23.7311 15.6823L22.2689 14.3177Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 369 B

@@ -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="M2 0V22H12L10 19.5L14 16L16 18L19 15V4.5L14.5 0H2ZM13.5 5V2L16.5 5H13.5ZM22.2689 14.3177L16.0317 21.0004L13.7593 18.3492L12.2407 19.6508L15.9683 23.9996L23.7311 15.6823L22.2689 14.3177Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 356 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4142 0H2V22H11V20H4V2H12V7H17V11H19V4.58579L14.4142 0ZM16.5858 5L14 2.41421V5H16.5858ZM20.2122 20.7723C18.8453 22.1391 16.6293 22.1391 15.2624 20.7723C13.8956 19.4054 13.8956 17.1893 15.2624 15.8225C16.6293 14.4557 18.8453 14.4557 20.2122 15.8225L20.3897 16H19V18H24.0406V13L22.0406 13V14.8225L21.6264 14.4083C19.4785 12.2604 15.9961 12.2604 13.8482 14.4083C11.7003 16.5562 11.7003 20.0386 13.8482 22.1865C15.9961 24.3344 19.4785 24.3344 21.6264 22.1865L20.2122 20.7723Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 645 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 d="M9.34783 12.9348V12.5015L9.03177 12.2052L1 4.67546L0.316059 5.405L1 4.67546V3.5H23V4.69448L15.4668 12.2277L15.1739 12.5206V12.9348L15.1739 21.5495L9.34783 23.0384V12.9348Z" stroke="#262626" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 321 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="M0 3V4.17546C0 4.45187 0.114409 4.71595 0.316059 4.905L8.34783 12.4348V22.5384C8.34783 23.1911 8.96302 23.6689 9.59542 23.5073L15.4215 22.0184C15.8642 21.9052 16.1739 21.5064 16.1739 21.0495V12.4348L23.7071 4.90159C23.8946 4.71405 24 4.4597 24 4.19448V3C24 2.44772 23.5523 2 23 2H1C0.447715 2 0 2.44772 0 3Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 438 B

@@ -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="M17.5857 5L12.2928 10.2929L13.707 11.7071L19 6.41412V11H21V3H13V5L17.5857 5ZM5 13V17.5859L10.293 12.2929L11.7072 13.7071L6.4143 19H11V21H3V13H5Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 315 B

@@ -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="M1 0C0.447715 0 0 0.447716 0 1V23C0 23.5523 0.447716 24 1 24H23C23.5523 24 24 23.5523 24 23V1C24 0.447715 23.5523 0 23 0H1ZM12.2928 10.2929L17.5857 5L13 5V3H21V11H19V6.41412L13.707 11.7071L12.2928 10.2929ZM5 17.5859V13H3V21H11V19H6.4143L11.7072 13.7071L10.293 12.2929L5 17.5859Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 449 B

@@ -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="M16.414 8.99999L21.7068 3.7071L20.2926 2.29288L14.9999 7.58561V2.99999H12.9999V11H20.9999V8.99999H16.414ZM7.58562 15L2.29272 20.2929L3.70694 21.7071L8.99991 16.4141L8.99991 21H10.9999L10.9999 13L2.99991 13L2.99991 15L7.58562 15Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 399 B

@@ -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="M1 0C0.447715 0 0 0.447716 0 1V23C0 23.5523 0.447716 24 1 24H23C23.5523 24 24 23.5523 24 23V1C24 0.447715 23.5523 0 23 0H1ZM21.7068 3.70709L16.414 8.99998H20.9999V11H12.9999V2.99998H14.9999V7.5856L20.2926 2.29288L21.7068 3.70709ZM2.29272 20.2929L7.58562 15L2.99991 15L2.99991 13L10.9999 13L10.9999 21H8.99991V16.4141L3.70694 21.7071L2.29272 20.2929Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 520 B

+1 -1
View File
@@ -4,5 +4,5 @@
"outDir": "./cjs",
"module": "commonjs"
},
"exclude": ["./figma", "./scripts", "**/stories"]
"exclude": ["./figma", "./scripts", "**/*.stories.*"]
}
+4 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.14.4",
"version": "0.17.2",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
@@ -35,8 +35,9 @@
},
"dependencies": {
"@material-ui/core": "^4.12.3",
"@navikt/ds-icons": "^0.7.2",
"@navikt/ds-icons": "^0.8.4",
"@popperjs/core": "^2.10.1",
"@radix-ui/react-toggle-group": "0.1.5",
"classnames": "^2.2.6",
"react-collapse": "^5.1.0",
"react-merge-refs": "^1.1.0",
@@ -58,6 +59,7 @@
"react-router-dom": "^6.1.0",
"rimraf": "3.0.2",
"styled-components": "^5.3.1",
"swr": "^1.1.2",
"ts-jest": "^27.0.5"
},
"peerDependencies": {
@@ -1,39 +0,0 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import MenuItems from "./MenuItems";
import Collapsable, {
AccordionMenuCollapsableType,
} from "./AccordionMenuCollapsable";
import Item, { AccordionMenuItemType } from "./AccordionMenuItem";
export interface AccordionMenuProps extends React.HTMLAttributes<HTMLElement> {
children: React.ReactNode;
}
interface AccordionMenuComponent
extends React.ForwardRefExoticComponent<
AccordionMenuProps & React.RefAttributes<HTMLElement>
> {
Collapsable: AccordionMenuCollapsableType;
Item: AccordionMenuItemType;
}
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
({ children, className, ...rest }, ref) => {
return (
<nav
role="navigation"
ref={ref}
className={cl("navds-accordion-menu", className)}
{...rest}
>
<MenuItems>{children}</MenuItems>
</nav>
);
}
) as AccordionMenuComponent;
AccordionMenu.Collapsable = Collapsable;
AccordionMenu.Item = Item;
export default AccordionMenu;
@@ -1,45 +0,0 @@
import React, { forwardRef, HTMLAttributes, useState } from "react";
import cl from "classnames";
import { Expand } from "@navikt/ds-icons";
import MenuItems from "./MenuItems";
export interface AccordionMenuCollapsableProps
extends HTMLAttributes<HTMLDivElement> {
title: string;
defaultOpen?: boolean;
children: React.ReactNode;
}
export type AccordionMenuCollapsableType = React.ForwardRefExoticComponent<
AccordionMenuCollapsableProps & React.RefAttributes<HTMLDivElement>
>;
const Collapsable: AccordionMenuCollapsableType = forwardRef(
({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
return (
<div
ref={ref}
className={cl("navds-accordion-menu-collapsable", className, {
"navds-accordion-menu-collapsable--open": isOpen,
})}
{...rest}
>
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-accordion-menu-collapsable__button"
>
{title}
<Expand
title={isOpen ? "Pil peker opp" : "Pil peker ned"}
className="navds-accordion-menu-collapsable__expand-icon"
/>
</button>
{isOpen && <MenuItems>{children}</MenuItems>}
</div>
);
}
);
export default Collapsable;
@@ -1,13 +0,0 @@
import React from "react";
const MenuItems = ({ children }: { children: React.ReactNode }) => (
<ul className="navds-accordion-menu__list">
{React.Children.toArray(children).map((child, i) => (
<li key={i} className="navds-accordion-menu__list-item">
{child}
</li>
))}
</ul>
);
export default MenuItems;
@@ -1,3 +0,0 @@
export { default as AccordionMenu, AccordionMenuProps } from "./AccordionMenu";
export { AccordionMenuCollapsableProps } from "./AccordionMenuCollapsable";
export { AccordionMenuItemProps } from "./AccordionMenuItem";
@@ -1,66 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { AccordionMenu } from "../../index";
<Meta title="ds-react/accordion-menu/intro" />
# Hvordan ta i bruk Accordion-menu
```jsx
<AccordionMenu>
<AccordionMenu.item href="#leo">Leo</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla" active>
Nulla
</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.item href="#justo" aria-current="page">
Justo
</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla">Nulla</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
```
<Canvas>
<AccordionMenu>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla">Nulla</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
</Canvas>
Accordion-menu støtter opp til maks to-nivårer av `AccordionMenu.Collapsable` akkurat nå.
`AccordionMenu.Item` er implementert med `OverridableComponent`, noe som
gjør at man kan ta i bruk eks react-router slik:
```jsx
<AccordionMenu.item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Lenketekst
</AccordionMenu.item>
```
Her er `NavLink` fra `react-router-dom` brukt, og man får da
samtidig bruke alle propsene til denne komponenten som da er `activeClassName` her.
@@ -1,141 +0,0 @@
import * as React from "react";
import { AccordionMenu } from "../index";
import { NavLink, HashRouter as Router } from "react-router-dom";
export default {
title: "ds-react/accordion-menu",
component: { AccordionMenu },
};
export const All = () => (
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<AccordionMenu>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur" active aria-current="page">
Pariatur
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item href="#justo" active>
Justo
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur">Pariatur</AccordionMenu.Item>
</AccordionMenu>
</div>
);
export const ReactRouter = () => (
<AccordionMenu>
<AccordionMenu.Collapsable title="Nivå 1 – 3 rems høy">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Nivå 2 innrykk 2 rems
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/2"
>
Subtitle 3
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Skjema og søknad">
<AccordionMenu.Collapsable title="Satser">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/3"
>
Nivå 3 – 3 rems innrykk Har du rett til dagpenger når du mottar annen
økonomisk støtte fra NAV?
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/4"
>
Subtitle 2
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/5"
>
Subtitle 3
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Sakbehandlingstider">
<AccordionMenu.Collapsable title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/6"
>
Subtitle 5
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/7"
>
Internasjonalt
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Meld fra om endringer lang tittel på første nivå">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/8"
>
Subtitle 6
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/9"
>
Nivå 1
</AccordionMenu.Item>
</AccordionMenu>
);
ReactRouter.decorators = [
(Story) => (
<Router>
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<Story />
</div>
</Router>
),
];
@@ -43,6 +43,7 @@ const AccordionHeader: AccordionHeaderType = forwardRef(
return (
<button
{...rest}
ref={ref}
id={context.buttonId}
className={cl(
@@ -52,17 +53,17 @@ const AccordionHeader: AccordionHeaderType = forwardRef(
"navds-heading--small"
)}
onClick={handleClick}
{...rest}
aria-expanded={context.open}
>
{children}
<Expand
title={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
aria-hidden
className={cl("navds-accordion__expand-icon", {
"navds-accordion__expand-icon--flip": context.open,
})}
/>
<ExpandFilled
title={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
aria-hidden
className={cl(
"navds-accordion__expand-icon",
"navds-accordion__expand-icon--filled",
@@ -0,0 +1,90 @@
import React, { useState } from "react";
import AccordionContent from "./AccordionContent";
import AccordionHeader from "./AccordionHeader";
import AccordionItem from "./AccordionItem";
import { Accordion } from ".";
export default {
title: "ds-react/accordion",
component: Accordion,
subcomponents: {
AccordionItem,
AccordionContent,
AccordionHeader,
},
};
export const All = () => {
const [open, setOpen] = useState(false);
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>
</>
);
};
@@ -1,72 +0,0 @@
import { Meta, Canvas, Props } from "@storybook/addon-docs";
import { Accordion } from "../../index";
<Meta title="ds-react/accordion/intro" />
# Hvordan ta i bruk Accordion
```jsx
<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.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Aliquip amet irure consectetur occaecat</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do deserunt
amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
<Canvas>
<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.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>
Aliquip amet irure consectetur occaecat
</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do
deserunt amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</Canvas>
## Controlled state
Accordion-komponeten styrer selv open-state, men om man ønsker kan man selv overskrive denne med
`open`-prop + `onClick`-prop slik det er gjort på eksemplet.
```jsx
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={(open) => 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
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
`renderContentWhenClosed`-prop på `Accordion.Item` bestemmer om innholdet (children) skal beholdes i dom-strukturen mens
Accordion er lukket. Defaulter til `false`.
@@ -1,92 +0,0 @@
import React, { useState } from "react";
import AccordionContent from "../AccordionContent";
import AccordionHeader from "../AccordionHeader";
import AccordionItem from "../AccordionItem";
import { Accordion } from "../index";
export default {
title: "ds-react/accordion",
component: Accordion,
subcomponents: {
AccordionItem,
AccordionContent,
AccordionHeader,
},
};
export const All = () => {
const [open, setOpen] = useState(false);
return (
<>
<div>
<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>
</div>
</>
);
};
+5 -9
View File
@@ -36,13 +36,13 @@ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
const Icon = ({ variant, ...props }) => {
switch (variant) {
case "error":
return <ErrorFilled {...props} />;
return <ErrorFilled title="Feil" {...props} />;
case "warning":
return <WarningFilled {...props} />;
return <WarningFilled title="Advarsel" {...props} />;
case "info":
return <InformationFilled {...props} />;
return <InformationFilled title="Informasjon" {...props} />;
case "success":
return <SuccessFilled {...props} />;
return <SuccessFilled title="Suksess" {...props} />;
default:
return null;
}
@@ -76,11 +76,7 @@ const Alert = forwardRef<HTMLDivElement, AlertProps>(
{ "navds-alert--full-width": fullWidth, "navds-alert--inline": inline }
)}
>
<Icon
title={`${variant}-ikon`}
variant={variant}
className="navds-alert__icon"
/>
<Icon variant={variant} className="navds-alert__icon" />
<BodyLong as="div" size={size} className="navds-alert__wrapper">
{children}
</BodyLong>
@@ -1,6 +1,6 @@
import React from "react";
import { Alert } from "..";
import { BodyLong, Heading } from "../..";
import { Alert } from ".";
import { BodyLong, Heading } from "..";
export default {
title: "ds-react/alert",
@@ -1,96 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Alert, Heading, BodyLong } from "../../index";
<Meta title="ds-react/alert/intro" />
# Hvordan ta i bruk Alert
```jsx
<Alert variant="info">
Id elit esse enim reprehenderit.Tempor tempor ex exercitation id aute
eu.Laborum nulla nisi irure voluptate mollit fugiat.Est quis culpa nostrud et
reprehenderit ea sint.Eu veniam labore enim labore qui eiusmod Lorem amet ad
esse.
</Alert>
```
<Canvas>
<Alert variant="info">
Id elit esse enim reprehenderit.Tempor tempor ex exercitation id aute
eu.Laborum nulla nisi irure voluptate mollit fugiat.Est quis culpa nostrud
et reprehenderit ea sint.Eu veniam labore enim labore qui eiusmod Lorem amet
ad esse.
</Alert>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`info`, `success`, `warning` og `error`.
<Canvas>
<Alert variant="info">Id elit esse enim reprehenderit.</Alert>
<Alert variant="success">Id elit esse enim reprehenderit.</Alert>
<Alert variant="warning">Id elit esse enim reprehenderit.</Alert>
<Alert variant="error">Id elit esse enim reprehenderit.</Alert>
</Canvas>
## Sizing
Alert har to størrelser: Default 64px height og small 32px height default.
<Canvas>
<Alert size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="success">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="warning">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="error">
Id elit esse enim reprehenderit.
</Alert>
</Canvas>
## fullWidth
<Canvas>
<div style={{ margin: 32, display: "grid", gap: 16 }}>
<Alert fullWidth variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert fullWidth size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
</div>
</Canvas>
## Med heading
```jsx
<Alert variant="info">
<Heading spacing size="small" level="2">
Aliquip duis est in commodo pariatur
</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>
```
<Canvas>
<Alert variant="info">
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</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>
</Canvas>
+60 -19
View File
@@ -1,6 +1,8 @@
import React, { forwardRef } from "react";
import React, { useRef, useState, forwardRef } from "react";
import mergeRefs from "react-merge-refs";
import cl from "classnames";
import { BodyShort, OverridableComponent } from "../";
import { BodyShort, OverridableComponent, Loader } from "../";
import { useClientLayoutEffect } from "../util";
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
@@ -17,13 +19,18 @@ 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
* @default false
*/
disabled?: boolean;
/**
* Replaces button content with a Loader component, keeps width
* @default false
*/
loading?: boolean;
}
const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
@@ -34,25 +41,59 @@ const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
className,
children,
size = "medium",
loading = false,
disabled,
style,
...rest
},
ref
) => (
<Component
{...rest}
ref={ref}
className={cl(
className,
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`
)}
>
<BodyShort as="span" className="navds-button__inner" size={size}>
{children}
</BodyShort>
</Component>
)
) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
const mergedRef = mergeRefs([buttonRef, ref]);
const [widthOverride, setWidthOverride] = useState<number>();
useClientLayoutEffect(() => {
if (loading) {
const requestID = window.requestAnimationFrame(() => {
setWidthOverride(buttonRef?.current?.getBoundingClientRect()?.width);
});
return () => {
setWidthOverride(undefined);
cancelAnimationFrame(requestID);
};
}
}, [loading, children]);
return (
<Component
{...rest}
ref={mergedRef}
className={cl(
className,
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`,
{
"navds-button--loading": widthOverride,
}
)}
style={{
...style,
width: widthOverride,
}}
disabled={disabled ?? widthOverride ? true : undefined}
>
<BodyShort
as="span"
className="navds-button__inner"
size={size === "medium" ? "medium" : "small"}
aria-live="polite"
>
{widthOverride ? <Loader size={size} /> : children}
</BodyShort>
</Component>
);
}
);
export default Button;
@@ -1,10 +1,13 @@
import React from "react";
import { Button } from "../index";
import React, { useState } from "react";
import { Button } from "./index";
import { Success } from "@navikt/ds-icons";
export default {
title: "ds-react/button",
component: Button,
parameters: {
chromatic: { delay: 300 },
},
};
const Section = ({ children }) => (
@@ -37,6 +40,13 @@ const varSwitch = {
};
export const All = () => {
const [loadingState, setLoadingState] = useState(true);
const [content, setContent] = useState<string>("");
const toggleLoading = () => {
setLoadingState(!loadingState);
};
return (
<div style={{ paddingLeft: "1rem" }}>
<h1>Button</h1>
@@ -71,6 +81,14 @@ export const All = () => {
</Button>
))}
</Section>
<h2>Xsmall</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="xsmall">
{varSwitch[variant]}
</Button>
))}
</Section>
<h2>Button w/icon</h2>
<Section>
{variants.map((variant) => (
@@ -82,7 +100,7 @@ export const All = () => {
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span className="sr-only">Success ikon</span>
<span className="navds-sr-only">Success ikon</span>
<Success />
</Button>
))}
@@ -98,11 +116,42 @@ export const All = () => {
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<span className="sr-only">Success ikon</span>
<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>
);
};
@@ -1,70 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Button, Loader } from "../../index";
import { Success } from "@navikt/ds-icons";
<Meta title="ds-react/button/intro" />
# Hvordan ta i bruk Button
```jsx
<Button>Button</Button>
```
<Canvas>
<Button>Button</Button>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`primary`, `secondary`, `tertiary` og `danger`
<Canvas>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="danger">Danger</Button>
</Canvas>
## Sizing
Button har to størrelser: Default 48px min-height og small 32px min-height
<Canvas>
<Button size="small" variant="primary">
Primary
</Button>
<Button size="small" variant="secondary">
Secondary
</Button>
<Button size="small" variant="tertiary">
Tertiary
</Button>
<Button size="small" variant="danger">
Danger
</Button>
</Canvas>
## Med ikon eller `<Loader />`
Hvis man setter ikoner (svg) eller `<Loader />` rett på button vil størrelsen
bli justert automatisk og sentrert.
<Canvas>
<Button>
<Loader /> Laster... <Loader />
</Button>
<Button size="small">
<Loader />
Laster...
<Loader />
</Button>
<Button>
<Success /> Laster... <Success />
</Button>
<Button size="small">
<Success />
Laster...
<Success />
</Button>
</Canvas>
@@ -96,7 +96,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
size={size}
as="legend"
className={cl("navds-fieldset__legend", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
>
{legend}
@@ -105,7 +105,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
(size === "medium" ? (
<BodyShort
className={cl("navds-fieldset__description", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
id={inputDescriptionId}
size="small"
@@ -116,7 +116,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
) : (
<Detail
className={cl("navds-fieldset__description", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
id={inputDescriptionId}
size="small"
+3 -3
View File
@@ -63,7 +63,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
size={size}
as="label"
className={cl("navds-select__label", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
>
{label}
@@ -72,7 +72,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
<BodyShort
as="div"
className={cl("navds-select__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
@@ -94,7 +94,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
>
{children}
</select>
<Expand className="navds-select__chevron" />
<Expand className="navds-select__chevron" aria-hidden />
</div>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
+68 -7
View File
@@ -1,8 +1,35 @@
import cl from "classnames";
import React, { forwardRef, InputHTMLAttributes } from "react";
import React, {
forwardRef,
InputHTMLAttributes,
useEffect,
useState,
} from "react";
import { BodyShort, Detail, Loader, omit } from "..";
import { FormFieldProps, useFormField } from "./useFormField";
const SelectedIcon = () => (
<svg
width="12px"
height="12px"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
role="img"
aria-hidden
aria-label="Deaktiver valg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.01386 8L10.25 2L11 2.75L4.01386 9.5L1 6.5L1.75 5.75L4.01386 8Z"
fill="currentColor"
stroke="currentColor"
/>
</svg>
);
export interface SwitchProps
extends Omit<FormFieldProps, "error" | "errorId">,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
@@ -18,6 +45,10 @@ export interface SwitchProps
* Toggles loading state with loader-component on switch
*/
loading?: boolean;
/**
* Positions switch on left/right side of label
*/
position?: "left" | "right";
}
const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
@@ -29,34 +60,64 @@ const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
description,
hideLabel = false,
loading,
checked: checkedProp,
defaultChecked,
position = "left",
...rest
} = props;
const Description = size === "medium" ? BodyShort : Detail;
const [checked, setChecked] = useState(
defaultChecked ?? checkedProp ?? false
);
useEffect(() => {
checkedProp !== undefined && setChecked(checkedProp);
}, [checkedProp]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setChecked(e.target.checked);
props.onChange && props.onChange(e);
};
return (
<div
className={cl("navds-switch", props.className, `navds-switch--${size}`, {
"navds-switch--disabled": inputProps.disabled,
})}
className={cl(
"navds-switch",
props.className,
`navds-switch--${size}`,
`navds-switch--${position}`,
{
"navds-switch--loading": loading,
"navds-switch--disabled": inputProps.disabled ?? loading,
}
)}
>
<input
{...omit(rest, ["size"])}
{...omit(inputProps, ["aria-invalid", "aria-describedby"])}
disabled={inputProps.disabled ?? loading}
checked={checkedProp}
defaultChecked={defaultChecked}
ref={ref}
type="checkbox"
onChange={(e) => handleChange(e)}
className={cl(className, "navds-switch__input")}
/>
<span className="navds-switch__track">
<span className="navds-switch__thumb">
{loading && <Loader size="xsmall" />}
{loading ? (
<Loader size="xsmall" aria-live="polite" />
) : checked ? (
<SelectedIcon />
) : null}
</span>
</span>
<label htmlFor={inputProps.id} className="navds-switch__label-wrapper">
<div
className={cl("navds-switch__content", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
"navds-switch--with-description": !!description && !hideLabel,
})}
>
+5 -3
View File
@@ -62,7 +62,9 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
htmlFor={inputProps.id}
size={size}
as="label"
className={cl("navds-text-field__label", { "sr-only": hideLabel })}
className={cl("navds-text-field__label", {
"navds-sr-only": hideLabel,
})}
>
{label}
</Label>
@@ -72,7 +74,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
{size === "medium" ? (
<BodyShort
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size="small"
@@ -83,7 +85,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
) : (
<Detail
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size="small"
+3 -3
View File
@@ -77,7 +77,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
size={size}
as="label"
className={cl("navds-textarea__label", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
>
{label}
@@ -86,7 +86,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
<BodyShort
as="div"
className={cl("navds-textarea__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
@@ -113,7 +113,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
/>
{hasMaxLength && (
<>
<span id={maxLengthId} className="sr-only">
<span id={maxLengthId} className="navds-sr-only">
Tekstområde med plass til {maxLength} tegn., Textarea can have{" "}
{maxLength} signs.
</span>
@@ -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,12 @@ export interface CheckboxProps
/**
* The value of the HTML element.
*/
value?: string;
value?: any;
/**
* Specify whether the Checkbox is in an indeterminate state
* @default false
*/
indeterminate?: boolean;
}
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
@@ -50,15 +55,28 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
"error",
"description",
"hideLabel",
"indeterminate",
])}
{...inputProps}
type="checkbox"
className="navds-checkbox__input"
ref={ref}
aria-checked={props.indeterminate ? "mixed" : inputProps.checked}
ref={(el) => {
if (el) {
el.indeterminate = props.indeterminate ?? false;
}
if (typeof ref === "function") {
ref(el);
} else if (ref != null) {
ref.current = el;
}
}}
/>
<label htmlFor={inputProps.id} className="navds-checkbox__label">
<div
className={cl("navds-checkbox__content", {
"sr-only": props.hideLabel,
"navds-sr-only": props.hideLabel,
})}
>
<BodyShort as="div" size={size}>
@@ -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>
@@ -1,19 +1,52 @@
import React from "react";
import React, { useState } from "react";
import { Checkbox, CheckboxGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
import { CheckboxGroupProps } from "..";
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) => (
const Checkboxes = (
props: Omit<CheckboxGroupProps, "legend" | "description" | "children">
) => (
<CheckboxGroup
legend="Mollit eiusmod"
description="Exercitation do labore"
{...props}
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value={1}>Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
@@ -30,7 +63,7 @@ export const All = () => {
<h2>Single checkbox</h2>
<Checkbox value="Apple">Apple</Checkbox>
<h3>Desription</h3>
<Checkbox value="Apple" description="Laborum ad" defaultChecked>
<Checkbox value={1} description="Laborum ad" defaultChecked>
Apple
</Checkbox>
<h3>Error</h3>
@@ -51,6 +84,13 @@ export const All = () => {
<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 />
@@ -61,7 +101,7 @@ export const All = () => {
<h3>Small + error</h3>
<Checkboxes size="small" error="Dette er en feilmelding" />
<h3>Default value</h3>
<Checkboxes defaultValue={["Orange", "Melon"]} />
<Checkboxes defaultValue={[1, "Melon"]} />
<h3>Disabled</h3>
<Checkboxes disabled />
</>
@@ -32,16 +32,15 @@ const useCheckbox = ({ children, ...props }: CheckboxProps) => {
...rest,
inputProps: {
...inputProps,
type: "checkbox",
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);
},
},
};
+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";
+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
*/
@@ -1,23 +1,21 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { RadioGroup, Radio } from "../index";
import { RadioGroupProps } from "../RadioGroup";
export default {
title: "ds-react/form/radio",
component: RadioGroup,
} as Meta;
export const All = () => {
const Radios = (props) => (
const Radios = (props: Omit<RadioGroupProps, "legend" | "children">) => (
<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>}>
<Radio value={1}>Apple</Radio>
<Radio value={false} description={<div>Laborum ad</div>}>
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
@@ -35,13 +33,13 @@ export const All = () => {
<h2>Small + error</h2>
<Radios size="small" error="Dette er en feilmelding" />
<h2>Default value</h2>
<Radios defaultValue="Orange" />
<Radios defaultValue={1} />
<h2>Disabled</h2>
<RadioGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Radio value="Apple" disabled>
Apple
</Radio>
<Radio value="Orange" description="Laborum ad" disabled>
<Radio value={false} description="Laborum ad" disabled>
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
@@ -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", {
"sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
as="div"
className={cl("navds-text-field__description", {
"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="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="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="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="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,236 @@
import { Close } from "@navikt/ds-icons";
import cl from "classnames";
import React, {
forwardRef,
InputHTMLAttributes,
useCallback,
useEffect,
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 "tertiary"
*/
variant?: "tertiary" | "primary";
}
interface SearchComponent
extends React.ForwardRefExoticComponent<
SearchProps & React.RefAttributes<HTMLDivElement>
> {
Button: SearchButtonType;
}
export interface SearchContextProps {
disabled?: boolean;
size: "medium" | "small";
variant?: "tertiary" | "primary";
}
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 = "tertiary",
...rest
} = props;
const searchRef = useRef<HTMLInputElement | null>(null);
const mergedRef = mergeRefs([searchRef, ref]);
const [wrapperRef, setWrapperRef] = useState<HTMLFormElement | null>(null);
const [controlledValue, setControlledValue] = useState(value ?? "");
const handleChange = useCallback(
(v: string) => {
searchRef.current && value === undefined && setControlledValue(v);
props?.onChange?.(v);
},
[props, value]
);
const handleClear = useCallback(
(event: SearchClearEvent) => {
onClear?.(event);
handleChange("");
if (searchRef.current && value === undefined) {
searchRef.current.value = "";
}
searchRef.current && searchRef.current?.focus?.();
},
[handleChange, onClear, value]
);
useEventListener(
"keydown",
useCallback(
(e) => {
if (e.key === "Escape") {
e.preventDefault();
handleClear({ trigger: "Escape", event: e });
}
},
[handleClear]
),
wrapperRef
);
useEffect(() => {
value !== undefined && setControlledValue(value);
}, [value]);
return (
<form
role="search"
ref={setWrapperRef}
className={cl(
className,
"navds-form-field",
`navds-form-field--${size}`,
"navds-search",
{
"navds-search--disabled": !!inputProps.disabled,
}
)}
onSubmit={(e) => {
e.preventDefault();
onSearch?.(controlledValue);
}}
>
<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">
<input
ref={mergedRef}
{...omit(rest, ["size"])}
{...inputProps}
{...(props.value !== undefined && { value: props.value })}
onChange={(e) => handleChange(e.target.value)}
type="search"
role="searchbox"
className={cl(
className,
"navds-search__input",
"navds-text-field__input",
"navds-body-short",
`navds-body-${size ?? "medium"}`
)}
/>
{controlledValue && 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,
}}
>
{children ? children : <SearchButton />}
</SearchContext.Provider>
</div>
</form>
);
}) as SearchComponent;
Search.Button = SearchButton;
export default Search;
@@ -0,0 +1,48 @@
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 } = context;
return (
<Button
type="submit"
{...rest}
ref={ref}
size={size}
variant={variant}
className={cl("navds-search__button-search", className)}
disabled={context?.disabled ?? disabled}
onClick={(e) => 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,91 @@
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,
} as Meta;
export const All = () => {
const [value, setValue] = useState("");
return (
<div style={{ maxWidth: 300 }}>
<h1>Search</h1>
<div>
<Search
label="Søk alle sider om X og Y"
onSearch={console.log}
></Search>
<br />
<Search
label="Søk alle sider om X og Y"
onSearch={console.log}
variant="primary"
></Search>
</div>
<h2>Search small</h2>
<Search
label="Søk alle sider om X og Y"
description="Beskrivelse av søket"
size="small"
>
<Search.Button />
</Search>
<br />
<Search
label="Søk alle sider om X og Y"
description="Beskrivelse av søket"
size="small"
hideLabel
variant="primary"
>
<Search.Button />
</Search>
<h2>Med knappe-tekst</h2>
<Search label="Søk alle sider om X og Y" hideLabel={false}>
<Search.Button>Søk</Search.Button>
</Search>
<Search
label="Søk alle sider om X og Y"
hideLabel={false}
variant="primary"
>
<Search.Button>Søk</Search.Button>
</Search>
<h2>Hidelabel false</h2>
<Search label="Søk alle sider om X og Y" hideLabel={false}>
<Search.Button />
</Search>
<h2>Controlled state </h2>
<Search
value={value}
label="Søk alle sider om X og Y"
description="Beskrivelse av søket"
onChange={(e) => setValue(e)}
onClear={() => setValue("")}
>
<Search.Button />
</Search>
<h2>No clear button</h2>
<Search
hideLabel
label="Søk alle sider om X og Y"
description="Beskrivelse av søket"
clearButton={false}
>
<Search.Button />
</Search>
</div>
);
};
export const UUDemo = () => {
return (
<Search label="Søk på nav.no" onSearch={console.log} placeholder="Søk">
<Search.Button />
</Search>
);
};
@@ -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,
},
};
};
@@ -6,21 +6,70 @@ import { Switch } from "../index";
# Hvordan ta i bruk Switch
```jsx
<Switch>Slå på feature</Switch>
<Switch>Slå på feature</Switch>
<div>
<Switch position="right">Slå på feature</Switch>
</div>
```
<Canvas>
<Switch>Slå på feature</Switch>
<div>
<Switch position="right">Slå på feature</Switch>
</div>
</Canvas>
## Description
```jsx
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
<div>
<Switch position="right" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
```
<Canvas>
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
<div>
<Switch position="right" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
</Canvas>
## Position
Switch kan ha label på høyre eller venstre side. Velges med "Position"-prop "left" | "right". Husk at hvis position
"right" velges, må man selv passe på at den har en definert bredde slik at elementet ikke vises over hele skjermen.
```jsx
<div>
<div>
<h3>Feil</h3>
<Switch position="right">Slå på feature</Switch>
<h3>Riktig</h3>
<div style={{ width: 200 }}>
<Switch position="right">Slå på feature 1</Switch>
<Switch position="right">Slå på feature 2</Switch>
<Switch position="right">Slå på feature 3</Switch>
</div>
</div>
</div>
```
<Canvas>
<div>
<h3>Feil</h3>
<Switch position="right">Slå på feature</Switch>
<h3>Riktig</h3>
<div style={{ width: 300 }}>
<Switch position="right">Slå på feature 1</Switch>
<Switch position="right">Slå på feature 2</Switch>
<Switch position="right">Slå på feature 3</Switch>
</div>
</div>
</Canvas>
## Sizing
@@ -30,6 +79,9 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
```jsx
<Switch size="small" >Slå på feature</Switch>
<Switch size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
<Switch position="right" size="small" >Slå på feature</Switch>
<Switch position="right" size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
```
<Canvas>
@@ -39,6 +91,14 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
Slå på feature
</Switch>
</div>
<div>
<Switch position="right" size="small">
Slå på feature
</Switch>
<Switch position="right" size="small" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
</Canvas>
## defaultChecked
@@ -58,11 +118,21 @@ Switch er en stylet checkbox, så både `checked` og `defaultChecked` fungerer
Ved bruk av `hideLegend` på Switch kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<Switch hideLabel>Slå på feature</Switch>
<div style={{ width: 300 }}>
<Switch hideLabel>Slå på feature</Switch>
<Switch hideLabel position="right">
Slå på feature
</Switch>
</div>
```
<Canvas>
<Switch hideLabel>Slå på feature</Switch>
<div style={{ width: 300 }}>
<Switch hideLabel>Slå på feature</Switch>
<Switch hideLabel position="right">
Slå på feature
</Switch>
</div>
</Canvas>
## Disabled
@@ -9,16 +9,24 @@ export default {
export const All = () => {
const [checked, setChecked] = useState(false);
const [loadingState, setLoadingState] = useState(false);
return (
<div>
<div style={{ width: "fit-content" }}>
<h1>Switch</h1>
<Switch>Label text</Switch>
<Switch position="right">Label text</Switch>
<h2>Switch w/Description</h2>
<Switch>Label text</Switch>
<Switch description="Switch description">Label text</Switch>
<Switch>Label text</Switch>
<Switch position="right">Label text</Switch>
<Switch position="right" description="Switch description">
Label text
</Switch>
<Switch position="right">Label text</Switch>
<h2>hidelabel</h2>
<Switch description="Switch description" hideLabel>
Label text
@@ -29,6 +37,15 @@ export const All = () => {
<Switch hideLabel size="small">
Label text small
</Switch>
<Switch position="right" description="Switch description" hideLabel>
Label text
</Switch>
<Switch position="right" description="Switch description" hideLabel>
Label text
</Switch>
<Switch position="right" hideLabel size="small">
Label text small
</Switch>
<h2>Switch small</h2>
<Switch size="small">Label text</Switch>
@@ -37,6 +54,16 @@ export const All = () => {
</Switch>
<Switch size="small">Label text</Switch>
<Switch position="right" size="small">
Label text
</Switch>
<Switch position="right" description="Switch description" size="small">
Label text
</Switch>
<Switch position="right" size="small">
Label text
</Switch>
<h2>Controlled</h2>
<Switch checked={checked} onChange={() => setChecked(!checked)}>
Label text
@@ -65,6 +92,13 @@ export const All = () => {
<Switch disabled loading>
Label text
</Switch>
<Switch checked loading>
Label text
</Switch>
<button onClick={() => setLoadingState(!loadingState)}>
Toggle loading
</button>
<Switch loading={loadingState}>Label text</Switch>
</div>
);
};
+16 -14
View File
@@ -1,38 +1,40 @@
import { Helptext as HelpTextIcon } from "@navikt/ds-icons";
import { Placement } from "@popperjs/core";
import cl from "classnames";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import mergeRefs from "react-merge-refs";
import { Popover } from "..";
import { Popover, PopoverProps } from "..";
export interface HelpTextProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
Pick<PopoverProps, "strategy" | "placement"> {
/**
* Component content
*/
children: React.ReactNode;
/**
* Placement of popover
* @default "top"
*/
placement?: Placement;
}
const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
(
{ className, children, placement = "top", title = "hjelp", ...rest },
{
className,
children,
placement = "top",
strategy = "absolute",
title = "hjelp",
...rest
},
ref
) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
const mergedRef = mergeRefs([buttonRef, ref]);
const popoverRef = useRef<HTMLDivElement | null>(null);
const [popoverRef, setPopoverRef] = useState<HTMLDivElement | null>(null);
const wrapperRef = useRef<HTMLDivElement | null>(null);
const [open, setOpen] = useState(false);
useEffect(() => {
open && popoverRef.current?.focus();
}, [open]);
open && popoverRef?.focus?.();
}, [open, popoverRef]);
const handleClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
@@ -40,7 +42,6 @@ const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
setOpen((x) => !x);
rest.onClick && rest.onClick(e);
};
return (
<div className="navds-help-text" ref={wrapperRef}>
<button
@@ -57,13 +58,14 @@ const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
<span className="navds-sr-only">{title}</span>
</button>
<Popover
ref={popoverRef}
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>
+4 -1
View File
@@ -1,5 +1,4 @@
export * from "./accordion";
export * from "./accordion-menu";
export * from "./alert";
export * from "./button";
export * from "./form";
@@ -9,11 +8,15 @@ export * from "./guide-panel";
export * from "./link";
export * from "./link-panel";
export * from "./loader";
export * from "./menu";
export * from "./modal";
export * from "./pagination";
export * from "./panel";
export * from "./popover";
export * from "./speech-bubble";
export * from "./step-indicator";
export * from "./tag";
export * from "./toggle-group";
export * from "./table";
export * from "./typography";
export * from "./util";
@@ -40,10 +40,7 @@ const LinkPanelComponent: OverridableComponent<
className={cl("navds-link-panel", className)}
>
<div className="navds-link-panel__content">{children}</div>
<Next
className="navds-link-panel__chevron"
aria-label="arrow-icon pointing right"
/>
<Next className="navds-link-panel__chevron" aria-hidden />
</Panel>
);
}
@@ -63,25 +63,3 @@ Bakgrunnen kan settes til transparent med `transparent={true}`
<Canvas>
<Loader size="2xlarge" transparent />
</Canvas>
## Bruk av loader i knapper
Husk her å gi brukeren nok informasjon om hvorfor knappen har en Loader. Dette kan gjøres ved å ha god tekst på siden,
i knappen og i `title`-proppen for `Loader`. Unngå også bruk av `Loader` uten noen tekst som hinter til hva som foregår.
Stylingen er overstyrt for knapper, slik at `transparent` ikke fungerer by-default ved bruk i knapper.
Størrelsen justeres også automatisk, slik at alt man trenger er å sette Loaderen rett inn i knappen.
```jsx
<Button>
Laster inn nytt innhold...
<Loader />
</Button>
```
<Canvas>
<Button>
Laster inn nytt innhold...
<Loader />
</Button>
</Canvas>
+36
View File
@@ -0,0 +1,36 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import MenuItems from "./MenuItems";
import Item, { MenuItemType } from "./MenuItem";
import Collapse, { MenuCollapseType } from "./MenuCollapse";
export interface MenuProps extends React.HTMLAttributes<HTMLElement> {
children: React.ReactNode;
}
interface MenuComponent
extends React.ForwardRefExoticComponent<
MenuProps & React.RefAttributes<HTMLElement>
> {
Collapse: MenuCollapseType;
Item: MenuItemType;
}
const Menu = forwardRef<HTMLElement, MenuProps>(
({ children, className, ...rest }, ref) => (
<nav
{...rest}
role="navigation"
ref={ref}
className={cl("navds-menu", className)}
>
<MenuItems>{children}</MenuItems>
</nav>
)
) as MenuComponent;
Menu.Collapse = Collapse;
Menu.Item = Item;
export default Menu;
@@ -0,0 +1,80 @@
import React, {
createContext,
forwardRef,
HTMLAttributes,
useContext,
useState,
} from "react";
import cl from "classnames";
import { Expand, ExpandFilled } from "@navikt/ds-icons";
import MenuItems from "./MenuItems";
export const NestingContext = createContext<{ depth: number }>({ depth: 1 });
const NestingProvider = ({ children }) => {
const context = useContext(NestingContext);
return (
<NestingContext.Provider
value={{
depth: context.depth + 1,
}}
>
{children}
</NestingContext.Provider>
);
};
export interface MenuCollapseProps extends HTMLAttributes<HTMLDivElement> {
title: string;
defaultOpen?: boolean;
children: React.ReactNode;
}
export type MenuCollapseType = React.ForwardRefExoticComponent<
MenuCollapseProps & React.RefAttributes<HTMLDivElement>
>;
const Collapse: MenuCollapseType = forwardRef(
({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
const context = useContext(NestingContext);
return (
<div
{...rest}
ref={ref}
className={cl("navds-menu-collapse", className, {
"navds-menu-collapse--open": isOpen,
})}
>
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-menu-collapse__button"
>
{title}
<Expand
title={isOpen ? "lukk navigasjons-skuff" : "åpne navigason-skuff"}
className="navds-menu-collapse__expand-icon"
/>
<ExpandFilled
title={isOpen ? "lukk navigasjons-skuff" : "åpne navigason-skuff"}
className="navds-menu-collapse__expand-icon navds-menu-collapse__expand-icon--filled"
/>
</button>
<NestingProvider>
{isOpen && (
<MenuItems
data-depth={context.depth}
className="navds-menu__list--inner"
>
{children}
</MenuItems>
)}
</NestingProvider>
</div>
);
}
);
export default Collapse;
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
import { OverridableComponent } from "..";
import cl from "classnames";
export interface AccordionMenuItemProps
export interface MenuItemProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
children: React.ReactNode;
/**
@@ -12,12 +12,12 @@ export interface AccordionMenuItemProps
active?: boolean;
}
export type AccordionMenuItemType = OverridableComponent<
AccordionMenuItemProps,
export type MenuItemType = OverridableComponent<
MenuItemProps,
HTMLAnchorElement
>;
const Item: AccordionMenuItemType = forwardRef(
const Item: MenuItemType = forwardRef(
(
{ children, as: Component = "a", active = false, className, ...rest },
ref
@@ -25,8 +25,8 @@ const Item: AccordionMenuItemType = forwardRef(
return (
<Component
ref={ref}
className={cl("navds-accordion-menu-item", className, {
"navds-accordion-menu-item--active": active,
className={cl("navds-menu-item", className, {
"navds-menu-item--active": active,
})}
{...rest}
>
+21
View File
@@ -0,0 +1,21 @@
import cl from "classnames";
import React from "react";
const MenuItems = ({
children,
className,
...rest
}: {
children: React.ReactNode;
className?: string;
}) => (
<ul {...rest} className={cl("navds-menu__list", className)}>
{React.Children.toArray(children).map((child, i) => (
<li key={i} className="navds-menu__list-item">
{child}
</li>
))}
</ul>
);
export default MenuItems;
+3
View File
@@ -0,0 +1,3 @@
export { default as Menu, MenuProps } from "./Menu";
export { MenuCollapseProps } from "./MenuCollapse";
export { MenuItemProps } from "./MenuItem";
Loaded 100 of 164 files, more files were not shown because too many files have changed in this diff. Show more