Compare commits

...
Author SHA1 Message Date
github-actions[bot] c9adb83158 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.20
 - @navikt/ds-react@0.7.4
2021-08-20 10:00:01 +00:00
KenAndreas NordahlMagnusRom MagnusRom@users.noreply.github.com
bf079796f3 SearchField komponent (#1178)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: MagnusRom MagnusRom@users.noreply.github.com
2021-08-20 11:42:42 +02:00
Andreas Nordahl a1f4f0fe28 only allow string for checkbox value (#1181) 2021-08-20 11:40:13 +02:00
Ken f146c0c57c Update useCheckbox.ts 2021-08-20 11:36:40 +02:00
Ken fd397b03e5 La til storybook på repo forside 2021-08-20 08:10:56 +02:00
Michael Johansen 2a66f1ec6e Glemmer alltid denne lenka (#1180) 2021-08-19 16:38:19 +02:00
github-actions[bot] 2853e5cd94 Lerna versionbump [ci skip]
- @navikt/ds-react@0.7.3
2021-08-18 08:42:44 +00:00
Ken 8a068e787d oppdatert omit props (#1177) 2021-08-18 10:28:24 +02:00
Ken f8fbf6c3a8 oppdatert utdaterte stories 2021-08-18 08:37:49 +02:00
Ken 6da78d13a3 fjernet storybook plugins som ikke ble brukt 2021-08-18 08:32:12 +02:00
github-actions[bot] bc7ff31a29 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.19
 - @navikt/ds-icons@0.5.2
 - @navikt/ds-react@0.7.2
2021-08-17 08:02:27 +00:00
Ken b82afbe806 Forsøk på margin-top fix for form-elements (#1176) 2021-08-17 09:42:58 +02:00
Ken 92425cdb5b Erstattet rm -rf med rimraf for windows support (#1175) 2021-08-17 09:42:51 +02:00
github-actions[bot] 12cca3e352 Lerna versionbump [ci skip]
- @navikt/ds-icons@0.5.1
 - @navikt/ds-react@0.7.1
2021-08-13 14:21:59 +00:00
Ken 396bcfbb8a Oppdatert package-resolving for ds-react og ds-icons (#1171)
* oppdatet script

* oppdatert icons script

* endret til mjs

* oppdatert icons script

* oppdaterte ds-react script og packagehandler script

* oppdaterte versjoner

* lint fix

* oppdater ds-react imports

* oppdaterte package script
2021-08-13 16:01:11 +02:00
Ken 0a364b989a Oppdatert useId (#1172)
* oppdaterte srrprovider

* fikset useId

* oppdatert yarn lock

* fikset id-bruk i ds-react

* lint fix

* fjernet console log

* fikset story

* fikset error-uu story

* oppdatert til noop når useId kjøres på server
2021-08-13 15:49:09 +02:00
Ken 233cf0cb31 la til subheadings for mobilmeny (#1174) 2021-08-13 15:12:44 +02:00
github-actions[bot] b3d1c8429a Lerna versionbump [ci skip]
- @navikt/ds-icons@0.4.1
 - @navikt/ds-react@0.6.19
2021-08-13 08:04:15 +00:00
Ken 1b66630b08 fikset versjon for ds-icons 2021-08-13 09:47:25 +02:00
Ken a3640b4ad1 Oppdatert ikoner (#1169) 2021-08-13 09:18:32 +02:00
Ken c9092c951e nextjs example app (#1168) 2021-08-12 11:43:04 +02:00
github-actions[bot] 5761ee7213 Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.18
2021-08-12 08:39:45 +00:00
KenandAndreas Nordahl 6239d40d9c Forsøk på form aria-describedby fix (#1166)
* forsøk på fix

* bruker omit2

* Update @navikt/ds-react/src/form/Fieldset/Fieldset.tsx

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

* Update @navikt/ds-react/src/form/Fieldset/useFieldset.ts

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

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2021-08-12 10:26:03 +02:00
github-actions[bot] 4081131e1a Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.17
2021-08-12 07:44:58 +00:00
Ken a0797cbf70 laget bedre story for hideLabel 2021-08-12 09:29:18 +02:00
Ken 8f0c6948c3 hideLabel-prop for Checkbox (#1167) 2021-08-12 09:25:03 +02:00
github-actions[bot] 9dd22c2201 Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.16
2021-08-11 12:57:49 +00:00
Ken 47f174edee oppdatert props (#1164) 2021-08-11 14:40:53 +02:00
Ken 00ccebf826 Demo for uu-testing av fieldset (#1165) 2021-08-11 13:37:12 +02:00
github-actions[bot] ca3d011b54 Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.15
2021-08-11 10:23:41 +00:00
Ken da11faf790 Endret imports fra ../index -> .. i ds-react (#1161)
* oppdaterte index imports

* Revert "oppdaterte index imports"

This reverts commit a9f766965a.

* fikset storybook crashing

* fikset imports fra merge
2021-08-11 12:09:29 +02:00
github-actions[bot] 41022fb3ab Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.18
 - @navikt/ds-react@0.6.14
 - @navikt/ds-tokens@0.4.4
2021-08-11 10:04:45 +00:00
Ken 81a79de789 vnext ConfirmationPanel (Bekreftcheckboxpanel) (#1160)
* satt opp confirmation-panel

* oppdatert confirmationpanel styling

* oppdatert api

* oppdatert docs

* flyttet checkmark images til tokens
2021-08-11 11:49:15 +02:00
github-actions[bot] 1d6e33799f Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.17
 - @navikt/ds-react@0.6.13
2021-08-11 09:15:18 +00:00
KenandAndreas Nordahl 3c9187ce50 ErrorSummary (Feiloppsummering) (#1159)
* oppdatert div styling

* oppdatert storybook

* oppdatert alert styling

* fjernet ubrukt kode

* scaffolding input

* lint fix

* default styling for input

* checkbox styling

* styling for checkbox

* fikset typing for skjemaelementer

* lint fix

* fikset input

* uuid for checkbox og radio

* label + desciption på input

* select komponent og styling

* klasse på skjemaelement wrappers

* la til fieldset

* button story

* fjernet button-styling

* fjernet button story

* 44px hover-area for radio + checkbox

* lint fix

* oppdatert styling radio checkbox

* fikset checkbox hover state

* lint-fix

* oppdatert radio og fieldset css

* flyttet label styling til form

* error styling checkbox og radio

* fikset checkbox og radio sizing

* r styling

* oppdatert error styling + disabled input/select

* styling form-elementer

* error handling i checkbox

* error handling i fieldset

* error handling radio

* error handling for input + select

* form-elementer inherither size fra fieldset

* oppdatert fieldset story

* la til textarea

* oppdatert throttling i textarea

* fjernet ubbrukt css

* lint fix

* fikset files for textarea

* fikset textarea animationframe

* laget custom hook for forms

* implementerte formHook

* fikset state handling for error + input

* lint fix

* rename input -> text-input

* move error message classes to message element

* add disabled prop to text-input

* input size problem story

* expose htmlSize prop in select and text-input

* some more select story stuff

* move content in checkbox and radio from label to children

* refactor text-input

* colocate form stuff

* refactor Fieldset

* refactor textarea and move some stuff around

* extract generic field component

* checkbox rewrite wip

* more checkbox refactoring and checkbox group

* checkbox complete?

* radio group wip

* storybook fix

* fikset fieldset types

* endret til short-uiod

* bruker nå short-uuid

* prefixed id gen

* oppdatert textarea-styling

* oppdatert props i useRadio og useCheckbox

* oppdateringer rest spread radio

* reverserte bruk av useForm

* flyttet useRadio ut av radio.tsx

* oppdatert checkbox styling

* fikset small sizing checkbox

* oppdatert checkbox for ny useForm

* oppdatert use hooks for forms

* fikset disabled for checkbox og radio

* oppdatert radio, fieldset og checkbox styling

* komponenter bruker nå typo-komponenter

* endret textInput -> textField

* fikset textfield styling

* oppdatert select

* la til htmlFor for textinput og select

* oppdaterte textarea

* fikset imports

* testet løsning for gap på skjemaelementer

* fjernet ubrukt styling

* fikset props fieldset

* oppdatert fieldset

* oppdatert margins for alle forms-elementer

* oppdaterte useId for SSR

* apender aria-describedby

* hideLabel implementert for alle elementer

* fikset intern errormsg margintop i checkbox og radio

* fikset intern errormsg margintop i checkbox og radio

* comment fix

* småjuseringer props-logikk

* ryddet opp i props handlig for fieldset

* laget intro stories for alle form-elementer

* oppdatert alle form-stories

* implementert errorsummary

* fikset imports

* Fikset opp i imports (#1158)

* småfiks

* css fiks feiloppsummering

* endret på title størrelse

* fikset kommentar 1

* fikset kommentar 2

* fikset kommentar 3

* flyttet error-message til egen fil

* fikset kommenter 5

* fikset kommenter 6

* fikset kommentar 7

* fikset kommentar 8

* fikset kommentar 9

* fikset kommentar 11

* fikset kommentar 12-14

* fikset sizing

* fikset hidelabel

* Update @navikt/ds-css/form/index.css

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

* oppdatert formFieldProps

* renamet genericFormFieldProps

* ryddet opp i radiogroup

* oppdatert styling

* fikset opp i props for fieldset

* doc oppdateringer

* reverserte story-endring

* reverserte story-endring

* oppdatert omit

* fikset sizing i useFormField

* fikset i imports

* fikset imports/exports i index.ts

* fjernet forms

* Revert "fjernet forms"

This reverts commit 490f295b41.

* fikset fieldset naming error

* fikset import error

* oppdatert errorsummary

* oppdatert errorsummary props

* oppdaterte docs for errorsummary

* Update @navikt/ds-react/src/form/error-summary/ErrorSummary.tsx

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

* oppdatert css

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2021-08-11 11:00:26 +02:00
github-actions[bot] 87b4d45583 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.16
 - @navikt/ds-react@0.6.12
2021-08-10 14:05:47 +00:00
KenandAndreas Nordahl 154eab1ec6 Vnext Form fundementals (#1151)
* oppdatert div styling

* oppdatert storybook

* oppdatert alert styling

* fjernet ubrukt kode

* scaffolding input

* lint fix

* default styling for input

* checkbox styling

* styling for checkbox

* fikset typing for skjemaelementer

* lint fix

* fikset input

* uuid for checkbox og radio

* label + desciption på input

* select komponent og styling

* klasse på skjemaelement wrappers

* la til fieldset

* button story

* fjernet button-styling

* fjernet button story

* 44px hover-area for radio + checkbox

* lint fix

* oppdatert styling radio checkbox

* fikset checkbox hover state

* lint-fix

* oppdatert radio og fieldset css

* flyttet label styling til form

* error styling checkbox og radio

* fikset checkbox og radio sizing

* r styling

* oppdatert error styling + disabled input/select

* styling form-elementer

* error handling i checkbox

* error handling i fieldset

* error handling radio

* error handling for input + select

* form-elementer inherither size fra fieldset

* oppdatert fieldset story

* la til textarea

* oppdatert throttling i textarea

* fjernet ubbrukt css

* lint fix

* fikset files for textarea

* fikset textarea animationframe

* laget custom hook for forms

* implementerte formHook

* fikset state handling for error + input

* lint fix

* rename input -> text-input

* move error message classes to message element

* add disabled prop to text-input

* input size problem story

* expose htmlSize prop in select and text-input

* some more select story stuff

* move content in checkbox and radio from label to children

* refactor text-input

* colocate form stuff

* refactor Fieldset

* refactor textarea and move some stuff around

* extract generic field component

* checkbox rewrite wip

* more checkbox refactoring and checkbox group

* checkbox complete?

* radio group wip

* storybook fix

* fikset fieldset types

* endret til short-uiod

* bruker nå short-uuid

* prefixed id gen

* oppdatert textarea-styling

* oppdatert props i useRadio og useCheckbox

* oppdateringer rest spread radio

* reverserte bruk av useForm

* flyttet useRadio ut av radio.tsx

* oppdatert checkbox styling

* fikset small sizing checkbox

* oppdatert checkbox for ny useForm

* oppdatert use hooks for forms

* fikset disabled for checkbox og radio

* oppdatert radio, fieldset og checkbox styling

* komponenter bruker nå typo-komponenter

* endret textInput -> textField

* fikset textfield styling

* oppdatert select

* la til htmlFor for textinput og select

* oppdaterte textarea

* fikset imports

* testet løsning for gap på skjemaelementer

* fjernet ubrukt styling

* fikset props fieldset

* oppdatert fieldset

* oppdatert margins for alle forms-elementer

* oppdaterte useId for SSR

* apender aria-describedby

* hideLabel implementert for alle elementer

* fikset intern errormsg margintop i checkbox og radio

* fikset intern errormsg margintop i checkbox og radio

* comment fix

* småjuseringer props-logikk

* ryddet opp i props handlig for fieldset

* laget intro stories for alle form-elementer

* oppdatert alle form-stories

* Fikset opp i imports (#1158)

* fikset kommentar 1

* fikset kommentar 2

* fikset kommentar 3

* flyttet error-message til egen fil

* fikset kommenter 5

* fikset kommenter 6

* fikset kommentar 7

* fikset kommentar 8

* fikset kommentar 9

* fikset kommentar 11

* fikset kommentar 12-14

* fikset sizing

* fikset hidelabel

* Update @navikt/ds-css/form/index.css

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

* oppdatert formFieldProps

* renamet genericFormFieldProps

* ryddet opp i radiogroup

* oppdatert styling

* fikset opp i props for fieldset

* doc oppdateringer

* reverserte story-endring

* reverserte story-endring

* oppdatert omit

* fikset sizing i useFormField

* fikset i imports

* fikset imports/exports i index.ts

* fjernet forms

* Revert "fjernet forms"

This reverts commit 490f295b41.

* fikset fieldset naming error

* fikset import error

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2021-08-10 15:48:49 +02:00
0ee4fc5a6d Oppdatert innhold for "God Praksis" siden (#1157)
* flyttet innhold og component routing

* fikset linking i sider

* implementert sider fra annet repo

* fungerende redirect

* fikset redirects, manyer

* la til egen forside for vk

* oppdatert med card

* laget nye forside

* oppdatert card layout

* fikset card margin, ingress tekst

* oppdatert filter i sidebar

* fikset build error

* branch fix workflow

* fikset paths

* oppdatert sorting av sidebar

* fjernet cname fra defaut static

* fikset pathing

* fikset pathing2

* fikset config

* fikset forside

* la tilbake plugins

* fjernet border fra img

* fikset hjem pil

* edit on dev

* forsøk på classname fix

* fjernet console log

* fikset farger

* la til underline

* oppdatert styling

* fikset config

* Update build-publish.yml

* oppdatert workflow

* Create sidemaler.mdx

* Update and rename sidemaler.mdx to produktsider.mdx (#1132)

* fikset br error

* fikset table

* Create livssituasjonssider.mdx (#1133)

Co-authored-by: Ken <ken.aleksander@gmail.com>

* yarn  lock

* fikset code errors

* fikset kode for nye analytics sider

* fjernet betafiler fra publish

Co-authored-by: Sjur-NAV <82579704+Sjur-NAV@users.noreply.github.com>
2021-08-05 15:55:32 +02:00
Snyk bot 1bfb3acbdf fix: package.json to reduce vulnerabilities (#1154)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-JSZIP-1251497
2021-08-02 10:51:53 +02:00
Ken 8c0e121d66 Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.11
2021-08-02 10:30:45 +02:00
Ken 0c86b6e6b3 Fikset offset i popover (#1155) 2021-08-02 09:42:15 +02:00
github-actions[bot] 23f077d0d9 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.15
 - @navikt/ds-react@0.6.10
2021-07-28 07:31:31 +00:00
Andreas Nordahl 2be6c7b629 refactor speech-bubble-style (#1153) 2021-07-28 09:17:55 +02:00
Ken dc63423efb Update CHANGELOG.md 2021-07-18 14:51:56 +02:00
github-actions[bot] 223a328382 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.14
 - @navikt/ds-react@0.6.9
2021-07-16 13:56:44 +00:00
Ken 6450782d49 Vnext SpeechBubble (snakkeboble) (#1152) 2021-07-16 15:41:12 +02:00
Ken 1c05a87aa0 Update layout.stories.mdx 2021-07-15 09:34:35 +02:00
github-actions[bot] 286e8e7265 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.13
 - @navikt/ds-react@0.6.8
2021-07-14 13:02:15 +00:00
Ken fea8356538 Oppdatert Loader (#1150) 2021-07-14 14:48:24 +02:00
Ken 3017843435 Fikset loader eksempler i storybook 2021-07-14 11:46:56 +02:00
github-actions[bot] 5a8807cf30 Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.7
2021-07-14 09:35:27 +00:00
Ken ca7c15118f Bedre dokumentasjon for nye pakkebiblioteket i storybook (#1148) 2021-07-14 11:23:42 +02:00
github-actions[bot] 564df74c79 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.12
2021-07-13 18:09:43 +00:00
Ken 50bfca15e8 Patched button med ikon (#1147) 2021-07-13 19:57:35 +02:00
github-actions[bot] 8d0c782903 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.10
 - @navikt/ds-react@0.6.6
2021-07-13 13:48:22 +00:00
Ken b50c5c5b20 Loader (spinner) (#1146) 2021-07-13 15:34:07 +02:00
github-actions[bot] c13ae0ba42 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.9
2021-07-13 13:28:48 +00:00
Ken db3598b763 Oppdatert Button for ikonbruk (#1145) 2021-07-13 15:16:05 +02:00
github-actions[bot] bfb3d2fd04 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.8
2021-07-12 10:25:58 +00:00
Ken 9c9d69dc4a Hotfikser for ds-css styling (#1144) 2021-07-12 12:11:33 +02:00
github-actions[bot] 8fcc763ee0 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.7
2021-07-11 10:42:36 +00:00
Ken 70a202737f Merge branch 'master' of https://github.com/navikt/nav-frontend-moduler 2021-07-11 12:29:54 +02:00
Ken e91c4b5853 border-box fix for alert 2021-07-11 01:47:58 +02:00
github-actions[bot] c4588ba1d2 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.6
2021-07-10 23:30:25 +00:00
Ken 759cf51851 hotfix button errors 2021-07-11 01:17:33 +02:00
github-actions[bot] 4c5f810fdc Lerna versionbump [ci skip]
- nav-frontend-hjelpetekst@3.1.1
2021-07-09 11:44:26 +00:00
Ken ae142178ad Oppdatert hjelpetekst (#1143) 2021-07-09 13:32:02 +02:00
github-actions[bot] 74aefe9329 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.5
 - @navikt/ds-react@0.6.5
2021-07-08 13:37:45 +00:00
Ken d774cda10f Alertstripe patch (#1142) 2021-07-08 15:25:51 +02:00
github-actions[bot] 145489756d Lerna versionbump [ci skip]
- @navikt/ds-react@0.6.4
2021-07-06 18:53:10 +00:00
Ken 8df7514055 oppdatert focus + role for ikonbruk i komponenter 2021-07-06 20:37:20 +02:00
Ken 614767d5a2 oppdatert specify for icons [ci skip] 2021-07-06 17:10:14 +02:00
Ken fb23dbac85 oppdatert specify for icons [ci skip] 2021-07-06 17:00:10 +02:00
Ken 51acc59fde [ci skip] 2021-07-03 22:36:56 +02:00
Ken a18e62ec95 [ci skip] 2021-07-03 22:18:59 +02:00
Ken 9dc465dc76 Update .specifyrc.json 2021-07-03 22:12:02 +02:00
Ken ffd5023dd9 [ci skip] 2021-07-03 22:07:39 +02:00
Ken 6ae42fccef [ci skip] 2021-07-03 22:07:08 +02:00
Ken 3692c588af [CI SKIP] 2021-07-03 21:57:42 +02:00
Ken e2be70da9b Update .specifyrc.json 2021-07-03 21:51:52 +02:00
Ken dd4c90c24f Create .specifyrc.json 2021-07-03 21:47:51 +02:00
github-actions[bot] c1615a5acd Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.4
2021-07-02 19:46:26 +00:00
Ken c6aef457de Oppdatert accordion-menu styling (#1135) 2021-07-02 21:34:37 +02:00
github-actions[bot] 6f36724570 Lerna versionbump [ci skip]
- @navikt/ds-css@0.6.3
 - @navikt/ds-react@0.6.3
 - @navikt/ds-tokens@0.4.3
 - nav-frontend-ikonknapper@2.0.2
 - nav-frontend-knapper-style@2.0.2
 - nav-frontend-knapper@3.0.2
 - nav-frontend-tabell-style@2.0.2
 - nav-frontend-toggle-style@2.0.2
 - nav-frontend-toggle@2.0.2
2021-07-02 15:03:44 +00:00
Ken 91b956d8c2 Button styling + oppdatert styling for ds-react komponenter (#1134) 2021-07-02 16:50:09 +02:00
Ken c9d70ebd1c Update README.md 2021-06-24 09:02:56 +02:00
210 changed files with 10353 additions and 3149 deletions

No files matched your search

+57
View File
@@ -0,0 +1,57 @@
{
"repository": "@nav/designsystem",
"head": "updated-specify-tokens",
"base": "master",
"rules": [
{
"name": "Specify / Icons",
"path": "@navikt/ds-icons/svg",
"filter": {
"types": ["vector"]
},
"parsers": [
{
"name": "pascalcasify",
"options": {
"keys": ["name"]
}
},
{
"name": "name-assets-files-by-pattern",
"options": {
"pattern": "{{name}}.{{format}}"
}
}
]
},
{
"name": "Specify / Icons - metadata",
"path": "@navikt/ds-icons/figma-api/metadata-specify.json",
"filter": {
"types": ["vector"]
},
"parsers": [
{
"name": "pascalcasify",
"options": {
"keys": ["name"]
}
},
{
"name": "pick",
"options": {
"keys": [
"name",
"createdAt",
"updatedAt",
"meta.description",
"meta.parentFrame",
"meta.frame",
"page"
]
}
}
]
}
]
}
-2
View File
@@ -10,7 +10,6 @@ module.exports = {
"../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)",
],
addons: [
"@storybook/addon-links",
"@storybook/addon-docs",
{
name: "@storybook/addon-storysource",
@@ -27,6 +26,5 @@ module.exports = {
controls: { hideNoControlsWarning: true },
},
},
"@whitespace/storybook-addon-html",
],
};
+3 -14
View File
@@ -1,4 +1,4 @@
import { Meta } from "@storybook/addon-docs/blocks";
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-react/Kom i gang" />
@@ -11,7 +11,7 @@ yarn add @navikt/ds-react @navikt/ds-css
```
Siden stilene ikke importeres direkte i komponentene, så må man selv importere ds-css.
Dette gjøres for å la komponetene brukes i Nextjs prosjekter.
For å legge til all stylingen som trengs må man da bare importere `ds-css`.
```bash
import "@navikt/ds-css"
@@ -19,15 +19,4 @@ import "@navikt/ds-css"
Dette vil også legge css-variabler på :root. For å få dette til å fungere med IE11, kan denne pakken tas i bruk: https://jhildenbiddle.github.io/css-vars-ponyfill/#/
## Testing
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
```bash
"moduleNameMapper": {
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
}
```
Dette vil remappe komponentene (og ikonpakken) til å bruke CommonJs versjonen for testing
Note: Disse komponentene kan ikke garanteres at fungerer som forventet i IE11 da vi har valgt og ikke unngå styling-valg basert på IE11 støtte eller ikke.
+57
View File
@@ -0,0 +1,57 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-react/Roadmap" />
# Plan videre
Arbeidet med det nye pakke-oppsettet har nå foregått en stund og skulle egentlig vært
lengre på vei en det er nå. Men arbeidet har på ingen måte stoppet opp! Vi jobber kontinuerlig med
å finne bedre løsninger for å kunne bygge systemet opp fra bunnen av. Dette innegår da
ny dokumentasjons-side bygd med Sanity, nye byggeblokker helt fra token-nivå og bedre sizing for eksterne/interne sider. Dette vil da forhåpentligvis la oss
bygge mer robuste og fleksible løsninger for fremtiden.
(Rekkefølgen representer ikke faktisk tidsline eller prioritet)
## Tokens
Vi bygger opp `@navikt/ds-tokens` pakken som inneholder alle design-tokensene til designsystemet fra bunnen av.
Dette vil gjøre styling og overriding av komponenter enklere da man kan bruke css-variabler.
## Intern / Ekstern sizing
Komponenter tilpasses og standariseres bedre for skillet mellom interne/eksterne flater.
Løsning er ikke fast bestemt, men eksempel på dette er `size="s" -> 32px, size="m"-> 48px`.
Dette vil da eksempelvis kunne være en standard som er gjennomgående for de fleste komponentene.
## Ny dokumentasjon-side
Vi bygger en ny side for å dokumentere systemet, og mer rundt utvikling/design i nav med "Verktøykassen"
## Migrere komponenter/styling fra nav-frontend-\* -> `@navikt/ds-css / @navikt/ds-react`
Dette arbeidet kommer sakte men sikkert på plass, men tar litt tid da mye må på plass først, da eksempelvis sizing og tokens.
Noen komponenter vil ha oppdatert funksjonalitet, noen bare stilendringer, mens noen kan nesten brukes 1-1 fra nav-frontend-.
Note: Noen pakker vil ikke flyttes over fra nav-frontend og `deprecates` i praksis da. De pakkene som ikka tas over vil ikke bli deprecated på `npm`, slik at man kan fortsette å ta dem i bruk uten en sint terminal hver gang man kjører `yarn install`.
## Theming
Etterhvert når vi har nye react, css og token pakke på plass har vi et ønske om å kunne se på theming for
eks darkmode.
## Vue, svelte, web-components etc...
Dette er noe vi ikke har på planene for tiden, men etterhvert som ting faller på plass så vil dette være
noe vi kunne ta en titt på hvis vi ser at det trengs.
## Feature-flagging
Ideen om å ta i bruk feature-flagging er noe som virker veldig interessant og vil da se på muligheten for å kunne levere
større endringe i feature-flags for testing, og da publisere under eks major-bump i faste intervaller. Dette vil da kunne
gjøre det enklere for deg som consumer av pakkene å ha oversikt over endringer og hva som må migreres.
## Versjonering
To av de nye pakkene under `@navikt`, da `ds-css` og `ds-react` er nå versjonert under to store pakker med alle komponentene. I fremtiden vil vi se på å
ha både samversjonering (alle pakker under en eks ds-react versjon) og induvduell verjsonering da eks ds-react/button har en egen versjon
slik at man kan ha mer finkontroll over komponentbruk på siden sin.
+3
View File
@@ -0,0 +1,3 @@
# Designsystem v2
Storybook: https://navikt.github.io/Designsystemet/
+3 -10
View File
@@ -22,18 +22,11 @@
text-decoration: underline;
}
.navds-accordion-menu-collapsable .navds-accordion-menu__list,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
font-weight: var(--navds-font-weight-regular);
}
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable__button {
display: flex;
padding: var(--navds-spacing-3) var(--navds-spacing-4);
line-height: 1.5rem; /* TODO: fix typography. */
text-decoration: none;
}
.navds-accordion-menu-collapsable__expand-icon {
@@ -82,16 +75,16 @@
.navds-accordion-menu-collapsable__button:focus {
outline: 3px solid var(--navds-text-focus);
outline-offset: -3px;
color: var(--navds-color-darkgray);
}
.navds-accordion-menu-item:hover,
.navds-accordion-menu-collapsable__button:hover {
background-color: var(--navds-color-gray-20);
background-color: var(--navds-color-blue-10);
}
.navds-accordion-menu-item--active {
box-shadow: inset 0.5rem 0 var(--navds-color-text-link);
color: var(--navds-color-text);
text-decoration: none;
font-weight: var(--navds-font-weight-bold);
}
+18 -7
View File
@@ -5,14 +5,12 @@
.navds-accordion {
position: relative;
background: var(--navds-color-background);
border: var(--navds-border-default);
border-radius: 4px;
border-bottom: 2px solid #c9c9c9;
}
.navds-accordion:hover {
box-shadow: var(--navds-color-hover);
border: var(--navds-panel-hover);
color: black;
/* color: black; */
border-bottom: 2px solid var(--navds-color-blue-50);
}
.navds-accordion:focus,
@@ -39,16 +37,16 @@
.navds-accordion__button {
padding: var(--navds-spacing-4);
border-radius: 4px;
background: transparent;
border: 0;
text-align: left;
border: none;
width: 100%;
margin-bottom: 0;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
color: var(--navds-color-text-link);
}
.navds-accordion__button:hover .navds-accordion__heading {
@@ -69,3 +67,16 @@
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.navds-accordion__chevron--filled {
display: none;
}
.navds-accordion__button:hover
> .navds-accordion__chevron.navds-accordion__chevron--filled {
display: inherit;
}
.navds-accordion__button:hover > .navds-accordion__chevron {
display: none;
}
+23 -11
View File
@@ -2,21 +2,24 @@
border-radius: 4px;
border: var(--navds-border-default);
/* Padding calculated based on 16px font for 64px tall alert */
padding: 1.1875rem var(--navds-spacing-4);
/* Padding calculated based on 18px font for 64px tall alert */
padding: var(--navds-spacing-4) var(--navds-spacing-4);
display: grid;
grid-auto-flow: column;
column-gap: 0.75rem;
justify-content: start;
min-height: 64px;
box-sizing: border-box;
}
.navds-alert--s {
border-radius: 0;
padding: var(--navds-spacing-2) var(--navds-spacing-4);
padding: var(--navds-spacing-1) var(--navds-spacing-4);
min-height: 32px;
}
.navds-alert > svg {
.navds-alert > span > svg {
margin-right: var(--navds-spacing-3);
font-size: 1.5rem;
flex-shrink: 0;
background: radial-gradient(
circle,
var(--navds-color-background) 50%,
@@ -25,8 +28,17 @@
);
}
.navds-alert > div {
display: block;
margin: auto 0;
max-width: 43.5rem;
flex: 1;
}
.navds-alert > span {
margin-top: 1px;
display: flex;
align-items: center;
max-height: calc(var(--navds-spacing-8) - 2px);
}
.navds-alert--error {
@@ -34,7 +46,7 @@
background-color: var(--navds-color-error-background);
}
.navds-alert--error > svg {
.navds-alert--error > span > svg {
color: var(--navds-color-red-60);
}
@@ -43,7 +55,7 @@
background-color: var(--navds-color-warning-background);
}
.navds-alert--warning > svg {
.navds-alert--warning > span > svg {
color: var(--navds-color-orange-40);
background: radial-gradient(
circle,
@@ -58,7 +70,7 @@
background-color: var(--navds-color-info-background);
}
.navds-alert--info > svg {
.navds-alert--info > span > svg {
color: var(--navds-color-lightblue-70);
}
@@ -67,6 +79,6 @@
background-color: var(--navds-color-success-background);
}
.navds-alert--success > svg {
.navds-alert--success > span > svg {
color: var(--navds-color-green-70);
}
+10
View File
@@ -9,6 +9,16 @@
/* Disabled because of UU concerns */
/* @import "smooth-scroll.css"; */
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
font-family: var(--navds-font-family);
line-height: 1.375;
+34 -172
View File
@@ -1,5 +1,5 @@
.navds-button {
display: inline-block;
display: inline-flex;
cursor: pointer;
background-color: var(--navds-color-background);
color: var(--navds-color-action-default);
@@ -10,14 +10,38 @@
border-radius: 2px;
border-style: solid;
border-width: 2px;
min-height: 48px;
align-items: center;
/* Padding calculated based on 18px font for 44px tall button */
padding: calc(0.625rem - 2px) calc(var(--navds-spacing-8) - 2px);
padding: calc(var(--navds-spacing-3) - 2px) var(--navds-spacing-3);
}
.navds-button > svg {
font-size: 1.5rem;
width: 1.5rem;
height: 1.5rem;
}
.navds-button--s > svg {
font-size: 1.25rem;
width: 1.25rem;
height: 1.25rem;
}
.navds-button > svg + *:not(.sr-only),
.navds-button > *:not(.sr-only) + svg {
margin-left: 0.5rem;
}
/* .navds-button:last-child {
margin-left: 0.5rem;
} */
.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: calc(0.3125rem - 2px) calc(var(--navds-spacing-4) - 2px);
padding: 0.25rem calc(var(--navds-spacing-4) - 2px);
min-height: 32px;
}
.navds-button:focus {
@@ -33,16 +57,7 @@
.navds-button--primary:active {
color: var(--navds-color-text-inverse);
background-color: var(--navds-color-action-hover);
border-width: 0;
/* Padding calculated based on 18px font for 44px tall button */
padding: 0.625rem var(--navds-spacing-8);
}
.navds-button--primary:hover.navds-button--s,
.navds-button--primary:active.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: 0.3125rem var(--navds-spacing-4);
border-color: transparent;
}
.navds-button--primary:active {
@@ -86,42 +101,18 @@
.navds-button--action,
.navds-button--danger {
/* Padding calculated based on 18px font for 44px tall button */
padding: 0.625rem var(--navds-spacing-8);
border-width: 0;
transform: translateY(calc(-1 * 2px));
position: relative;
color: var(--navds-color-text-inverse);
}
.navds-button--action.navds-button--s,
.navds-button--danger.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: 0.3125rem var(--navds-spacing-4);
}
.navds-button--action:not(:focus),
.navds-button--danger:not(:focus) {
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25), 0 2px 0 rgba(0, 0, 0, 0.25);
color: white;
border-width: 1px;
}
.navds-button--action:hover {
background-color: var(--navds-color-action-hover);
border-color: var(--navds-color-action-hover);
}
.navds-button--danger:hover {
background-color: var(--navds-color-danger-hover);
}
.navds-button--danger:hover,
.navds-button--action:hover {
transform: translateY(calc(-1 * 3px));
position: relative;
}
.navds-button--action:hover:not(:focus),
.navds-button--danger:hover:not(:focus) {
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25), 0 3px 0 rgba(0, 0, 0, 0.25);
border-color: var(--navds-color-danger-hover);
}
.navds-button--action:active {
@@ -132,131 +123,9 @@
background-color: var(--navds-color-danger-active);
}
.navds-button--action:active,
.navds-button--danger:active {
transform: translateY(0);
position: relative;
}
.navds-button--action:active:not(:focus),
.navds-button--danger:active:not(:focus) {
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25), 0 0 0 rgba(0, 0, 0, 0.25);
}
.navds-button--action:focus {
color: var(--navds-color-action-default);
background-color: var(--navds-color-background);
}
.navds-button--action:focus,
.navds-button--danger:focus {
color: var(--navds-color-danger-default);
background-color: var(--navds-color-background);
}
.navds-button--danger:focus,
.navds-button--action:focus {
/* Padding calculated based on 18px font for 44px tall button */
padding: calc(0.625rem - 2px) calc(var(--navds-spacing-8) - 2px);
transform: translateY(calc(-1 * 2px));
position: relative;
border-width: 2px;
}
.navds-button--action:focus.navds-button--s,
.navds-button--danger:focus.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: calc(0.3125rem - 2px) calc(var(--navds-spacing-4) - 2px);
}
.navds-button--action:hover:focus {
background-color: var(--navds-color-action-hover);
}
.navds-button--danger:hover:focus {
background-color: var(--navds-color-danger-hover);
}
.navds-button--action:hover:focus,
.navds-button--danger:hover:focus {
/* Padding calculated based on 18px font for 44px tall button */
padding: 0.625rem var(--navds-spacing-8);
border-width: 0;
color: var(--navds-color-text-inverse);
}
.navds-button--action:hover:focus.navds-button--s,
.navds-button--danger:hover:focus.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: 0.3125rem var(--navds-spacing-4);
}
.navds-button--action:active:focus {
color: var(--navds-color-action-active);
border-color: var(--navds-color-action-active);
}
.navds-button--danger:active:focus {
color: var(--navds-color-danger-active);
border-color: var(--navds-color-danger-active);
}
.navds-button--action:active:focus,
.navds-button--danger:active:focus {
/* Padding calculated based on 18px font for 44px tall button */
padding: calc(0.625rem - 2px) calc(var(--navds-spacing-8) - 2px);
transform: translateY(0);
position: relative;
border-width: 2px;
background-color: var(--navds-color-background);
}
.navds-button--action:active:focus.navds-button--s,
.navds-button--danger:active:focus.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: calc(0.3125rem - 2px) calc(var(--navds-spacing-4) - 2px);
}
.navds-button--action:hover:focus:active {
color: var(--navds-color-text-inverse);
background-color: var(--navds-color-action-active);
}
.navds-button--danger:hover:focus:active {
color: var(--navds-color-text-inverse);
background-color: var(--navds-color-danger-active);
}
/**************************
* ::before *
**************************/
.navds-button--action::before,
.navds-button--danger::before {
bottom: calc(-1 * 2px);
height: 2px;
content: "";
display: block;
position: absolute;
left: 0;
right: 0;
}
.navds-button--action:hover::before,
.navds-button--danger:hover::before {
bottom: calc(-1 * 3px);
height: 3px;
}
.navds-button--action:focus::before,
.navds-button--danger:focus::before {
bottom: calc(-1 * 2px);
height: 2px;
}
.navds-button--action:active::before,
.navds-button--danger:active::before {
bottom: 0;
height: 0;
border-color: white;
}
/**************************
@@ -264,8 +133,6 @@
**************************/
.navds-button:disabled:disabled {
/* Padding calculated based on 18px font for 44px tall button */
padding: 0.625rem var(--navds-spacing-8);
background-color: var(--navds-color-disabled);
color: var(--navds-color-text-inverse);
cursor: not-allowed;
@@ -273,8 +140,3 @@
box-shadow: none;
transform: none;
}
.navds-button:disabled:disabled.navds-button--s {
/* Padding calculated based on 16px font for 32px tall button */
padding: 0.3125rem var(--navds-spacing-4);
}
+1
View File
@@ -3,6 +3,7 @@
align-items: center;
column-gap: 0.5em;
padding: var(--navds-spacing-1);
min-height: 32px;
}
.navds-copy-to-clipboard__popover {
+13
View File
@@ -0,0 +1,13 @@
.navds-checkbox-group--s > .navds-checkboxes {
display: flex;
flex-direction: column;
gap: 4px;
}
.navds-fieldset.navds-checkbox-group--m > .navds-checkboxes {
margin-top: 0;
}
.navds-fieldset.navds-checkbox-group--m > .navds-fieldset__error {
margin-top: 0;
}
+124
View File
@@ -0,0 +1,124 @@
.navds-checkbox {
position: relative;
padding: var(--navds-spacing-3) 0;
}
.navds-checkbox__input {
cursor: pointer;
position: absolute;
z-index: 1;
width: 48px;
height: 48px;
left: -12px;
margin: 0;
opacity: 0;
top: 0;
}
.navds-checkbox__label {
display: flex;
width: fit-content;
gap: 12px;
cursor: pointer;
}
.navds-checkbox__description {
padding-left: calc(48px - 12px);
color: var(--navds-color-gray-80);
}
.navds-checkbox--with-description {
padding-bottom: 0;
}
.navds-checkbox .navds-error-message {
margin-top: var(--navds-spacing-3);
}
.navds-checkbox--with-description .navds-error-message {
margin-top: 0;
}
.navds-checkbox--with-error-message {
padding-bottom: var(--navds-spacing-2);
}
.navds-checkbox__label::before {
content: "";
background-color: white;
border: 1px solid var(--navds-color-border);
width: 1.5rem;
height: 1.5rem;
border-radius: 4px;
flex-shrink: 0;
}
.navds-checkbox--s {
padding: var(--navds-spacing-1) 0;
}
.navds-checkbox--s > .navds-checkbox__input {
width: 24px;
height: 24px;
top: 2px;
left: 0;
}
.navds-checkbox--s > .navds-checkbox__label::before {
margin-top: -2px;
margin-bottom: -2px;
}
.navds-checkbox__input:hover + .navds-checkbox__label {
color: var(--navds-color-blue-50);
}
.navds-checkbox__input:hover + .navds-checkbox__label::before {
border-color: var(--navds-color-blue-50);
background-color: var(--navds-color-blue-10);
}
.navds-checkbox__input:focus + .navds-checkbox__label::before {
box-shadow: var(--navds-shadow-focus);
}
.navds-checkbox__input:checked + .navds-checkbox__label::before {
background-image: var(--navds-checkmark-image-white);
background-position: center center;
background-repeat: no-repeat;
background-size: 75%;
border: 2px solid var(--navds-color-blue-50);
background-color: var(--navds-color-blue-50);
}
.navds-checkbox__input:checked:focus + .navds-checkbox__label::before {
background-color: white;
background-image: var(--navds-checkmark-image-blue);
}
.navds-checkbox--error
> .navds-checkbox__input:not(:hover):not(:focus):not(:disabled):not(:checked)
+ .navds-checkbox__label::before {
box-shadow: 0 0 0 1px var(--navds-color-red-50);
border-color: var(--navds-color-red-50);
}
.navds-checkbox--s .navds-error-message {
margin-top: 4px;
}
.navds-checkbox__input:disabled,
.navds-checkbox__input:disabled + .navds-checkbox__label {
color: var(--navds-color-gray-40);
cursor: not-allowed;
}
.navds-checkbox__input:disabled + .navds-checkbox__label::before {
background-color: var(--navds-color-gray-10);
border-color: var(--navds-color-gray-60);
}
.navds-checkbox__input:disabled:checked + .navds-checkbox__label::before {
background-color: var(--navds-color-gray-40);
border-color: var(--navds-color-gray-40);
}
@@ -0,0 +1,68 @@
.navds-confirmation-panel {
display: flex;
flex-direction: column;
gap: var(--navds-spacing-4);
padding: var(--navds-spacing-4);
border-radius: 4px;
background-color: #ffeccc;
transition: background-color linear 100ms;
}
.navds-confirmation-panel__content {
max-width: 80ch;
}
.navds-confirmation-panel--s {
padding: var(--navds-spacing-3);
gap: var(--navds-spacing-2);
}
.navds-confirmation-panel--checked {
background-color: #ccf1d6;
border-color: #ccf1d6;
}
.navds-confirmation-panel--error {
background-color: #f3e3e3;
border: 1px solid transparent;
}
.navds-confirmation-panel--checked
> .navds-confirmation-panel__content
.navds-link:not(:focus) {
color: var(--navds-color-darkgray);
}
.navds-confirmation-panel
.navds-checkbox__input:hover
+ .navds-checkbox__label {
text-decoration: underline;
}
.navds-confirmation-panel--checked
.navds-checkbox__input:hover
+ .navds-checkbox__label {
color: var(--navds-color-darkgray);
}
.navds-confirmation-panel--checked
.navds-checkbox__input
+ .navds-checkbox__label::before {
transition: none;
background-color: var(--navds-color-green-50);
border-color: var(--navds-color-green-50);
background-image: var(--navds-checkmark-image-white);
}
.navds-confirmation-panel--checked
.navds-checkbox__input:hover
+ .navds-checkbox__label::before {
background-color: var(--navds-color-green-70);
border-color: var(--navds-color-green-70);
}
.navds-confirmation-panel--checked
.navds-checkbox__input:focus:hover
+ .navds-checkbox__label::before {
background-image: var(--navds-checkmark-image-white);
}
+4
View File
@@ -0,0 +1,4 @@
.navds-error-message {
display: block;
color: var(--navds-color-red-50);
}
+25
View File
@@ -0,0 +1,25 @@
.navds-error-summary {
background-color: #fff;
padding: var(--navds-spacing-4);
border: 4px solid #ba3a26;
}
.navds-error-summary--s {
padding: var(--navds-spacing-2);
}
.navds-error-summary:focus {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-error-summary__list {
margin: 1rem 0;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.navds-error-summary--s > .navds-error-summary__list {
margin: 0.5rem 0;
}
+19
View File
@@ -0,0 +1,19 @@
.navds-fieldset {
margin: 0;
padding: 0;
border: 0;
min-width: 0;
}
.navds-fieldset > :not(:first-child):not(:empty) {
margin-top: 8px;
}
.navds-fieldset--s > :not(:first-child):not(:empty) {
margin-top: 4px;
}
/* Applied when hideLegend is applied to fieldset */
.navds-fieldset > .sr-only + :not(:first-child):not(:empty) {
margin-top: 0;
}
+15
View File
@@ -0,0 +1,15 @@
.navds-form-field > :not(:first-child):not(:empty),
.navds-form-field > input:not(:first-child) {
margin-top: 8px;
}
.navds-form-field--s > :not(:first-child):not(:empty),
.navds-form-field--s > input:not(:first-child) {
margin-top: 4px;
}
/* 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) {
margin-top: 0;
}
+16
View File
@@ -0,0 +1,16 @@
/*
Order matters; rearrange with care
*/
@import "fieldset.css";
@import "form.css";
@import "error-summary.css";
@import "checkbox.css";
@import "checkbox-group.css";
@import "confirmation-panel.css";
@import "error-message.css";
@import "radio.css";
@import "radio-group.css";
@import "select.css";
@import "text-field.css";
@import "textarea.css";
@import "search-field.css";
+13
View File
@@ -0,0 +1,13 @@
.navds-radio-group--s > .navds-radio-buttons {
display: flex;
flex-direction: column;
gap: 4px;
}
.navds-fieldset.navds-radio-group--m > .navds-radio-buttons {
margin-top: 0;
}
.navds-fieldset.navds-radio-group--m > .navds-fieldset__error {
margin-top: 0;
}
+124
View File
@@ -0,0 +1,124 @@
.navds-radio {
position: relative;
padding: var(--navds-spacing-3) 0;
}
.navds-radio--with-description .navds-error-message {
margin-top: 0;
}
.navds-radio .navds-error-message {
margin-top: var(--navds-spacing-3);
}
.navds-radio__input {
cursor: pointer;
position: absolute;
z-index: 1;
width: 48px;
height: 48px;
left: -12px;
margin: 0;
opacity: 0;
top: 0;
}
.navds-radio__label {
display: flex;
width: fit-content;
gap: 12px;
min-width: 48px;
cursor: pointer;
}
.navds-radio__description {
padding-left: calc(48px - 12px);
color: var(--navds-color-gray-80);
}
.navds-radio--with-description {
padding-bottom: 0;
}
.navds-radio--with-error-message {
padding-bottom: var(--navds-spacing-2);
}
.navds-radio__label::before {
content: "";
background-color: white;
border: 1px solid var(--navds-color-border);
width: 1.5rem;
height: 1.5rem;
border-radius: 4px;
flex-shrink: 0;
border-radius: 50%;
}
.navds-radio--s {
padding: var(--navds-spacing-1) 0;
}
.navds-radio--s > .navds-radio__input {
width: 24px;
height: 24px;
top: 2px;
left: 0;
}
.navds-radio--s > .navds-radio__label::before {
margin-top: -2px;
margin-bottom: -2px;
}
.navds-radio__input:hover + .navds-radio__label {
color: var(--navds-color-blue-50);
}
.navds-radio__input:hover + .navds-radio__label::before {
border-color: var(--navds-color-blue-50);
background-color: var(--navds-color-blue-10);
}
.navds-radio__input:focus + .navds-radio__label::before {
box-shadow: var(--navds-shadow-focus);
}
.navds-radio__input:checked + .navds-radio__label::before {
border: 2px solid var(--navds-color-blue-50);
box-shadow: 0 0 0 3px #fff inset, 0 0 0 2rem var(--navds-color-blue-50) inset;
}
.navds-radio__input:checked:focus + .navds-radio__label::before {
transition: box-shadow 200ms cubic-bezier(0.465, 0.183, 0.153, 0.946);
box-shadow: 0 0 0 3px var(--navds-color-blue-80), 0 0 0 3px #fff inset,
0 0 0 2rem var(--navds-color-blue-50) inset;
}
.navds-radio--error
> .navds-radio__input:not(:hover):not(:focus):not(:disabled):not(:checked)
+ .navds-radio__label::before {
box-shadow: 0 0 0 1px var(--navds-color-red-50);
border-color: var(--navds-color-red-50);
}
.navds-radio--s .navds-error-message {
margin-top: 4px;
}
.navds-radio__input:disabled,
.navds-radio__input:disabled + .navds-radio__label {
color: var(--navds-color-gray-40);
cursor: not-allowed;
}
.navds-radio__input:disabled + .navds-radio__label::before {
background-color: var(--navds-color-gray-10);
border-color: var(--navds-color-gray-60);
}
.navds-radio__input:disabled:checked + .navds-radio__label::before {
background-color: var(--navds-color-gray-40);
border-color: var(--navds-color-gray-40);
box-shadow: 0 0 0 3px #fff inset, 0 0 0 2rem var(--navds-color-gray-40) inset;
}
+32
View File
@@ -0,0 +1,32 @@
.navds-search-field__input-wrapper {
display: flex;
}
.navds-form-field--s .navds-search-field__input {
padding: 0.25rem;
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 :focus {
z-index: 1;
}
.navds-search-field--error
.navds-search-field__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-color-red-50) inset;
border-color: var(--navds-color-red-50);
}
+62
View File
@@ -0,0 +1,62 @@
.navds-select__input {
appearance: none;
padding: 0.5rem;
background-color: white;
border-radius: 4px;
border: 1px solid var(--navds-color-gray-40);
width: 100%;
box-sizing: border-box;
min-height: 48px;
display: inline-block;
position: relative;
padding-right: 2.5rem;
}
.navds-select__input:hover {
border-color: var(--navds-color-blue-50);
}
.navds-select__input:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
}
.navds-select__container {
position: relative;
display: flex;
width: 100%;
align-items: center;
}
.navds-select__chevron {
position: absolute;
font-size: 1rem;
right: 0.5rem;
pointer-events: none;
}
.navds-form-field--s .navds-select__input {
min-height: 32px;
padding: 0.25rem;
}
/**
Error handling
*/
.navds-select--error > * select:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-color-red-50);
border-color: var(--navds-color-red-50);
}
/*
Disabled handling
TODO: Oppdatere farger her
*/
.navds-select__input:disabled,
.navds-select__input[read-only] {
background-color: var(--navds-color-gray-10);
border-color: var(--navds-color-gray-40);
box-shadow: none;
color: var(--navds-color-darkgray);
cursor: not-allowed;
}
+45
View File
@@ -0,0 +1,45 @@
.navds-text-field__input {
appearance: none;
padding: 0.5rem;
background-color: white;
border-radius: 4px;
border: 1px solid var(--navds-color-border);
min-height: 48px;
width: 100%;
}
.navds-form-field--s > .navds-text-field__input {
padding: 0.25rem;
min-height: 32px;
}
.navds-text-field__input:hover {
border-color: var(--navds-color-blue-50);
}
.navds-text-field__input:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
}
/**
Error handling
*/
.navds-text-field--error
> .navds-text-field__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-color-red-50);
border-color: var(--navds-color-red-50);
}
/*
TODO: Oppdater denne til riktige farger
Disabled handling
*/
.navds-text-field__input:disabled,
.navds-text-field__input[readonly] {
background-color: #f1f1f1;
border-color: #6a6a6a;
box-shadow: none;
color: #262626;
cursor: not-allowed;
}
+76
View File
@@ -0,0 +1,76 @@
.navds-textarea__wrapper {
position: relative;
width: 100%;
}
.navds-textarea__input {
appearance: none;
padding: var(--navds-spacing-2);
background-color: white;
border-radius: 4px;
border: 1px solid var(--navds-color-border);
resize: none;
width: 100%;
transition: height 0.1s ease-out;
display: block;
min-height: 48px;
}
.navds-textarea--counter {
padding-bottom: var(--navds-spacing-8);
}
.navds-textarea__input:hover {
border-color: var(--navds-color-blue-50);
}
.navds-textarea__input:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
}
.navds-form-field--s .navds-textarea__input {
padding: var(--navds-spacing-1);
min-height: 32px;
}
.navds-form-field--s .navds-textarea--counter.navds-textarea__input {
padding-bottom: var(--navds-spacing-7);
}
.navds-textarea__counter {
pointer-events: none;
color: var(--navds-color-gray-40);
font-style: italic;
position: absolute;
text-align: right;
left: var(--navds-spacing-3);
right: var(--navds-spacing-3);
bottom: var(--navds-spacing-2);
}
.navds-textarea__counter--error {
color: var(--navds-color-red-50);
}
/**
Error handling
*/
.navds-textarea--error
.navds-textarea__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-color-red-50);
border-color: var(--navds-color-red-50);
}
/*
TODO: Oppdater denne til riktige farger
Disabled handling
*/
.navds-textarea__input:disabled,
.navds-textarea__input[readonly] {
background-color: #f1f1f1;
border-color: #6a6a6a;
box-shadow: none;
color: #262626;
cursor: not-allowed;
}
+3
View File
@@ -13,9 +13,12 @@
@import "copy-to-clipboard.css";
@import "header.css";
@import "internal-header.css";
@import "form/index.css";
@import "link.css";
@import "loader.css";
@import "modal.css";
@import "popover.css";
@import "tag.css";
@import "panel.css";
@import "link-panel.css";
@import "speech-bubble.css";
+105
View File
@@ -0,0 +1,105 @@
.navds-loader {
width: 1.5rem;
display: inline-block;
position: relative;
animation: loader-rotate 1.4s linear infinite;
}
.navds-loader__foreground {
animation: loader-dasharray 1.4s ease-in-out infinite;
stroke-dasharray: 80px, 200px;
stroke-dashoffset: 0;
stroke: var(--navds-color-gray-40);
}
.navds-loader__background {
stroke: var(--navds-color-gray-10);
}
.navds-loader--neutral .navds-loader__foreground {
stroke: var(--navds-color-gray-40);
}
.navds-loader--interaction .navds-loader__foreground {
stroke: var(--navds-color-blue-50);
}
.navds-loader--inverted .navds-loader__foreground {
stroke: white;
}
.navds-loader--inverted .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
}
.navds-loader--transparent .navds-loader__background {
stroke: transparent;
}
.navds-loader--2xl {
width: 4rem;
}
.navds-loader--xl {
width: 2.5rem;
}
.navds-loader--l {
width: 2rem;
}
.navds-loader--m {
width: 1.5rem;
}
.navds-loader--s {
width: 1.25rem;
}
.navds-loader--xs {
width: 1rem;
}
/*
* Button spesific styling
*/
.navds-button .navds-loader .navds-loader__foreground {
stroke: currentColor;
}
.navds-button:hover .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
}
.navds-button:active .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
}
.navds-button--action .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
}
@keyframes loader-rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes loader-dasharray {
0% {
stroke-dasharray: 1px, 200px;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 100px, 200px;
stroke-dashoffset: -15px;
}
100% {
stroke-dasharray: 100px, 200px;
stroke-dashoffset: -120px;
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.6.2",
"version": "0.6.20",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
@@ -21,7 +21,7 @@
"watch-css": "postcss -w --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^0.4.2",
"@navikt/ds-tokens": "^0.4.4",
"normalize.css": "^8.0.1",
"postcss": "^8.2.7",
"postcss-cli": "^8.3.1",
+69
View File
@@ -0,0 +1,69 @@
.navds-speechbubble {
display: flex;
align-items: flex-end;
gap: var(--navds-spacing-4);
}
.navds-speechbubble--right {
flex-direction: row-reverse;
}
.navds-speechbubble__bubble-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--navds-spacing-3);
}
.navds-speechbubble--right .navds-speechbubble__bubble-list {
align-items: flex-end;
}
.navds-speechbubble__illustration {
align-items: center;
background: var(--navds-color-gray-20);
color: var(--navds-color-darkgray);
border-radius: 50%;
display: flex;
flex-shrink: 0;
justify-content: center;
overflow: hidden;
height: 3rem;
width: 3rem;
}
.navds-speechbubble__illustration svg {
align-self: center;
height: 100%;
width: 100%;
}
.navds-speechbubble__bubble {
padding: 1rem;
box-shadow: 0 2px 4px 0 var(--navds-color-gray-20);
width: fit-content;
max-width: 37.5rem;
background-color: var(--navds-color-gray-10);
border-radius: 12px;
border-bottom-left-radius: 2px;
display: flex;
flex-direction: column;
gap: var(--navds-spacing-2);
}
.navds-speechbubble__bubble:focus {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-speechbubble--right .navds-speechbubble__bubble {
border-radius: 12px;
border-bottom-right-radius: 2px;
align-items: flex-end;
}
.navds-speechbubble__top-text {
color: var(--navds-color-gray-60);
}
-6
View File
@@ -1,6 +0,0 @@
{
"type": "commonjs",
"main": "index.js",
"typings": "../esm/index.d.ts",
"sideEffects": false
}
File renamed without changes.
File renamed without changes.
+61 -45
View File
@@ -11,7 +11,7 @@
"name": "AddCircle",
"description": "",
"created_at": "2020-07-01T10:37:42.784Z",
"updated_at": "2021-04-09T13:32:16.308Z",
"updated_at": "2021-08-12T11:15:52.168Z",
"pageName": "Interface",
"visible": true
},
@@ -32,18 +32,18 @@
"visible": true
},
{
"name": "AddPeople",
"name": "AddPerson",
"description": "",
"created_at": "2021-06-15T15:06:55.651Z",
"updated_at": "2021-06-15T15:06:55.651Z",
"updated_at": "2021-08-13T06:33:04.695Z",
"pageName": "People",
"visible": true
},
{
"name": "AddPeopleFilled",
"name": "AddPersonFilled",
"description": "",
"created_at": "2021-06-15T15:06:55.654Z",
"updated_at": "2021-06-15T15:06:55.654Z",
"updated_at": "2021-08-13T06:33:04.683Z",
"pageName": "People",
"visible": true
},
@@ -107,7 +107,7 @@
"name": "Back",
"description": "",
"created_at": "2020-07-01T10:37:42.840Z",
"updated_at": "2021-04-09T13:32:23.607Z",
"updated_at": "2021-08-12T14:51:21.441Z",
"pageName": "Chevron",
"visible": true
},
@@ -123,7 +123,7 @@
"name": "Bag",
"description": "",
"created_at": "2020-07-01T10:37:42.673Z",
"updated_at": "2021-06-14T07:21:59.055Z",
"updated_at": "2021-08-13T09:47:23.613Z",
"pageName": "Jobs",
"visible": true
},
@@ -203,7 +203,7 @@
"name": "Bookmark",
"description": "",
"created_at": "2020-07-01T10:37:42.877Z",
"updated_at": "2021-04-09T13:32:23.611Z",
"updated_at": "2021-08-12T12:32:34.047Z",
"pageName": "File",
"visible": true
},
@@ -251,7 +251,7 @@
"name": "Calculator",
"description": "",
"created_at": "2020-07-01T10:37:42.917Z",
"updated_at": "2021-06-14T07:21:59.043Z",
"updated_at": "2021-08-12T12:31:15.652Z",
"pageName": "Money",
"visible": true
},
@@ -395,7 +395,7 @@
"name": "Clock",
"description": "",
"created_at": "2020-07-01T10:37:42.647Z",
"updated_at": "2021-04-09T13:32:23.334Z",
"updated_at": "2021-08-13T07:30:12.128Z",
"pageName": "Time",
"visible": true
},
@@ -411,7 +411,7 @@
"name": "Close",
"description": "",
"created_at": "2020-07-01T10:37:42.827Z",
"updated_at": "2021-04-09T13:32:16.911Z",
"updated_at": "2021-08-12T13:19:34.922Z",
"pageName": "Interface",
"visible": true
},
@@ -419,7 +419,7 @@
"name": "CloseFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.364Z",
"updated_at": "2021-04-09T13:32:16.624Z",
"updated_at": "2021-08-12T10:54:40.891Z",
"pageName": "Interface",
"visible": true
},
@@ -427,7 +427,7 @@
"name": "CoApplicant",
"description": "",
"created_at": "2021-04-30T10:55:32.823Z",
"updated_at": "2021-04-30T10:55:32.823Z",
"updated_at": "2021-08-13T09:47:48.809Z",
"pageName": "People",
"visible": true
},
@@ -507,7 +507,7 @@
"name": "Copy",
"description": "",
"created_at": "2020-07-01T10:37:42.619Z",
"updated_at": "2021-05-05T12:44:31.388Z",
"updated_at": "2021-08-12T12:36:11.164Z",
"pageName": "File",
"visible": true
},
@@ -567,6 +567,14 @@
"pageName": "File",
"visible": true
},
{
"name": "Decision",
"description": "",
"created_at": "2021-08-13T06:33:04.661Z",
"updated_at": "2021-08-13T06:33:04.661Z",
"pageName": "People",
"visible": true
},
{
"name": "DecisionCheck",
"description": "",
@@ -591,6 +599,14 @@
"pageName": "People",
"visible": true
},
{
"name": "DecisionFilled",
"description": "",
"created_at": "2021-08-13T06:33:04.665Z",
"updated_at": "2021-08-13T06:33:04.665Z",
"pageName": "People",
"visible": true
},
{
"name": "Delete",
"description": "",
@@ -619,7 +635,7 @@
"name": "DialogDots",
"description": "",
"created_at": "2020-07-01T10:37:43.133Z",
"updated_at": "2021-04-09T13:32:23.486Z",
"updated_at": "2021-08-12T11:19:13.127Z",
"pageName": "Communication",
"visible": true
},
@@ -875,7 +891,7 @@
"name": "EmployerFilled",
"description": "",
"created_at": "2021-01-22T13:40:32.293Z",
"updated_at": "2021-04-22T08:46:31.424Z",
"updated_at": "2021-08-13T06:33:04.692Z",
"pageName": "People",
"visible": true
},
@@ -931,7 +947,7 @@
"name": "Eye",
"description": "",
"created_at": "2020-07-01T10:37:42.895Z",
"updated_at": "2021-04-09T13:32:23.514Z",
"updated_at": "2021-08-12T09:55:24.102Z",
"pageName": "Privacy",
"visible": true
},
@@ -939,7 +955,7 @@
"name": "EyeFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.321Z",
"updated_at": "2021-04-09T13:32:16.996Z",
"updated_at": "2021-08-12T09:55:25.386Z",
"pageName": "Privacy",
"visible": true
},
@@ -947,7 +963,7 @@
"name": "EyeScreened",
"description": "",
"created_at": "2020-07-01T10:37:42.956Z",
"updated_at": "2021-04-09T13:32:23.351Z",
"updated_at": "2021-08-12T09:56:29.536Z",
"pageName": "Privacy",
"visible": true
},
@@ -955,7 +971,7 @@
"name": "EyeScreenedFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.578Z",
"updated_at": "2021-04-09T13:32:23.419Z",
"updated_at": "2021-08-12T09:55:47.137Z",
"pageName": "Privacy",
"visible": true
},
@@ -1107,7 +1123,7 @@
"name": "Findout",
"description": "",
"created_at": "2021-05-05T13:04:25.502Z",
"updated_at": "2021-05-05T13:04:25.502Z",
"updated_at": "2021-08-12T12:32:46.082Z",
"pageName": "File",
"visible": true
},
@@ -1139,7 +1155,7 @@
"name": "Folder",
"description": "",
"created_at": "2020-07-01T10:37:42.682Z",
"updated_at": "2021-04-09T13:32:23.439Z",
"updated_at": "2021-08-13T07:30:12.108Z",
"pageName": "File",
"visible": true
},
@@ -1267,7 +1283,7 @@
"name": "HandBandage",
"description": "",
"created_at": "2020-07-01T10:37:42.711Z",
"updated_at": "2021-04-09T13:32:16.442Z",
"updated_at": "2021-08-13T09:48:45.392Z",
"pageName": "Health",
"visible": true
},
@@ -1379,7 +1395,7 @@
"name": "Helmet",
"description": "",
"created_at": "2020-07-01T10:37:42.793Z",
"updated_at": "2021-04-09T13:32:23.412Z",
"updated_at": "2021-08-13T09:49:01.868Z",
"pageName": "Jobs",
"visible": true
},
@@ -1491,7 +1507,7 @@
"name": "Information",
"description": "",
"created_at": "2020-07-01T10:37:43.005Z",
"updated_at": "2021-04-09T13:32:16.578Z",
"updated_at": "2021-08-12T12:35:33.631Z",
"pageName": "Status",
"visible": true
},
@@ -1499,7 +1515,7 @@
"name": "InformationFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.736Z",
"updated_at": "2021-04-09T13:32:16.132Z",
"updated_at": "2021-08-12T11:36:44.756Z",
"pageName": "Status",
"visible": true
},
@@ -1531,7 +1547,7 @@
"name": "LawFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.330Z",
"updated_at": "2021-04-09T13:32:16.725Z",
"updated_at": "2021-08-13T09:50:59.913Z",
"pageName": "Privacy",
"visible": true
},
@@ -1539,7 +1555,7 @@
"name": "Left",
"description": "",
"created_at": "2020-07-01T10:37:42.797Z",
"updated_at": "2021-04-09T13:32:23.354Z",
"updated_at": "2021-08-13T06:33:04.688Z",
"pageName": "Arrow",
"visible": true
},
@@ -1619,7 +1635,7 @@
"name": "Locked",
"description": "",
"created_at": "2020-07-01T10:37:43.027Z",
"updated_at": "2021-04-09T13:32:23.385Z",
"updated_at": "2021-08-12T09:56:54.295Z",
"pageName": "Privacy",
"visible": true
},
@@ -1715,7 +1731,7 @@
"name": "MinusCircleFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.721Z",
"updated_at": "2021-04-09T13:32:16.246Z",
"updated_at": "2021-08-12T10:26:25.789Z",
"pageName": "Interface",
"visible": true
},
@@ -1731,7 +1747,7 @@
"name": "Mobile",
"description": "",
"created_at": "2020-07-01T10:37:43.010Z",
"updated_at": "2021-04-09T13:32:16.508Z",
"updated_at": "2021-08-12T11:19:05.339Z",
"pageName": "Device",
"visible": true
},
@@ -1747,7 +1763,7 @@
"name": "Money",
"description": "",
"created_at": "2020-07-01T10:37:42.741Z",
"updated_at": "2021-04-09T13:32:23.388Z",
"updated_at": "2021-08-12T12:31:01.092Z",
"pageName": "Money",
"visible": true
},
@@ -1891,7 +1907,7 @@
"name": "Office1",
"description": "",
"created_at": "2020-07-01T10:37:42.720Z",
"updated_at": "2021-04-09T13:32:23.456Z",
"updated_at": "2021-08-12T12:56:17.625Z",
"pageName": "Building",
"visible": true
},
@@ -1987,7 +2003,7 @@
"name": "People",
"description": "",
"created_at": "2020-07-01T10:37:42.850Z",
"updated_at": "2021-04-09T13:32:23.661Z",
"updated_at": "2021-08-12T11:17:04.979Z",
"pageName": "People",
"visible": true
},
@@ -2115,7 +2131,7 @@
"name": "Profile",
"description": "",
"created_at": "2021-04-26T09:24:38.029Z",
"updated_at": "2021-04-30T10:55:32.846Z",
"updated_at": "2021-08-12T12:32:56.285Z",
"pageName": "File",
"visible": true
},
@@ -2147,7 +2163,7 @@
"name": "Receipt",
"description": "",
"created_at": "2020-07-01T10:37:42.904Z",
"updated_at": "2021-04-09T13:32:23.649Z",
"updated_at": "2021-08-12T12:29:47.091Z",
"pageName": "Money",
"visible": true
},
@@ -2227,7 +2243,7 @@
"name": "Right",
"description": "",
"created_at": "2020-07-01T10:37:42.642Z",
"updated_at": "2021-04-09T13:32:23.409Z",
"updated_at": "2021-08-12T07:14:26.093Z",
"pageName": "Arrow",
"visible": true
},
@@ -2259,7 +2275,7 @@
"name": "Sandglass",
"description": "",
"created_at": "2020-07-01T10:37:43.117Z",
"updated_at": "2021-04-09T13:32:23.313Z",
"updated_at": "2021-08-12T08:18:12.598Z",
"pageName": "Time",
"visible": true
},
@@ -2323,7 +2339,7 @@
"name": "Search",
"description": "",
"created_at": "2020-07-01T10:37:42.983Z",
"updated_at": "2021-04-09T13:32:16.382Z",
"updated_at": "2021-08-12T12:37:22.919Z",
"pageName": "Interface",
"visible": true
},
@@ -2387,7 +2403,7 @@
"name": "Send",
"description": "",
"created_at": "2020-07-01T10:37:43.101Z",
"updated_at": "2021-04-09T13:32:23.596Z",
"updated_at": "2021-08-13T07:30:12.151Z",
"pageName": "Communication",
"visible": true
},
@@ -2403,7 +2419,7 @@
"name": "Service",
"description": "",
"created_at": "2020-07-01T10:37:42.707Z",
"updated_at": "2021-06-14T07:21:59.047Z",
"updated_at": "2021-08-12T11:15:52.145Z",
"pageName": "People",
"visible": true
},
@@ -2675,7 +2691,7 @@
"name": "SuccessStroke",
"description": "",
"created_at": "2021-04-15T07:12:49.753Z",
"updated_at": "2021-04-15T07:12:49.753Z",
"updated_at": "2021-08-12T11:30:36.177Z",
"pageName": "Status",
"visible": true
},
@@ -2755,7 +2771,7 @@
"name": "ThermometerStroke",
"description": "",
"created_at": "2021-04-07T12:13:28.179Z",
"updated_at": "2021-04-09T13:32:16.814Z",
"updated_at": "2021-08-12T12:34:12.825Z",
"pageName": "Health",
"visible": true
},
@@ -2811,7 +2827,7 @@
"name": "Unlocked",
"description": "",
"created_at": "2020-07-01T10:37:42.823Z",
"updated_at": "2021-04-09T13:32:16.901Z",
"updated_at": "2021-08-12T09:56:56.564Z",
"pageName": "Privacy",
"visible": true
},
@@ -2843,7 +2859,7 @@
"name": "Upload",
"description": "",
"created_at": "2020-07-01T10:37:43.046Z",
"updated_at": "2021-04-09T13:32:23.685Z",
"updated_at": "2021-08-13T07:41:40.719Z",
"pageName": "Attachment",
"visible": true
},
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "0.3.3",
"version": "0.5.2",
"private": false,
"description": "NAVs egne ikoner i SVG og React format",
"repository": {
@@ -14,11 +14,10 @@
],
"license": "MIT",
"author": "NAV",
"main": "esm/index.js",
"module": "esm/index.js",
"typings": "esm/index.d.ts",
"sideEffects": false,
"type": "module",
"main": "./cjs/index.js",
"module": "./esm/index.js",
"typings": "./esm/index.d.ts",
"files": [
"/cjs",
"/esm",
@@ -26,12 +25,13 @@
"/svg"
],
"scripts": {
"cjs-package": "copyfiles -f config/package.json cjs",
"dl-icons": "FILE_KEY=UmEVH3pZ71uJPsSz9ilP3Y node --experimental-modules --es-module-specifier-resolution=node -r dotenv/config figma-api/index.js dotenv_config_path=figma-api/.env",
"create-package-json-pointers-to-esm": "node ../../utilities/scripts/createPackageJsonsWithESMPointers.js",
"dl-icons": "FILE_KEY=UmEVH3pZ71uJPsSz9ilP3Y node --experimental-modules --es-module-specifier-resolution=node -r dotenv/config figma-api/index.mjs dotenv_config_path=figma-api/.env",
"create-icons": "svgr --silent --typescript --ref --icon --title-prop --replace-attr-values \"#262626=currentColor\" -d src svg",
"convert-icons": "node figma-api/pngConverter.js",
"clean": "rm -rf src && rm -rf esm && rm -rf cjs && rm -rf png && rm -rf NAV-ikonpakke-png.zip && rm -rf NAV-ikonpakke-svg.zip",
"build": "npm run clean && npm run create-icons && tsc && tsc -p tsconfig-esm.json && yarn cjs-package && npm run convert-icons && node figma-api/zipIcons.js"
"convert-icons": "node figma-api/pngConverter.mjs",
"clean": "rimraf src esm cjs png NAV-ikonpakke-png.zip NAV-ikonpakke-svg.zip",
"zip-icons": "node figma-api/zipIcons.mjs",
"build": "npm run clean && npm run create-icons && tsc && tsc -p tsconfig-esm.json && yarn create-package-json-pointers-to-esm && npm run convert-icons && yarn zip-icons"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
+4 -15
View File
@@ -1,10 +1,10 @@
import { Meta } from "@storybook/addon-docs/blocks";
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/resources/icons
Alle ikoner kan bli funnet her https://design.nav.no/designsystem/resources/icons
## Oppsett
@@ -12,7 +12,7 @@ Alle ikoner kan bli funnet her https://design.nav.no/resources/icons
yarn add @navikt/ds-icons
```
```bash
```jsx
Import { Expand } from `@navikt/ds-icons`;
<Expand
@@ -22,15 +22,4 @@ Import { Expand } from `@navikt/ds-icons`;
/>
```
## Testing
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
```bash
"moduleNameMapper": {
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
}
```
Dette vil remappe Ikonpakken (og komponentpakken) til å bruke CommonJs versjonen for testing
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.
File renamed without changes.
+5
View File
@@ -0,0 +1,5 @@
<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="M10.9565 8C12.6134 8 13.9565 6.65685 13.9565 5C13.9565 3.34315 12.6134 2 10.9565 2C9.29969 2 7.95654 3.34315 7.95654 5C7.95654 6.65685 9.29969 8 10.9565 8ZM10.9565 10C13.718 10 15.9565 7.76142 15.9565 5C15.9565 2.23858 13.718 0 10.9565 0C8.19512 0 5.95654 2.23858 5.95654 5C5.95654 7.76142 8.19512 10 10.9565 10Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0569 11.5858C19.2758 10.8047 18.0095 10.8047 17.2285 11.5858L15.8143 13C15.0332 13.781 15.0332 15.0474 15.8143 15.8284L16.6856 16.6997L12.1071 21.2782L11.4 21.9853L12.8142 23.3995L13.5213 22.6924L18.0998 18.114L19.0496 19.0637C19.8306 19.8448 21.0969 19.8448 21.878 19.0637L23.2922 17.6495C24.0733 16.8685 24.0733 15.6021 23.2922 14.8211L20.0569 11.5858ZM18.6427 13L21.878 16.2353L20.4638 17.6495L17.2285 14.4142L18.6427 13Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1594 11.7521C13.2095 11.2709 12.1352 11 11 11C7.13401 11 4 14.134 4 18H6C6 15.2386 8.23858 13 11 13C11.5609 13 12.0993 13.092 12.6014 13.2617L14.1594 11.7521Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+4
View File
@@ -0,0 +1,4 @@
<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 5C16 7.76142 13.7614 10 11 10C8.23858 10 6 7.76142 6 5C6 2.23858 8.23858 0 11 0C13.7614 0 16 2.23858 16 5ZM4 18C4 14.134 7.13401 11 11 11C12.3956 11 13.6959 11.4084 14.7877 12.1123L8.7108 18H4Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.2782 12.2854C18.8876 11.9049 18.2545 11.9049 17.8639 12.2854L15.3891 14.6973C14.9985 15.0778 14.9985 15.6949 15.3891 16.0754L16.8033 17.4536L11.5 22.6218L12.9142 24L18.2175 18.8318L19.8085 20.3823C20.199 20.7628 20.8322 20.7628 21.2227 20.3823L23.6976 17.9704C24.0881 17.5899 24.0881 16.9728 23.6976 16.5923L19.2782 12.2854Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 764 B

-6
View File
@@ -1,6 +0,0 @@
{
"type": "commonjs",
"main": "index.js",
"typings": "../esm/index.d.ts",
"sideEffects": false
}
+12 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.6.2",
"version": "0.7.4",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
@@ -14,11 +14,10 @@
"type": "git",
"url": "git+https://github.com/navikt/nav-frontend-moduler/tree/master/%40navikt/ds-react"
},
"main": "esm/index.js",
"module": "esm/index.js",
"typings": "esm/index.d.ts",
"sideEffects": false,
"type": "module",
"main": "./cjs/index.js",
"module": "./esm/index.js",
"typings": "./esm/index.d.ts",
"publishConfig": {
"access": "public"
},
@@ -28,13 +27,14 @@
"/src"
],
"scripts": {
"cjs-package": "copyfiles -f config/package.json cjs",
"clean": "rm -rf cjs esm",
"build": "yarn run clean && tsc && tsc -p tsconfig-esm.json && yarn cjs-package",
"create-package-json-pointers-to-esm": "node ../../utilities/scripts/createPackageJsonsWithESMPointers.js",
"clean": "rimraf cjs esm",
"build": "yarn run clean && tsc && tsc -p tsconfig-esm.json && yarn create-package-json-pointers-to-esm",
"watch": "tsc --watch -p tsconfig-esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^0.3.3",
"@material-ui/core": "^4.12.2",
"@navikt/ds-icons": "^0.5.2",
"@popperjs/core": "^2.5.4",
"classnames": "^2.2.6",
"copy-to-clipboard": "^3.3.1",
@@ -42,11 +42,12 @@
"react-merge-refs": "^1.1.0",
"react-modal": "3.12.1",
"react-popper": "^2.2.4",
"uuid": "^8.3.2"
"short-uuid": "^4.2.0"
},
"devDependencies": {
"copyfiles": "^2.4.1",
"react-router-dom": "^5.2.0"
"react-router-dom": "^5.2.0",
"rimraf": "3.0.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
@@ -1,6 +1,6 @@
import React, { forwardRef, HTMLAttributes } from "react";
import { AccordionMenu as BaseAccordionMenu } from "../accordion-menu";
import { Title } from "../index";
import { Title } from "..";
import { ActiveAnchorProvider } from "./ActiveAnchorStore";
import cl from "classnames";
@@ -8,7 +8,6 @@ export interface AccordionAnchorMenuProps
extends HTMLAttributes<HTMLDivElement> {
title?: string;
children: React.ReactNode;
className?: string;
}
const AccordionAnchorMenu = forwardRef<
@@ -0,0 +1,14 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { AccordionAnchorMenu } from "../../index";
import { Success } from "@navikt/ds-react";
<Meta title="ds-react/accordion-anchor-menu/intro" />
# AccordionAnchorMenu
NOTE: Komponenten er ikke oppdatert og er veldig buggy. Ville ungått bruk av denne om mulig og bare brukt
vanlig `AccordionMenu`. Hvorvidt vi kommer til å oppdatere denne og ta den med i 1.0 er usikkert.
`AccordionAnchorMenu` er en meny-komponent som implementerer `AccordionMenu` med context
for lytting på aktiv anchor/heading. Dette vil si at active-state settes automatisk.
når man scroller forbi den relevante linken på siden.
@@ -4,7 +4,6 @@ import MenuItems from "./MenuItems";
export interface AccordionMenuProps extends HTMLAttributes<HTMLElement> {
children: React.ReactNode;
className?: string;
}
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
@@ -8,7 +8,6 @@ export interface AccordionMenuCollapsableProps
title: string;
defaultOpen?: boolean;
children: React.ReactNode;
className?: string;
}
const AccordionMenuCollapsable = forwardRef<
@@ -32,6 +31,7 @@ const AccordionMenuCollapsable = forwardRef<
{title}
<Expand
role="img"
focusable="false"
aria-label={isOpen ? "Pil peker opp" : "Pil peker ned"}
className="navds-accordion-menu-collapsable__expand-icon"
/>
@@ -1,8 +1,5 @@
import React from "react";
/**
* @ignore
*/
const MenuItems = ({ children }: { children: React.ReactNode }) => (
<ul className="navds-accordion-menu__list">
{React.Children.toArray(children).map((child, i) => (
@@ -0,0 +1,70 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import {
AccordionMenu,
AccordionMenuItem,
AccordionMenuCollapsable,
} from "../../index";
<Meta title="ds-react/accordion-menu/intro" />
# Hvordan ta i bruk Accordion-menu
```jsx
<AccordionMenu>
<AccordionMenuItem href="#leo">Leo</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla" active>
Nulla
</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
<AccordionMenuCollapsable title="Accumsan">
<AccordionMenuItem href="#justo" aria-current="page">
Justo
</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla">Nulla</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
</AccordionMenuCollapsable>
</AccordionMenu>
```
<Canvas>
<AccordionMenu>
<AccordionMenuItem href="#leo">Leo</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla" active>
Nulla
</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
<AccordionMenuCollapsable title="Accumsan">
<AccordionMenuItem href="#justo" aria-current="page">
Justo
</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla">Nulla</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
</AccordionMenuCollapsable>
</AccordionMenu>
</Canvas>
Accordion-menu støtter opp til maks to-nivårer av `AccordionMenuCollapsable` akkurat nå.
`AccordionMenuItem` er implementert med `OverridableComponent`, noe som
gjør at man kan ta i bruk eks react-router slik:
```jsx
<Item
component={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Lenketekst
</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.
@@ -42,10 +42,10 @@ export const All = () => (
<Item href="#luctus">Luctus</Item>
</Collapsable>
<Collapsable title="Accumsan">
<Item href="#justo" ariaCurrent="page">
<Item href="#justo" aria-current="page">
Justo
</Item>
<Item href="#pariatur" active ariaCurrent="page">
<Item href="#pariatur" active aria-current="page">
Pariatur
</Item>
<Collapsable title="Proin">
+16 -15
View File
@@ -1,8 +1,8 @@
import React, { forwardRef, useEffect, useState } from "react";
import cl from "classnames";
import { UnmountClosed, Collapse } from "react-collapse";
import { Expand } from "@navikt/ds-icons";
import { v4 as uuidv4 } from "uuid";
import { Expand, ExpandFilled } from "@navikt/ds-icons";
import { useId } from "..";
export interface AccordionProps
extends React.HTMLAttributes<HTMLButtonElement> {
@@ -10,10 +10,6 @@ export interface AccordionProps
* Component content
*/
children: React.ReactNode;
/**
* @ignore
*/
className?: string;
/**
* Content on interactive surface of component
*/
@@ -26,8 +22,6 @@ export interface AccordionProps
open?: boolean;
/**
* Callback for when user interacts with component
*
* @param {object} event
*/
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
/**
@@ -46,19 +40,15 @@ const Accordion = forwardRef<HTMLButtonElement, AccordionProps>(
className,
renderContentWhenClosed = false,
onClick,
id,
...rest
},
ref
) => {
const [contentId, setContentId] = useState("");
const [buttonId, setButtonId] = useState("");
const [internalOpen, setInternalOpen] = useState<boolean>(open);
// Forsøk på å fikse Nextjs SSR server/client clock problem
useEffect(() => {
setContentId(() => uuidv4());
setButtonId(() => uuidv4());
}, []);
const buttonId = useId(id);
const contentId = useId();
useEffect(() => {
setInternalOpen(open);
@@ -88,11 +78,22 @@ const Accordion = forwardRef<HTMLButtonElement, AccordionProps>(
{heading}
</span>
<Expand
focusable="false"
role="img"
className={cl(
"navds-accordion__chevron",
`navds-accordion__chevron--${internalOpen ? "up" : "down"}`
)}
/>
<ExpandFilled
focusable="false"
role="img"
className={cl(
"navds-accordion__chevron",
"navds-accordion__chevron--filled",
`navds-accordion__chevron--${internalOpen ? "up" : "down"}`
)}
/>
</button>
<div id={contentId} role="region" aria-labelledby={buttonId}>
<CollapseComponent isOpened={internalOpen}>
@@ -0,0 +1,33 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Accordion } from "../../index";
<Meta title="ds-react/accordion/intro" />
# Hvordan ta i bruk Accordion
```jsx
<Accordion heading="Qui id id ad cupidatat ullamco.">
Et anim nostrud reprehenderit duis eu tempor et irure proident. Eu ea occaecat
aliqua commodo sunt. Sit cupidatat ad id occaecat exercitation ipsum laboris
duis velit consequat adipisicing do amet aute. Aliquip culpa minim commodo
laborum eiusmod eu magna elit veniam ullamco ullamco minim.
</Accordion>
```
<Canvas>
<Accordion heading="Qui id id ad cupidatat ullamco.">
Et anim nostrud reprehenderit duis eu tempor et irure proident. Eu ea
occaecat aliqua commodo sunt. Sit cupidatat ad id occaecat exercitation
ipsum laboris duis velit consequat adipisicing do amet aute. Aliquip culpa
minim commodo laborum eiusmod eu magna elit veniam ullamco ullamco minim.
</Accordion>
</Canvas>
Accordion-komponeten styrer selv open/closed state, men om man ønsker kan man selv overskrive denne med
`open`-prop + `onClick`-prop.
Note: Hvis man tar i bruk `onClick`, så tolker komponeten det slik at du ønsker å styre state selv, så
man må da også bruke `open`-prop
`renderContentWhenClosed`-prop bestemmer om innholdet (children) skal beholdes i dom-strukturen mens
Accordion er lukket. Defaulter til `false`.
+36 -16
View File
@@ -12,17 +12,10 @@ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
* Decides what design the alert will have
*/
variant: "error" | "warning" | "info" | "success";
/**
* Component content
*/
children: React.ReactNode;
/**
* @ignore
*/
className?: string;
/**
* Reduces padding on component
* @default "medium"
* Changes padding and font-sizes
* @default "m"
*/
size?: "m" | "s";
}
@@ -30,13 +23,37 @@ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
const Icon = ({ variant }) => {
switch (variant) {
case "error":
return <ErrorFilled />;
return (
<ErrorFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
case "warning":
return <WarningFilled />;
return (
<WarningFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
case "info":
return <InformationFilled />;
return (
<InformationFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
case "success":
return <SuccessFilled />;
return (
<SuccessFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
default:
return null;
}
@@ -52,12 +69,15 @@ const Alert = forwardRef<HTMLDivElement, AlertProps>(
`navds-alert--${variant}`,
`navds-alert--${size}`,
"navds-body-long",
"navds-body--s"
{ "navds-body--s": size === "s" }
)}
{...rest}
>
<Icon variant={variant} />
<span>{children}</span>
<span>
<span className="sr-only">{`${variant}-ikon`}</span>
<Icon variant={variant} />
</span>
<div>{children}</div>
</div>
)
);
@@ -0,0 +1,55 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Alert } 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 min-height og small 32px min-height
<Canvas>
<Alert size="s" variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="success">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="warning">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="error">
Id elit esse enim reprehenderit.
</Alert>
</Canvas>
@@ -19,14 +19,19 @@ export const All = () => {
<h1>Alert</h1>
{variants.map((variant) => (
<Alert key={variant} variant={variant}>
{Array(8).fill(`${variant} content`).join(" ")}
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>
))}
<h2>Small</h2>
<div>
{variants.map((variant) => (
<Alert key={variant} variant={variant} size="s">
{Array(8).fill(`${variant} content`).join(" ")}
Exercitation enim nisi veniam nostrud Lorem ipsum ea fugiat. Aute
exercitation voluptate proident sit ex reprehenderit quis ex ut
mollit.
</Alert>
))}
</div>
+8 -9
View File
@@ -1,27 +1,25 @@
import React, { forwardRef } from "react";
import cl from "classnames";
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Component content
*/
children: React.ReactNode;
/**
* @ignore
*/
className?: string;
/**
* Decides component design and interactions
* Changes design and interactions
* @default "primary"
*/
variant?: "primary" | "secondary" | "action" | "danger";
/**
* Reduces internal padding for component
* @default "medium"
* Changes padding, height and font-size
* @default "m"
*/
size?: "m" | "s";
/**
* 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;
@@ -36,7 +34,8 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`,
"navds-body-short"
"navds-body-short",
{ "navds-body--s": size === "s" }
)}
{...rest}
/>
@@ -0,0 +1,65 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Button, Loader } from "../../index";
import { Success } from "@navikt/ds-react";
<Meta title="ds-react/button/intro" />
# Hvordan ta i bruk Button
```jsx
<Button>Buttontekst</Button>
```
<Canvas>
<Button>Buttontekst</Button>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`primary`, `secondary`, `action` og `danger`
<Canvas>
<Button variant="primary">Buttontekst</Button>
<Button variant="secondary">Buttontekst</Button>
<Button variant="action">Buttontekst</Button>
<Button variant="danger">Buttontekst</Button>
</Canvas>
## Sizing
Button har to størrelser: Default 48px min-height og small 32px min-height
<Canvas>
<Button size="s" variant="primary">
Buttontekst
</Button>
<Button size="s" variant="secondary">
Buttontekst
</Button>
<Button size="s" variant="action">
Buttontekst
</Button>
<Button size="s" variant="danger">
Buttontekst
</Button>
</Canvas>
## Med ikon eller `<Loader />`
Hvis man setter ikoner (svg) eller `<Loader />` rett på button vil størrelsen
bli justert automatisk. For å få riktige marginer rundt ikonet må man da wrappe innholdet
i et element
<Canvas>
<Button>
<span>Buttontekst</span> <Loader />
</Button>
<Button size="s">
<span>Buttontekst</span>
<Loader />
</Button>
<Button>
<Loader /> <span>Buttontekst</span>
</Button>
</Canvas>
@@ -1,5 +1,6 @@
import React from "react";
import { Button } from "../index";
import { Success } from "@navikt/ds-icons";
export default {
title: "ds-react/button",
@@ -52,7 +53,7 @@ export const All = () => {
{variants.map((variant) => (
<a
key={variant}
className={`navds-button navds-button--${variant}`}
className={`navds-button navds-button--${variant} navds-body-short`}
href="the-link"
>
{variant}
@@ -67,6 +68,30 @@ export const All = () => {
</Button>
))}
</Section>
<h2>Button w/icon</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span>{variant}</span> <Success />
</Button>
))}
</Section>
<h2>Small w/icon</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="s">
<Success /> <span>{variant}</span>
</Button>
))}
</Section>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="s">
<span className="sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
</>
);
};
-4
View File
@@ -5,10 +5,6 @@ import { OverridableComponent } from "../util";
export interface MicroCardProps {
props: {
children: string;
/**
* @ignore
*/
className?: string;
} & React.HTMLAttributes<HTMLAnchorElement>;
defaultComponent: "a";
}
@@ -1,4 +1,5 @@
import { Meta } from "@storybook/addon-docs/blocks";
import { Meta, Canvas } from "@storybook/addon-docs";
import { MicroCard } from "../index.ts";
<Meta title="ds-react/card/intro" />
@@ -12,9 +13,13 @@ Kan brukes som en vanlig lenke direkte:
<MicroCard href="/lenke/til/side">Lenketekst</MicroCard>
```
<Canvas>
<MicroCard href="/lenke/til/side">Lenketekst</MicroCard>
</Canvas>
Hvis man ønsker å ta i bruk nextjs sin `Link`-komponent:
```
```jsx
<Link href="/lenke/til/side" passHref>
<MicroCard>Lenketekst</MicroCard>
</Link>
@@ -2,10 +2,6 @@ import React, { forwardRef, HTMLAttributes } from "react";
import cl from "classnames";
export interface ContentContainerProps extends HTMLAttributes<HTMLDivElement> {
/**
* @ignore
*/
classNames?: string;
/**
* Component content
*/
@@ -0,0 +1,31 @@
import { Meta, Canvas } from "@storybook/addon-docs";
<Meta title="ds-react/content-container/intro" />
# Hvordan ta i bruk ContentContainer
```jsx
<ContentContainer>
<div>innhold...</div>
</ContentContainer>
```
## Bruk
Komponenten fungerer som en wrapper rundt innholdet ditt på siden for å
justere padding og max-width. Dette er all stylingen som blir applied
```css
.navds-content-container {
margin-left: auto;
margin-right: auto;
max-width: var(--navds-content-container-max-width);
padding: var(--navds-content-container-padding-small);
}
@media (min-width: 448px) {
.navds-content-container {
padding: var(--navds-content-container-padding-medium-and-larger);
}
}
```
@@ -9,10 +9,14 @@ import React, {
useState,
} from "react";
import mergeRefs from "react-merge-refs";
import { Popover, Button } from "../index";
import { Popover, Button } from "..";
export interface CopyToClipboardProps
extends HTMLAttributes<HTMLButtonElement> {
/**
* Button text
*/
children?: React.ReactNode;
/**
* Text to be copied to clipboard
*/
@@ -61,7 +65,15 @@ const CopyToClipboard = forwardRef<HTMLButtonElement, CopyToClipboardProps>(
onClick={handleClick}
{...rest}
>
{icon ? <>{icon}</> : <Copy aria-label="Fil ikon for kopiering" />}
{icon ? (
<>{icon}</>
) : (
<Copy
focusable="false"
role="img"
aria-label="Fil ikon for kopiering"
/>
)}
{children ? children : <span className="sr-only">{title}</span>}
</Button>
<Popover
@@ -9,7 +9,7 @@ export default {
};
export const All = () => {
const label = "pi";
const label = "Kopierte PI til clipboard";
const text = "3.14159265359";
return (
@@ -0,0 +1,35 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { CopyToClipboard } from "../../index";
import { Success } from "@navikt/ds-react";
<Meta title="ds-react/copy-to-clipboard/intro" />
# Hvordan ta i bruk CopyToClipboard
Innholdet i `text` vil da bli kopiert til clipboard, mens innholdet i `label`
brukes i popovertekst og `sr-only` span som rendres hvis knappen ikke har noe tekstinnhold
`sr-only` tekst blir da `Kopier ${label} (${text})`
```jsx
<CopyToClipboard label={"Kopierte PI til clipboard"} text={"3.14"}>
Kopier Pi{" "}
</CopyToClipboard>
```
<Canvas>
<CopyToClipboard label={"Kopierte PI til clipboard"} text={"3.14"}>
Kopier Pi{" "}
</CopyToClipboard>
</Canvas>
## Custom ikon
Man kan sette andre ikoner en `Copy` ved `icon`-proppen
```jsx
<CopyToClipboard
icon={<Link />}
label={"Kopierte PI til clipboard"}
text={"3.14"}
/>
```
@@ -0,0 +1,45 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { BodyLong, Checkbox, CheckboxProps } from "..";
export interface ConfirmationPanelProps extends Partial<CheckboxProps> {
/**
* Additional information on panel
*/
children?: React.ReactNode;
/**
* Checkbox label
*/
label: string;
/**
* Checked state for checkbox
*/
checked: boolean;
}
const ConfirmationPanel = forwardRef<HTMLDivElement, ConfirmationPanelProps>(
({ className, children, label, ...props }, ref) => {
return (
<div
ref={ref}
className={cl("navds-confirmation-panel", className, {
"navds-confirmation-panel--s": props.size === "s",
"navds-confirmation-panel--error": !!props.error,
"navds-confirmation-panel--checked": !!props.checked,
})}
>
{children && (
<BodyLong
size={props.size}
className="navds-confirmation-panel__content"
>
{children}
</BodyLong>
)}
<Checkbox {...props}>{label}</Checkbox>
</div>
);
}
);
export default ConfirmationPanel;
@@ -0,0 +1,17 @@
import React from "react";
import cl from "classnames";
import { Label } from "..";
const ErrorMessage = (props) => (
<Label
{...props}
component="div"
className={cl(
"navds-error-message",
props.className,
`navds-error-message--${props.size ?? "m"}`
)}
/>
);
export default ErrorMessage;
@@ -0,0 +1,132 @@
import cl from "classnames";
import React, { FieldsetHTMLAttributes, forwardRef, useContext } from "react";
import { BodyShort, Label, omit } from "../..";
import ErrorMessage from "../ErrorMessage";
import { FormFieldProps } from "../useFormField";
import { useFieldset } from "./useFieldset";
export type FieldsetContextProps = {
/**
* Error message applied to element
*/
error?: React.ReactNode;
/**
* Overrides internal errorId
*/
errorId: string;
/**
* Changes paddings, margins and font-sizes
*/
size: "m" | "s";
disabled: boolean;
};
export const FieldsetContext = React.createContext<FieldsetContextProps | null>(
null
);
export interface FieldsetProps
extends FormFieldProps,
FieldsetHTMLAttributes<HTMLFieldSetElement> {
/**
* FormFields in Fieldset
*/
children: React.ReactNode;
/**
* Fieldset legend
*/
legend: React.ReactNode;
/**
* If enabled shows the legend and description for screenreaders only
*/
hideLegend?: boolean;
/**
* Toggles error propagation to child-elements
* @default true
*/
errorPropagation?: boolean;
}
const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
(props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useFieldset(props);
const fieldset = useContext(FieldsetContext);
const {
children,
className,
errorPropagation = true,
legend,
description,
hideLegend,
...rest
} = props;
return (
<FieldsetContext.Provider
value={{
error: errorPropagation ? props.error ?? fieldset?.error : undefined,
errorId: cl({
[errorId]: showErrorMsg,
[fieldset?.errorId ?? ""]: !!fieldset?.error,
}),
size,
disabled: props.disabled ?? false,
}}
>
<fieldset
{...omit(rest, ["errorId", "error", "size"])}
{...inputProps}
ref={ref}
className={cl(
className,
"navds-fieldset",
`navds-fieldset--${size}`,
{ "navds-fieldset--error": hasError }
)}
>
<Label
size={size}
component="legend"
className={cl("navds-fieldset__legend", {
"sr-only": !!hideLegend,
})}
>
{legend}
</Label>
{!!description && (
<BodyShort
className={cl("navds-fieldset__description", {
"sr-only": !!hideLegend,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
{children}
<div
id={errorId}
aria-relevant="additions removals"
aria-live="polite"
className="navds-fieldset__error"
>
{showErrorMsg && (
<ErrorMessage size={size}>{props.error}</ErrorMessage>
)}
</div>
</fieldset>
</FieldsetContext.Provider>
);
}
);
export default Fieldset;
@@ -0,0 +1 @@
export { default, FieldsetProps, FieldsetContext } from "./Fieldset";
@@ -0,0 +1,17 @@
import { useFormField } from "../useFormField";
/**
* Handles props for Fieldset in context with parent Fieldset.
*/
export const useFieldset = (props) => {
const formField = useFormField(props, "fieldset");
const { inputProps } = formField;
return {
...formField,
inputProps: {
"aria-invalid": inputProps["aria-invalid"],
"aria-describedby": inputProps["aria-describedby"],
},
};
};
+103
View File
@@ -0,0 +1,103 @@
import React, { forwardRef, SelectHTMLAttributes } from "react";
import cl from "classnames";
import { Expand } from "@navikt/ds-icons";
import { BodyShort, Label, omit } from "..";
import ErrorMessage from "./ErrorMessage";
import { FormFieldProps, useFormField } from "./useFormField";
export interface SelectProps
extends FormFieldProps,
Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
/**
* Collection of <option>-elements
*/
children: React.ReactNode;
/**
* Expose the HTML size attribute
*/
htmlSize?: number;
/**
* Label for select
*/
label: string;
/**
* If enabled shows the label and description for screenreaders only
*/
hideLabel?: boolean;
}
const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useFormField(props, "textField");
const {
children,
label,
className,
description,
htmlSize,
hideLabel = false,
...rest
} = props;
return (
<div
className={cl(
props.className,
"navds-form-field",
`navds-form-field--${size}`,
{ "navds-select--error": hasError }
)}
>
<Label
htmlFor={inputProps.id}
size={size}
component="label"
className={cl("navds-select__label", {
"sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
className={cl("navds-select__description", {
"sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
<div className="navds-select__container">
<select
{...omit(rest, ["error", "errorId", "size"])}
{...inputProps}
ref={ref}
className={cl(
className,
"navds-select__input",
"navds-body-short",
`navds-body--${size ?? "m"}`
)}
size={props.htmlSize}
>
{children}
</select>
<Expand className="navds-select__chevron" />
</div>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
</div>
</div>
);
});
export default Select;
+92
View File
@@ -0,0 +1,92 @@
import React, { forwardRef, InputHTMLAttributes } from "react";
import cl from "classnames";
import { BodyShort, Label, omit } from "..";
import ErrorMessage from "./ErrorMessage";
import { FormFieldProps, useFormField } from "./useFormField";
export interface TextFieldProps
extends FormFieldProps,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
/**
* Expose the HTML size attribute
*/
htmlSize?: number;
/**
* If enabled shows the label and description for screenreaders only
*/
hideLabel?: boolean;
/**
* TextField label
*/
label: React.ReactNode;
}
const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useFormField(props, "textField");
const {
label,
className,
description,
htmlSize,
hideLabel = false,
...rest
} = props;
return (
<div
className={cl(
props.className,
"navds-form-field",
`navds-form-field--${size}`,
{ "navds-text-field--error": hasError }
)}
>
<Label
htmlFor={inputProps.id}
size={size}
component="label"
className={cl("navds-text-field__label", { "sr-only": hideLabel })}
>
{label}
</Label>
{!!description && (
<BodyShort
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
<input
{...omit(rest, ["error", "errorId", "size"])}
{...inputProps}
ref={ref}
type="text"
className={cl(
className,
"navds-text-field__input",
"navds-body-short",
`navds-body-${size ?? "m"}`
)}
size={htmlSize}
/>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
</div>
</div>
);
});
export default TextField;
+153
View File
@@ -0,0 +1,153 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import TextareaAutosize from "@material-ui/core/TextareaAutosize";
import { BodyShort, Label, omit } from "..";
import ErrorMessage from "./ErrorMessage";
import { FormFieldProps, useFormField } from "./useFormField";
import { useId } from "..";
/**
* TODO: Mulighet for lokalisering av sr-only/counter text
*/
export interface TextareaProps
extends FormFieldProps,
React.TextareaHTMLAttributes<HTMLTextAreaElement> {
/**
* Visually allowed length of content
*/
maxLength?: number;
value: string;
onChange: React.ChangeEventHandler<HTMLTextAreaElement>;
/**
* Maximum number of rows to display.
* @bug Internal scrolling with `maxLength` scrolls over maxLength-text
*/
maxRows?: number;
/**
* Minimum number of rows to display.
*/
minRows?: number;
/**
* Textarea label
*/
label: React.ReactNode;
/**
* If enabled shows the label and description for screenreaders only
*/
hideLabel?: boolean;
}
const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
(props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useFormField(props, "textarea");
const {
label,
className,
description,
maxLength,
hideLabel = false,
...rest
} = props;
const maxLengthId = `TextareaMaxLength-${useId()}`;
const hasMaxLength = maxLength !== undefined && maxLength > 0;
return (
<div
className={cl(
props.className,
"navds-form-field",
`navds-form-field--${size}`,
{ "navds-textarea--error": hasError }
)}
>
<Label
htmlFor={inputProps.id}
size={size}
component="label"
className={cl("navds-textarea__label", {
"sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
className={cl("navds-textarea__description", {
"sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
>
{description}
</BodyShort>
)}
<div className="navds-textarea__wrapper">
<TextareaAutosize
{...omit(rest, ["error", "errorId", "size"])}
{...inputProps}
ref={ref}
className={cl(
className,
"navds-textarea__input",
"navds-body-short",
`navds-body-${size ?? "m"}`,
{
"navds-textarea--counter": hasMaxLength,
}
)}
aria-describedby={cl(inputProps["aria-describedby"], {
[maxLengthId]: hasMaxLength,
})}
/>
{hasMaxLength && (
<>
<span id={maxLengthId} className="sr-only">
Tekstområde med plass til {maxLength} tegn., Textarea can have{" "}
{maxLength} signs.
</span>
<Counter
maxLength={maxLength}
currentLength={props.value.length}
size={size}
/>
</>
)}
</div>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && (
<ErrorMessage size={size}>{props.error}</ErrorMessage>
)}
</div>
</div>
);
}
);
export const Counter = ({ maxLength, currentLength, size }) => {
const difference = maxLength - currentLength;
return (
<BodyShort
className={cl("navds-textarea__counter", {
"navds-textarea__counter--error": difference < 0,
})}
aria-live="polite"
size={size}
>
{difference < 0
? `Du har ${Math.abs(difference)} tegn for mye`
: `Du har ${difference} tegn igjen`}
</BodyShort>
);
};
export default Textarea;
@@ -0,0 +1,89 @@
import React, { forwardRef, InputHTMLAttributes } from "react";
import cl from "classnames";
import useCheckbox from "./useCheckbox";
import ErrorMessage from "../ErrorMessage";
import { FormFieldProps } from "../useFormField";
import { BodyShort, omit } from "../..";
export interface CheckboxProps
extends FormFieldProps,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
/**
* Label for checkbox
*/
children: React.ReactNode;
/**
* Hides label and makes it viewable for screen-readers only.
*/
hideLabel?: boolean;
/**
* The value of the HTML element.
*/
value?: string;
}
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
hasError,
size,
inputDescriptionId,
} = useCheckbox(props);
return (
<div
className={cl(
props.className,
"navds-checkbox",
`navds-checkbox--${size}`,
{
"navds-checkbox--error": hasError,
"navds-checkbox--with-error-message": showErrorMsg,
"navds-checkbox--with-description": !!props.description,
}
)}
>
<input
{...omit(props, [
"children",
"size",
"error",
"errorId",
"description",
"hideLabel",
])}
{...inputProps}
className="navds-checkbox__input"
ref={ref}
/>
<BodyShort
component="label"
htmlFor={inputProps.id}
size={size}
className="navds-checkbox__label"
>
{props.hideLabel ? (
<span className="sr-only">{props.children}</span>
) : (
props.children
)}
</BodyShort>
{props.description && (
<BodyShort
size={size}
id={inputDescriptionId}
className="navds-checkbox__description"
>
{props.description}
</BodyShort>
)}
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
</div>
</div>
);
});
export default Checkbox;
@@ -0,0 +1,79 @@
import React, { createContext, forwardRef, useContext } from "react";
import cl from "classnames";
import { Fieldset, FieldsetProps, FieldsetContext } from "..";
export interface CheckboxGroupState {
readonly defaultValue: readonly string[];
readonly value?: readonly string[];
toggleValue(value: string): void;
}
export const CheckboxGroupContext = createContext<CheckboxGroupState | null>(
null
);
export interface CheckboxGroupProps extends Omit<FieldsetProps, "onChange"> {
/**
* Checkboxes
*/
children: React.ReactNode;
/**
* Controlled state for group
*/
value?: string[];
/**
* Default checked checkboxes on render
*/
defaultValue?: string[];
/**
* Returns current checked checkboxes in group
*/
onChange?: (value: string[]) => void;
}
const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
(
{
value,
defaultValue = [],
onChange = () => {},
children,
className,
...rest
},
ref
) => {
const state = value ?? [];
const fieldset = useContext(FieldsetContext);
return (
<Fieldset
{...rest}
ref={ref}
className={cl(
className,
"navds-checkbox-group",
`navds-checkbox-group--${rest.size ?? fieldset?.size ?? "m"}`
)}
>
<CheckboxGroupContext.Provider
value={{
value,
defaultValue,
toggleValue: (value: string) =>
onChange(
state.includes(value)
? state.filter((v) => v !== value)
: [...state, value]
),
}}
>
<div className="navds-checkboxes">{children}</div>
</CheckboxGroupContext.Provider>
</Fieldset>
);
}
);
export default CheckboxGroup;
@@ -0,0 +1,2 @@
export { default as Checkbox, CheckboxProps } from "./Checkbox";
export { default as CheckboxGroup, CheckboxGroupProps } from "./CheckboxGroup";
@@ -0,0 +1,227 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Checkbox, CheckboxGroup } from "../index";
<Meta title="ds-react/form/checkbox/intro" />
# Hvordan ta i bruk Checkbox
```jsx
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
Label å checkbox settes her da med children
## Description
Man kan både sette en description på CheckboxGroup og selve checkbox
```jsx
<CheckboxGroup legend="Culpa cupidatat" description="Exercitation do labore">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## Errors
```jsx
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## Errors uten errorPropagation
```jsx
<CheckboxGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" error="Boksen må være valgt">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## Sizing
Checkboxer har default 44px høy klikkflate. Med size="s" blir denne til 24px slik som før
```jsx
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" error="Boksen må være valgt">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## defaultValues
```jsx
<CheckboxGroup legend="Mollit eiusmod" defaultValue={["Orange", "Melon"]}>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" defaultValue={["Orange", "Melon"]}>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## hideLegend
Ved bruk av `hideLegend` på CheckboxGroup kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</Canvas>
## hideLabel
Ved bruk av `hideLabel` kan man lettere ta i bruk checkbox internt i eks tabeller.
```jsx
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple" hideLabel>
Apple
</Checkbox>
<Checkbox value="Orange" hideLabel>
Orange
</Checkbox>
<Checkbox value="Melon" hideLabel>
Melon
</Checkbox>
</CheckboxGroup>
```
<Canvas>
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple" hideLabel>
Apple
</Checkbox>
<Checkbox value="Orange" hideLabel>
Orange
</Checkbox>
<Checkbox value="Melon" hideLabel>
Melon
</Checkbox>
</CheckboxGroup>
</Canvas>
## Disabled
Ved bruk av `disabled` kan man både disabled enkelte checkboxer eller checkboxgruppen.
NOTE: Husk at disabled bør unngås!
```jsx
<CheckboxGroup legend="Mollit eiusmod" disabled>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<CheckboxGroup legend="Mollit eiusmod" >
<Checkbox value="Apple" disabled>Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
```
<Canvas>
<div>
<CheckboxGroup legend="Mollit eiusmod" disabled>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple" disabled>
Apple
</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</div>
</Canvas>
@@ -0,0 +1,96 @@
import React from "react";
import { Checkbox, CheckboxGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
title: "ds-react/form/checkbox",
component: Checkbox,
} as Meta;
export const All = () => {
return (
<>
<h1>Checkboxes</h1>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>description</h2>
<CheckboxGroup
legend="Mollit eiusmod"
description="Exercitation do labore"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" description="Laborum ad">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>error</h2>
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>error uten errorPropagation</h2>
<CheckboxGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" error="Boksen må være valgt">
Orange
</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>Sizing</h2>
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>defaultValue</h2>
<CheckboxGroup legend="Mollit eiusmod" defaultValue={["Orange", "Melon"]}>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>hideLenged</h2>
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<h2>hideLabel</h2>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple" hideLabel>
Apple
</Checkbox>
<Checkbox value="Orange" hideLabel>
Orange
</Checkbox>
<Checkbox value="Melon" hideLabel>
Melon
</Checkbox>
</CheckboxGroup>
<h2>Disabled</h2>
<CheckboxGroup legend="Mollit eiusmod" disabled>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
<CheckboxGroup legend="Mollit eiusmod">
<Checkbox value="Apple" disabled>
Apple
</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
</CheckboxGroup>
</>
);
};
@@ -0,0 +1,46 @@
import { useContext } from "react";
import { CheckboxProps } from "../..";
import { useFormField } from "../useFormField";
import { CheckboxGroupContext } from "./CheckboxGroup";
/**
* Handles props for Checkboxes in context with Fieldset and CheckboxGroup
*/
const useCheckbox = ({ children, ...props }: CheckboxProps) => {
const checkboxGroup = useContext(CheckboxGroupContext);
const { inputProps, ...rest } = useFormField(props, "checkbox");
if (checkboxGroup) {
if (props.checked) {
console.warn(
"`checked` is unsupported on <Checkbox> elements within a <CheckboxGroup>. Please set a `value` or `defaultValue` on <CheckboxGroup> instead."
);
}
if (props.value === undefined) {
console.warn(
"A <Checkbox> element within a <CheckboxGroup> requires a `value` property."
);
}
}
return {
...rest,
inputProps: {
...inputProps,
type: "checkbox",
checked: checkboxGroup?.value
? checkboxGroup.value.includes(props.value as string)
: props.checked,
defaultChecked: checkboxGroup
? checkboxGroup.defaultValue.includes(props.value as string)
: props.defaultChecked,
onChange: (e) => {
props.onChange && props.onChange(e);
checkboxGroup && checkboxGroup.toggleValue(props.value as string);
},
},
};
};
export default useCheckbox;
@@ -0,0 +1,66 @@
import React, { forwardRef, HTMLAttributes } from "react";
import cl from "classnames";
import { Title } from "../..";
export interface ErrorSummaryProps extends HTMLAttributes<HTMLDivElement> {
/**
* ErrorSummaryItems
*/
children: React.ReactNode;
/**
* Changes padding and font-sizes
* @default "m"
*/
size?: "m" | "s";
/**
* Heading above links
*/
heading?: React.ReactNode;
/**
* Allows setting a different HTML <tag>
* @default "h2"
*/
headingTag?: React.ElementType<any>;
}
const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
(
{ children, className, size = "m", headingTag = "h2", heading, ...rest },
ref
) => {
return (
<div
ref={ref}
{...rest}
className={cl(
className,
"navds-error-summary",
`navds-error-summary--${size}`
)}
tabIndex={-1}
role="region"
>
<Title
className="navds-error-summary__title"
component={headingTag}
size="s"
>
{heading}
</Title>
<ul
className={cl(
"navds-error-summary__list",
"navds-body-short",
`navds-body--${size}`
)}
>
{React.Children.map(children, (child) => {
return <li key={child?.toString()}>{child}</li>;
})}
</ul>
</div>
);
}
);
export default ErrorSummary;
@@ -0,0 +1,31 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "../..";
export type ErrorType = OverridableComponent<ErrorSummaryItemProps>;
export interface ErrorSummaryItemProps {
props: {
/**
* Link text
*/
children: React.ReactNode;
} & React.HTMLAttributes<HTMLAnchorElement>;
defaultComponent: "a";
}
const ErrorSummaryItem: ErrorType = forwardRef(
({ children, component: Component = "a", className, ...rest }, ref) => {
return (
<Component
{...rest}
ref={ref}
className={cl(className, "navds-error-summary__item", "navds-link")}
>
{children}
</Component>
);
}
);
export default ErrorSummaryItem;
@@ -0,0 +1,5 @@
export { default as ErrorSummary, ErrorSummaryProps } from "./ErrorSummary";
export {
default as ErrorSummaryItem,
ErrorSummaryItemProps,
} from "./ErrorSummaryItem";
@@ -0,0 +1,54 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { ErrorSummary, ErrorSummaryItem } from "../index";
<Meta title="ds-react/form/errorsummary/intro" />
# Hvordan ta i bruk ErrorSummary
`href` på `ErrorSummaryItem` linker til id som er satt på skjema-elementer.
```jsx
<ErrorSummary heading="Eiusmod est cillum mollit pariatur deserunt">
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummaryItem>
```
<Canvas>
<ErrorSummary heading="Eiusmod est cillum mollit pariatur deserunt">
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummary>
</Canvas>
## Custom headingTag
`headingTag` lar deg sette heading til en annen html-tag en default "h2"
```jsx
<ErrorSummary
heading="Eiusmod est cillum mollit pariatur deserunt"
headingTag="h3"
>
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummaryItem>
```
<Canvas>
<ErrorSummary
heading="Eiusmod est cillum mollit pariatur deserunt"
headingTag="h3"
>
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummary>
</Canvas>
@@ -0,0 +1,28 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { ErrorSummary, ErrorSummaryItem } from "..";
export default {
title: "ds-react/form/errorsummary",
component: ErrorSummary,
} as Meta;
export const All = () => {
return (
<>
<h1>Error summary</h1>
<ErrorSummary heading="Feiloppsummering komponent" headingTag="h4">
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummary>
<h2>size s</h2>
<ErrorSummary size="s" heading="Feiloppsummering komponent">
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummary>
</>
);
};
+31
View File
@@ -0,0 +1,31 @@
export {
Checkbox,
CheckboxProps,
CheckboxGroup,
CheckboxGroupProps,
} from "./checkbox";
export {
default as Fieldset,
FieldsetContext,
FieldsetProps,
} from "./Fieldset";
export { Radio, RadioGroup, RadioGroupProps, RadioProps } from "./radio";
export {
SearchField,
SearchFieldProps,
SearchFieldInput,
SearchFieldInputProps,
} from "./search-field";
export { default as Select, SelectProps } from "./Select";
export {
ErrorSummary,
ErrorSummaryProps,
ErrorSummaryItem,
ErrorSummaryItemProps,
} from "./error-summary";
export { Counter, default as Textarea, TextareaProps } from "./Textarea";
export { default as TextField, TextFieldProps } from "./TextField";
export {
default as ConfirmationPanel,
ConfirmationPanelProps,
} from "./ConfirmationPanel";
+72
View File
@@ -0,0 +1,72 @@
import React, { forwardRef, InputHTMLAttributes } from "react";
import cl from "classnames";
import { BodyShort, omit } from "../..";
import ErrorMessage from "../ErrorMessage";
import { FormFieldProps } from "../useFormField";
import { useRadio } from "./useRadio";
export interface RadioProps
extends FormFieldProps,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
/**
* Label for radio
*/
children: React.ReactNode;
value: string;
}
const Radio = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
const {
inputProps,
errorId,
showErrorMsg,
size,
hasError,
inputDescriptionId,
} = useRadio(props);
return (
<div
className={cl(props.className, "navds-radio", `navds-radio--${size}`, {
"navds-radio--error": hasError,
"navds-radio--with-error-message": showErrorMsg,
"navds-radio--with-description": !!props.description,
})}
>
<input
{...omit(props, [
"children",
"size",
"error",
"errorId",
"description",
])}
{...inputProps}
className="navds-radio__input"
ref={ref}
/>
<BodyShort
component="label"
htmlFor={inputProps.id}
size={size}
className="navds-radio__label"
>
{props.children}
</BodyShort>
{props.description && (
<BodyShort
size={size}
id={inputDescriptionId}
className="navds-radio__description"
>
{props.description}
</BodyShort>
)}
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
</div>
</div>
);
});
export default Radio;
@@ -0,0 +1,89 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { Fieldset, FieldsetContext, FieldsetProps } from "..";
import { useId } from "../..";
export interface RadioGroupContextProps {
name: string;
defaultValue?: string;
value?: string;
onChange: (value: string) => void;
required?: boolean;
}
export const RadioGroupContext = React.createContext<RadioGroupContextProps | null>(
null
);
export interface RadioGroupProps extends Omit<FieldsetProps, "onChange"> {
/**
* Collection of <Radio>-elements
*/
children: React.ReactNode;
/**
* Override internal name
*/
name?: string;
/**
* Default checked radiobutton
*/
defaultValue?: string;
/**
* Controlled state for Radiobutton
*/
value?: string;
/**
* Returns current checked radiobutton in group
*/
onChange?: (value: string) => void;
/**
* Tells Fieldset if group is required
*/
required?: boolean;
}
const RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(
(
{
children,
className,
name,
defaultValue,
value,
onChange = () => {},
required,
...rest
},
ref
) => {
const fieldset = useContext(FieldsetContext);
const nameId = useId();
return (
<Fieldset
{...rest}
ref={ref}
className={cl(
className,
"navds-radio-group",
`navds-radio-group--${rest.size ?? fieldset?.size ?? "m"}`
)}
>
<RadioGroupContext.Provider
value={{
name: name ?? `radioGroupName-${nameId}`,
defaultValue,
value,
onChange,
required,
}}
>
<div className="navds-radio-buttons">{children}</div>
</RadioGroupContext.Provider>
</Fieldset>
);
}
);
export default RadioGroup;
+2
View File
@@ -0,0 +1,2 @@
export { default as Radio, RadioProps } from "./Radio";
export { default as RadioGroup, RadioGroupProps } from "./RadioGroup";
@@ -0,0 +1,191 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Radio, RadioGroup } from "../index";
<Meta title="ds-react/form/radio/intro" />
# Hvordan ta i bruk Radio
```jsx
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
Label å Radio settes her da med children
## Description
Man kan både sette en description på RadioGroup og selve Radio
```jsx
<RadioGroup legend="Culpa cupidatat" description="Exercitation do labore">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Errors
```jsx
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Errors uten errorPropagation
```jsx
<RadioGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" error="Boksen må være valgt">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Sizing
Radioer har default 44px høy klikkflate. Med size="s" blir denne til 24px slik som før
```jsx
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" error="Boksen må være valgt">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## defaultValue
```jsx
<RadioGroup legend="Mollit eiusmod" defaultValue="Orange">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" defaultValue="Orange">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## hideLegend
Ved bruk av `hideLegend` på RadioGroup kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<RadioGroup legend="Mollit eiusmod" hideLegend>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" hideLegend>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</Canvas>
## Disabled
Ved bruk av `disabled` kan man både disabled enkelte Radioer eller Radiogruppen.
NOTE: Husk at disabled bør unngås!
```jsx
<RadioGroup legend="Mollit eiusmod" disabled>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<RadioGroup legend="Mollit eiusmod" >
<Radio value="Apple" disabled>Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
```
<Canvas>
<div>
<RadioGroup legend="Mollit eiusmod" disabled>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple" disabled>
Apple
</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</div>
</Canvas>
@@ -0,0 +1,81 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { RadioGroup, Radio } from "../index";
export default {
title: "ds-react/form/radio",
component: RadioGroup,
} as Meta;
export const All = () => {
return (
<>
<h1>Radios</h1>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>description</h2>
<RadioGroup legend="Mollit eiusmod" description="Exercitation do labore">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" description="Laborum ad">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>error</h2>
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>error uten errorPropagation</h2>
<RadioGroup
legend="Mollit eiusmod"
errorPropagation={false}
error="Boks nr 2 må være valgt"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" error="Boksen må være valgt">
Orange
</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>Sizing</h2>
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>defaultValue</h2>
<RadioGroup legend="Mollit eiusmod" defaultValue="Orange">
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>hideLenged</h2>
<RadioGroup legend="Mollit eiusmod" hideLegend>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<h2>Disabled</h2>
<RadioGroup legend="Mollit eiusmod" disabled>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
<RadioGroup legend="Mollit eiusmod">
<Radio value="Apple" disabled>
Apple
</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
</RadioGroup>
</>
);
};
@@ -0,0 +1,39 @@
import { useContext } from "react";
import { useFormField } from "../useFormField";
import { RadioProps } from "./Radio";
import { RadioGroupContext } from "./RadioGroup";
/**
* Handles props for Radios in context with Fieldset and RadioGroup
*/
export const useRadio = (props: RadioProps) => {
const radioGroup = useContext(RadioGroupContext);
const { inputProps, ...rest } = useFormField(props, "radio");
if (!radioGroup) {
console.warn("<Radio> must be used inside <RadioGroup>.");
}
if (props?.required !== undefined) {
console.warn("required is only supported on <RadioGroup>.");
}
return {
...rest,
inputProps: {
...inputProps,
name: radioGroup?.name,
checked:
(radioGroup?.value ?? radioGroup?.defaultValue) === props.value
? true
: undefined,
onChange: (e) => {
props.onChange && props.onChange(e);
radioGroup?.onChange && radioGroup.onChange(props.value);
},
required: radioGroup?.required,
type: "radio",
},
};
};
@@ -0,0 +1,110 @@
import cl from "classnames";
import React, { forwardRef } from "react";
import { BodyShort, Label, omit } from "../..";
import ErrorMessage from "../ErrorMessage";
import { FormFieldProps, useFormField } from "../useFormField";
export interface SearchFieldContextProps {
inputProps: {
id: string;
"aria-invalid": boolean;
"aria-describedby"?: string;
disabled?: boolean;
};
size?: "m" | "s";
}
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;
}
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 ?? "m"}`,
"navds-search-field",
{ "navds-search-field--error": hasError }
)}
>
<Label
htmlFor={inputProps.id}
size={size}
component="label"
className={cl("navds-text-field__label", {
"sr-only": hideLabel,
})}
>
{label}
</Label>
{!!description && (
<BodyShort
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>
);
}
);
export default SearchField;
@@ -0,0 +1,43 @@
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 "action"
*/
variant?: "primary" | "action";
}
const SearchFieldButton = forwardRef<HTMLButtonElement, SearchFieldButtonProps>(
({ className, variant = "action", 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;
@@ -0,0 +1,44 @@
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 "primary"
*/
variant?: "primary" | "action";
}
const SearchFieldClearButton = forwardRef<
HTMLButtonElement,
SearchFieldClearButtonProps
>(({ className, variant = "primary", 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
ref={ref}
className={cl(className, "navds-search-field__button")}
{...rest}
size={size}
variant={variant}
disabled={disabled ?? inputProps?.disabled}
/>
);
});
export default SearchFieldClearButton;
@@ -0,0 +1,37 @@
import React, { forwardRef, InputHTMLAttributes, useContext } from "react";
import cl from "classnames";
import { SearchFieldContext } from "./SearchField";
export interface SearchFieldInputProps
extends InputHTMLAttributes<HTMLInputElement> {}
const SearchFieldInput = forwardRef<HTMLInputElement, SearchFieldInputProps>(
({ 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}
ref={ref}
type="text"
className={cl(
className,
"navds-search-field__input",
"navds-text-field__input",
"navds-body-short",
`navds-body-${size ?? "m"}`
)}
/>
);
}
);
export default SearchFieldInput;
@@ -0,0 +1,13 @@
export { default as SearchField, SearchFieldProps } from "./SearchField";
export {
default as SearchFieldInput,
SearchFieldInputProps,
} from "./SearchFieldInput";
export {
default as SearchFieldButton,
SearchFieldButtonProps,
} from "./SearchFieldButton";
export {
default as SearchFieldClearButton,
SearchFieldClearButtonProps,
} from "./SearchFieldClearButton";
@@ -0,0 +1,31 @@
import React, { useState } from "react";
import { Close, Search } from "@navikt/ds-icons";
import {
SearchField,
SearchFieldInput,
SearchFieldButton,
SearchFieldClearButton,
} from "../index";
export const Example = () => {
const [value, setValue] = useState("");
return (
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldInput
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<SearchFieldClearButton onClick={() => setValue("")}>
<Close />
<span>Tøm</span>
</SearchFieldClearButton>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
);
};
@@ -0,0 +1,206 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import {
SearchField,
SearchFieldInput,
SearchFieldButton,
SearchFieldClearButton,
} 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">
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</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
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
</Canvas>
## Sizing
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="s"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="s"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
</Canvas>
## Errors
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
error="Error message"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
error="Error message"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
</Canvas>
## Plassering av knapp
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<div>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
<br />
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
</div>
</Canvas>
<h2>ClearButton</h2>
Man kan bruke `SearchFieldClearButton` for å håndtere clearing av value i `<input />`. For å bruke denne
kreves det da at `SearchFieldInput` er controlled slik at man styrer state selv slik som eksemplet under.
```jsx
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
<SearchFieldInput value={value} onChange={(e) => setValue(e.target.value)} />
<SearchFieldClearButton onClick={() => setValue("")}>
<Close />
<span>Tøm</span>
</SearchFieldClearButton>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
```
<Canvas>
<Example />
</Canvas>
@@ -0,0 +1,147 @@
import React from "react";
import { Meta } from "@storybook/react/types-6-0";
import { Close, Search } from "@navikt/ds-icons";
import {
SearchField,
SearchFieldInput,
SearchFieldButton,
SearchFieldClearButton,
} from "../index";
import { Fieldset } from "../..";
export default {
title: "ds-react/form/search-field",
component: SearchField,
} as Meta;
export const All = () => {
return (
<>
<h1>SearchField</h1>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
<h1>SearchField w clearsearch</h1>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldInput clearSearch />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldClearButton>
<Close /> <span>Tøm</span>
</SearchFieldClearButton>
<SearchFieldInput />
</SearchField>
<h2>Hidelabel</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
<h2>SearchField small</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="s"
>
<SearchFieldButton>
<Search />
<span className="sr-only">Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="s"
>
<SearchFieldInput />
<SearchFieldButton>
<Search />
<span className="sr-only">Søk</span>
</SearchFieldButton>
</SearchField>
<h2>SearchField w error</h2>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
error="Errormsg"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</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
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
</Fieldset>
</>
);
};
@@ -0,0 +1,59 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { ConfirmationPanelExample } from "./live-examples";
<Meta title="ds-react/form/confirmation-panel/intro" />
# Hvordan ta i bruk ConfirmationPanel
```jsx
<ConfirmationPanel
checked={checked}
onChange={() => setChecked(!checked)}
label="Checkbox label text"
>
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
ut mollit voluptate exercitation nulla mollit.
</ConfirmationPanel>
```
<Canvas>
<ConfirmationPanelExample />
</Canvas>
## Størrelser
Kommer i størrelsene "m" og "s".
```jsx
<ConfirmationPanel
checked={checked}
onChange={() => setChecked(!checked)}
label="Checkbox label text"
size="s"
>
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
ut mollit voluptate exercitation nulla mollit.
</ConfirmationPanel>
```
<Canvas>
<ConfirmationPanelExample size="s" />
</Canvas>
## Errors
```jsx
<ConfirmationPanel
checked={checked}
onChange={() => setChecked(!checked)}
label="Checkbox label text"
error="Laborum enim esse quis"
>
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
ut mollit voluptate exercitation nulla mollit.
</ConfirmationPanel>
```
<Canvas>
<ConfirmationPanelExample error="Laborum enim esse quis" />
</Canvas>
Loaded 100 of 210 files, more files were not shown because too many files have changed in this diff. Show more