Compare commits

..
Author SHA1 Message Date
github-actions[bot] 40d8d369a4 Lerna versionbump [ci skip]
- @navikt/ds-react@0.9.2
2021-09-24 07:25:25 +00:00
Andreas Nordahl 032240f939 [FIX] Checkbox group test (#1260)
* remove failing example test

* ds-react test setup

* add checkbox group test

* test ds-react from yarn script

* add test step to github build workflow

* dont transpile tests

* name cryptic argument lookup

* use faker to generate data
2021-09-24 09:07:40 +02:00
github-actions[bot] 27d89d7a41 Lerna versionbump [ci skip]
- @navikt/ds-react@0.9.1
2021-09-23 07:26:09 +00:00
Andreas Nordahl 3a56f34a62 [FIX] Allow text fields to be of any type that looks like a text input (#1264) 2021-09-23 09:11:14 +02:00
github-actions[bot] e7660412bc Lerna versionbump [ci skip]
- @navikt/ds-react@0.9.0
2021-09-21 13:07:25 +00:00
Andreas Nordahl 956afbb91a [FEATURE] remove Bubble from speech-bubble/index exports, and import it directly in SpeechBubble (#1262) 2021-09-21 14:55:56 +02:00
github-actions[bot] 5fd28b0131 Lerna versionbump [ci skip]
- @navikt/ds-css@0.8.3
 - @navikt/ds-icons@0.5.3
 - @navikt/ds-react@0.8.3
 - @navikt/ds-tokens@0.5.1
 - nav-frontend-ekspanderbartpanel@4.0.2
 - nav-frontend-hjelpetekst@3.1.2
 - nav-frontend-ikonknapper@2.1.2
 - nav-frontend-js-utils@1.0.20
 - nav-frontend-knapper@3.1.2
 - nav-frontend-lesmerpanel@2.0.2
 - nav-frontend-popover@2.0.3
 - nav-frontend-skjema-style@3.0.2
 - nav-frontend-skjema@4.0.4
 - nav-frontend-stegindikator@2.0.2
 - nav-frontend-tabs@2.0.2
 - nav-frontend-toggle@2.1.2
 - nav-frontend-veileder@3.0.2
 - nav-frontend-veilederpanel@2.0.2
2021-09-20 12:53:58 +00:00
Ken 646f6b858e [FIX] Fikset type-error 2021-09-20 14:36:44 +02:00
Ken c5add547bc fikset build 2021-09-20 14:07:00 +02:00
Andreas Nordahl cac3a433c4 [FIX] Remove flex-shrink: 0 from button (#1259) 2021-09-20 14:05:03 +02:00
Ken 5eb5b6b617 Update CONTRIBUTING.md 2021-09-20 14:03:47 +02:00
Ken 19afca1ed6 Update CONTRIBUTING.md 2021-09-20 14:03:30 +02:00
Ken 7c341f7cd2 [FIX] Chore: oppdatert pakkeversjoner og scripts (#1254) 2021-09-20 14:02:28 +02:00
github-actions[bot] 9a1a48d319 Lerna versionbump [ci skip]
- @navikt/ds-css@0.8.2
 - @navikt/ds-react@0.8.2
 - nav-frontend-skjema@4.0.3
2021-09-20 11:48:54 +00:00
Ken ce4afb17a8 [FIX] Refactor speechbubble til dot-notasjon (#1256) 2021-09-20 13:35:33 +02:00
Ken 146111e859 [FIX] Justert alignment av tekst i SpeechBubble (#1255) 2021-09-20 13:35:25 +02:00
Ken 40a8965cec [FIX] Setter aria-live til polite bare når 20 tegn gjenstår... (#1258)
... i Textarea
2021-09-20 13:34:23 +02:00
github-actions[bot] 8f4e6a5e89 Lerna versionbump [ci skip]
- @navikt/ds-react@0.8.1
2021-09-17 15:03:05 +00:00
Ken e73c9d2f3e [FIX] short-uuid -> uuid (short-uuid brekker sanity) (#1257) 2021-09-17 16:47:51 +02:00
Ken 0849fffe40 oppdatert changelog 2021-09-16 15:07:24 +02:00
TuvaSverdstad 7a261e86a3 Update produktsider.mdx (#1253) 2021-09-16 15:03:17 +02:00
TuvaSverdstad a2c48a9246 Update livssituasjonssider.mdx (#1252) 2021-09-16 15:03:03 +02:00
github-actions[bot] 7c845ac464 Lerna versionbump [ci skip]
- @navikt/ds-css@0.8.1
2021-09-16 08:24:28 +00:00
Ken 6edd03a9c1 [FIX] hotfix searchfield clearbutton 2021-09-16 10:09:35 +02:00
Andreas NordahlandKen 724a90eb28 [FIX] Button padding fix (#1248)
Co-authored-by: Ken <ken.aleksander@gmail.com>
2021-09-16 10:00:54 +02:00
TuvaSverdstad 43b686e769 Update produktsider.mdx (#1249) 2021-09-16 09:09:16 +02:00
github-actions[bot] c485e1bfc7 Lerna versionbump [ci skip]
- @navikt/ds-css@0.8.0
 - @navikt/ds-react@0.8.0
 - @navikt/ds-tokens@0.5.0
2021-09-15 14:04:17 +00:00
KenandAndreas Nordahl 9533504b16 [FEATURE] Samling av oppdaterte vnext komponenter (#1194)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2021-09-15 15:46:55 +02:00
T. GulbrandsenandKen bca56d1c48 God praksis om man bruker disabled state (#1246)
* God praksis for når man bruker disabled state

* Update disabled.mdx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2021-09-15 14:28:34 +02:00
TuvaSverdstad a656a19df5 Update livssituasjonssider.mdx (#1245) 2021-09-15 09:14:57 +02:00
Ken a2ac8fedb1 Update build-publish.yml 2021-09-14 15:58:56 +02:00
TuvaSverdstadandKen bf0a71f1d4 Update produktsider.mdx (#1243)
* Update produktsider.mdx

* Update produktsider.mdx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2021-09-14 13:25:02 +02:00
TuvaSverdstadandKen e4b51f49fb Update livssituasjonssider.mdx (#1244)
* Update livssituasjonssider.mdx

* Update livssituasjonssider.mdx

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2021-09-14 13:24:52 +02:00
Ken ea49e12e23 Update .specifyrc.json 2021-09-13 16:24:21 +02:00
Ken 4a29f5b449 Update .specifyrc.json 2021-09-13 16:21:11 +02:00
Ken 7b7950dab1 Update .specifyrc.json 2021-09-13 16:19:40 +02:00
Snyk bot bcb8d46c72 [Snyk] Security upgrade chalk from 1.1.3 to 2.0.0 (#1240) 2021-09-13 09:28:08 +02:00
TuvaSverdstad 60dbbaedd9 Update produktsider.mdx (#1236)
innholdsoppdatering
2021-09-10 11:09:49 +02:00
Ken 8991704a09 endret base branch for token sync 2021-09-10 08:52:26 +02:00
Ken 4a22f10763 [Tokens] Config for farge-sync (#1234) 2021-09-10 08:48:52 +02:00
github-actions[bot] 7335fb6c8d Lerna versionbump [ci skip]
- @navikt/ds-react@0.7.7
2021-09-08 10:25:17 +00:00
Ken 9b95eff894 [fix] Versjonering i commit MSG (#1220)
* started oppdatering av versionering

* oppdatert workflow

* oppdatert workflows

* oppdatert workflows2

* oppdatert workflow3

* tester pakke-endring

* la til chromatic i workflow comment

* testendring

* fikset workflow settings

* oppdatert yarn lock
2021-09-08 12:08:46 +02:00
208 changed files with 6321 additions and 4043 deletions

No files matched your search

+13 -3
View File
@@ -30,6 +30,8 @@ jobs:
- name: install
if: steps.node-cache.outputs.cache-hit != 'true'
run: yarn install
- name: test
run: yarn test
- name: Boot
run: yarn boot
- name: Eslint and Stylelint
@@ -50,7 +52,7 @@ jobs:
publish-npm:
needs: test-build
runs-on: ubuntu-latest
if: github.event_name == 'push'
if: github.event_name == 'push' && contains(github.event.head_commit.message, '[fix]') || contains(github.event.head_commit.message, '[feature]') || contains(github.event.head_commit.message, '[breaking]')
steps:
- uses: actions/checkout@v2
with:
@@ -78,8 +80,16 @@ jobs:
git remote set-url origin https://github-actions[bot]:$NAV_DS_TOKEN@github.com/$GITHUB_REPOSITORY.git
env:
NAV_DS_TOKEN: ${{secrets.GIT_REPO}}
- name: Update all package-versions with patch
- name: Update changed packages with PATCH
if: "contains(github.event.head_commit.message, '[fix]')"
run: yarn lerna version patch --include-merged-tags --yes
- name: Update changed packages with MINOR
if: "contains(github.event.head_commit.message, '[feature]')"
run: yarn lerna version minor --include-merged-tags --yes
- name: Update changed packages with MAJOR
if: "contains(github.event.head_commit.message, '[breaking]')"
run: yarn lerna version major --include-merged-tags --yes
- name: Create a .npmrc file for NPM
run: |
@@ -104,7 +114,7 @@ jobs:
yarn lerna publish --registry https://npm.pkg.github.com from-package --yes
publish-pages:
needs: publish-npm
needs: test-build
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
+46
View File
@@ -0,0 +1,46 @@
{
"repository": "@nav/designsystem",
"head": "specify-sync",
"base": "specify-token-parsing",
"rules": [
{
"name": "Color sync",
"path": "@navikt/ds-tokens/src/colors.js",
"filter": {
"types": ["color"]
},
"parsers": [
{
"name": "to-theme-ui",
"options": {
"formatConfig": {
"module": "commonjs"
},
"formatTokens": {
"colorFormat": {
"format": "rgb"
}
}
}
}
]
},
{
"name": "Spacing sync",
"path": "@navikt/ds-tokens/src/spacing.js",
"filter": {
"types": ["measurement"]
},
"parsers": [
{
"name": "to-theme-ui",
"options": {
"formatConfig": {
"module": "commonjs"
}
}
}
]
}
]
}
+229
View File
@@ -0,0 +1,229 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-react/Migration" />
# Migrering til ds-react, ds-css v0.8.0
Denne guiden vil være til hjelp for de som allerede har begynt å ta i bruk de nye pakkene våre tidligere enn v0.8.0.
For de som ikke har begynt å ta i bruk pakkene kan man se bort fra denne.
Fra versjon v0.7 til v0.8 er det komment flere store endringer både i ds-react og ds-css. For å lettere
oppdatere til v0.8 har vi da laget en liten guide som forklarer de største endringene.
## Styling
De fleste komponenter har fått diverse justering på styling. Anbefales da å ta en rask sjekk om alt fortsatt stemmer
etter oppdateringen.
## Sizing
Alle komponenter som tidligere var implementert med `size`-prop har fått oppdatert
props fra "xs", "s", "m", "l", "xl", "2xl" -> "xsmall", "small", "medium", "large", "xlarge", "2xlarge".
Dette betyr også at css-stylingen er eks endret fra `.navds-body-short--s` -> `.navds-body-short--small`
## Overridable component
Komponenter som tidligere implementerte ovveridable component med bruk av `component`-prop bruker nå `as`.
Implementasjonen av OverridableComponent er WIP så kan hende typene ender opp med å krangle i enkelte tilfeller. Om så ta gjerne kontakt med oss
slik at vi får sett på det tilfellet!
```jsx
/* Før */
<BodyShort component="span" />
/* Etter */
<BodyShort as="span" />
```
## Navneendringer
### Buttons
- `Primary` -> `Secondary` (Normal)
- `Action` -> `Primary` (Hoved)
- `Secondary` -> `Tertiary` (Flat)
For alle som har brukt `<Button />` så må man fikse slik at riktige knapper blir brukt der de skal!
## Nytt
- GuidePanel (veilederpanel)
- HelpText (Hjeleptext)
### Typography
Vi har valgt å endre fra `<Title/>` -> `<Heading/>` i typografien vår da dette ga mer mening i bruk.
APIet til komponenten er ikke endret borsett fra "Sizing" endringene nevt lengre opp, så skal bare være en rask search/replace.
For de som har brukt css-en direkte, eks `navds-title` så må man endre til `navds-heading`
Endret `Header` -> `PageHeader`, samme som er nevnt ang endringen over gjelder her også: sjekk css hvis brukt direkte.
## Fjernet komponenter
Fjernet da den var utdaterte/må ses mer på
- ProductPageLayout
## Typography
Linjehøyder for alle typo-komponentene er oppdatert til å matche figma.
Lagt til en Heading lvl 6 og size="xsmall"
## AccordionMenu
Implementert med dot-notation
- Trenger bare importere AccordionMenu
- AccordionMenuCollapsable -> AccordionMenu.Collapsable
- AccordionMenuItem -> AccordionMenu.Item
## Accordion
Implementert med dot-notation
- Trenger bare importere Accordion nå
Fragmenterte komponenten:
- Accordion -> Accordion.Item
- Header -> Accordion.Header
- children -> Accordion.Content
La til prop: `defaultOpen` på `Accordion.Item`
```jsx
/* Før */
<Accordion heading="tittel" open={open} onClick={(open) => setOpen(!open)}>
Eu magna fugiat officia
</Accordion>
<Accordion heading="tittel2" open={open2} onClick={(open2) => setOpen(!open2)}>
Eu magna fugiat officia
</Accordion>
/* Etter */
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={(open) => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit
</Accordion.Content>
</Accordion.Item>
<Accordion.Item open={open2}>
<Accordion.Header onClick={(open2) => setOpen(!open2)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
## Alert
- La til `fullWidth`-prop for alert uten border-radius og width 100%
- La til `inline`-prop for alert med transparent border/background og 0 padding.
## Button
Oppdatert med Overridablecomponent.
Håndtering av sentrering, margins er oppdatert. Trenger ikke wrappe tekst med `span` når man skal bruke ikoner lengre.
Hvis man skal manuelt justere på alignment av innhold, eks bruke `flex-direction: column` må man sette
det på css-klassen `.navds-button__inner` da children er wrappet i den.
## CopyToClipboard
Ekstender nå ButtonProps, slik at man eks kan ta i bruk `size`-proppen
`text`-prop -> `copyText`
`label`-prop -> `popoverText`
Fjernet `icon`-prop, la til `popoverPlacement`
## Modal
Implementert med dot-notasjon
Innholds-padding er flyttet fra Modal -> Modal.Content
```
/* Før */
<Modal>Modal innhold</Modal>
/* Etter */
<Modal><Modal.Content>Modal innhold</Modal.Content></Modal>
```
## LinkPanel
Implementert med dot-notasjon
```jsx
/* Før */
<LinkPanel href="#">Consectetur eu duis aliqua eu irure fugiat fugiat eu.</LinkPanel>
/* Etter */
<LinkPanel href="#">
<LinkPanel.Title>
Consectetur eu duis aliqua eu irure fugiat fugiat eu.
</LinkPanel.Title>
</LinkPanel>
```
Kan nå legge til en beskrivelse med `Linkpanel.Description`
```jsx
<LinkPanel href="#">
<LinkPanel.Title>
Consectetur eu duis aliqua eu irure fugiat fugiat eu.
</LinkPanel.Title>
<LinkPanel.Description>Aliqua id aliquip Lorem esse</LinkPanel.Description>
</LinkPanel>
```
## Popover
Implementert med dot-notasjon
Får nå padding rundt innhold med Popover.Content
```jsx
/* Før */
<Popover>Popover innhold</Popover>
/* Etter */
<Popover>
<Popover.Content>Modal innhold</Popover.Content>
</Popover>
```
## Header -> PageHeader
Props må fikses for de som har brukt denne komponenten, i tilleg til å endre navn.
- `variant`-prop -> `align`
- `theme`-prop -> `variant`
## MicroCard
- Oppdatert med OverridableComponent
## SpeechBubble
Implementert med Dot-notasjon
- `<Bubble/>` -> `<SpeechBubble.Bubble/>`
Bubble er fortsatt eksportert så vil ikke brekke noe for de som har begynt å ta denne i bruk.
+1 -7
View File
@@ -20,7 +20,7 @@ Dette vil gjøre styling og overriding av komponenter enklere da man kan bruke c
## 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`.
Løsning er ikke fast bestemt, men eksempel på dette er `size="small" -> 32px, size="medium"-> 48px`.
Dette vil da eksempelvis kunne være en standard som er gjennomgående for de fleste komponentene.
## Ny dokumentasjon-side
@@ -44,12 +44,6 @@ eks darkmode.
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å å
+1 -1
View File
@@ -1,3 +1,3 @@
# Designsystem v2
# Designsystem v2
Storybook: https://navikt.github.io/Designsystemet/
+19 -6
View File
@@ -1,3 +1,11 @@
:root {
--navds-accordion-menu-color-text: var(--navds-color-text-link);
--navds-accordion-menu-color-text-focus: var(--navds-color-darkgray);
--navds-accordion-menu-color-background-hover: var(--navds-color-blue-10);
--navds-accordion-menu-color-text-active: var(--navds-color-text);
--navds-accordion-menu-outline-focus: var(--navds-text-focus);
}
.navds-accordion-menu__list {
list-style: none;
margin: 0;
@@ -18,7 +26,7 @@
justify-content: space-between;
align-items: center;
font-weight: var(--navds-font-weight-bold);
color: var(--navds-color-text-link);
color: var(--navds-accordion-menu-color-text);
text-decoration: underline;
}
@@ -31,7 +39,7 @@
.navds-accordion-menu-collapsable__expand-icon {
font-size: 1.5rem;
color: var(--navds-color-text-link);
color: var(--navds-accordion-menu-color);
flex-shrink: 0;
margin-left: var(--navds-spacing-2);
}
@@ -73,18 +81,23 @@
.navds-accordion-menu-item:focus,
.navds-accordion-menu-collapsable__button:focus {
outline: 3px solid var(--navds-text-focus);
outline: 3px solid var(--navds-accordion-menu-outline-focus);
outline-offset: -3px;
color: var(--navds-color-darkgray);
color: var(--navds-accordion-menu-color-text-focus);
}
.navds-accordion-menu-collapsable__button:focus
> .navds-accordion-menu-collapsable__expand-icon {
color: var(--navds-accordion-menu-color-focus);
}
.navds-accordion-menu-item:hover,
.navds-accordion-menu-collapsable__button:hover {
background-color: var(--navds-color-blue-10);
background-color: var(--navds-accordion-menu-color-background-hover);
}
.navds-accordion-menu-item--active {
box-shadow: inset 0.5rem 0 var(--navds-color-text-link);
color: var(--navds-color-text);
color: var(--navds-accordion-menu-color-text-active);
text-decoration: none;
}
+36 -48
View File
@@ -1,82 +1,70 @@
.ReactCollapse--collapse {
transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1);
:root {
--navds-accordion-color-text: var(--navds-color-darkgray);
--navds-accordion-color-background: var(--navds-color-background);
--navds-accordion-color-text-hover: var(--navds-color-blue-50);
--navds-accordion-color-border-hover: var(--navds-color-blue-50);
--navds-accordion-color-border-focus: var(--navds-color-background);
}
.navds-accordion .ReactCollapse--collapse {
transition: height 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
.navds-accordion {
position: relative;
background: var(--navds-color-background);
border-bottom: 2px solid #c9c9c9;
background: var(--navds-accordion-color-background);
}
.navds-accordion:hover {
/* color: black; */
border-bottom: 2px solid var(--navds-color-blue-50);
}
.navds-accordion:focus,
.navds-accordion__button:focus {
box-shadow: var(--navds-shadow-focus);
.navds-accordion__header:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
border-color: var(--navds-accordion-color-border-focus);
}
.navds-accordion__chevron {
width: 1.25em;
height: 1.25em;
transform: rotateZ(0deg);
.navds-accordion__header:hover {
color: var(--navds-accordion-color-text-hover);
border-color: var(--navds-accordion-color-border-hover);
text-decoration: underline;
}
.navds-accordion__expand-icon {
width: 1.5rem;
height: 1.5rem;
flex-shrink: 0;
margin-left: var(--navds-spacing-4);
}
.navds-accordion__chevron--up {
transform: rotateZ(-180deg);
.navds-accordion__expand-icon--flip {
transform: rotateZ(180deg);
}
.navds-accordion__chevron--down {
transform: rotateZ(0deg);
}
.navds-accordion__button {
padding: var(--navds-spacing-4);
.navds-accordion__header {
padding: var(--navds-spacing-4) var(--navds-spacing-3);
background: transparent;
text-align: left;
border: none;
width: 100%;
margin-bottom: 0;
margin: 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 {
text-decoration: underline;
color: var(--navds-color-text-link);
border-bottom: 2px solid #a0a0a0;
gap: var(--navds-spacing-4);
}
.navds-accordion__content {
padding: var(--navds-spacing-2) var(--navds-spacing-4) var(--navds-spacing-4);
color: var(--navds-accordion-color-text);
padding: var(--navds-spacing-5) var(--navds-spacing-3) var(--navds-spacing-10);
}
.navds-accordion--open .navds-accordion__content {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.navds-accordion--open > .navds-accordion__button {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.navds-accordion__chevron--filled {
.navds-accordion__expand-icon--filled {
display: none;
}
.navds-accordion__button:hover
> .navds-accordion__chevron.navds-accordion__chevron--filled {
.navds-accordion__header:hover
> .navds-accordion__expand-icon.navds-accordion__expand-icon--filled {
display: inherit;
}
.navds-accordion__button:hover > .navds-accordion__chevron {
.navds-accordion__header:hover > .navds-accordion__expand-icon {
display: none;
}
+86 -51
View File
@@ -1,84 +1,119 @@
:root {
--navds-alert-color-border: var(--navds-color-gray-40);
--navds-alert-color-error-border: var(--navds-color-error-border);
--navds-alert-color-error-background: var(--navds-color-error-background);
--navds-alert-color-warning-border: var(--navds-color-warning-border);
--navds-alert-color-warning-background: var(--navds-color-warning-background);
--navds-alert-color-info-border: var(--navds-color-info-border);
--navds-alert-color-info-background: var(--navds-color-info-background);
--navds-alert-color-success-border: var(--navds-color-success-border);
--navds-alert-color-success-background: var(--navds-color-success-background);
--navds-alert-color-error-icon: var(--navds-color-red-60);
--navds-alert-color-error-icon-background: var(--navds-color-white);
--navds-alert-color-warning-icon: var(--navds-color-orange-40);
--navds-alert-color-warning-icon-background: var(--navds-color-darkgray);
--navds-alert-color-info-icon: var(--navds-color-lightblue-70);
--navds-alert-color-info-icon-background: var(--navds-color-white);
--navds-alert-color-success-icon: var(--navds-color-green-70);
--navds-alert-color-success-icon-background: var(--navds-color-white);
}
.navds-alert {
border-radius: 4px;
border: var(--navds-border-default);
/* 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;
justify-content: start;
min-height: 64px;
box-sizing: border-box;
border: 1px solid;
border-color: var(--navds-alert-color-border);
padding: calc(var(--navds-spacing-4) + 1px) calc(var(--navds-spacing-4) + 1px);
display: flex;
gap: var(--navds-spacing-3);
align-items: center;
}
.navds-alert--s {
padding: var(--navds-spacing-1) var(--navds-spacing-4);
min-height: 32px;
.navds-alert__wrapper {
max-width: 43.5rem;
}
.navds-alert > span > svg {
margin-right: var(--navds-spacing-3);
font-size: 1.5rem;
.navds-alert--small {
padding: calc(var(--navds-spacing-1) - 1px) var(--navds-spacing-4);
}
.navds-alert--full-width {
border-radius: 0;
}
.navds-alert > .navds-alert__icon {
flex-shrink: 0;
font-size: 1.5rem;
align-self: flex-start;
height: var(--navds-font-line-height-xl);
}
.navds-alert--small > .navds-alert__icon {
font-size: 1.25rem;
height: var(--navds-font-line-height-l);
}
.navds-alert--error {
border-color: var(--navds-alert-color-error-border);
background-color: var(--navds-alert-color-error-background);
}
.navds-alert--error > .navds-alert__icon {
color: var(--navds-alert-color-error-icon);
background: radial-gradient(
circle,
var(--navds-color-background) 50%,
var(--navds-alert-color-error-icon-background) 50%,
0,
transparent
);
}
.navds-alert > div {
display: block;
margin: auto 0;
max-width: 43.5rem;
flex: 1;
}
.navds-alert > span {
display: flex;
align-items: center;
max-height: calc(var(--navds-spacing-8) - 2px);
}
.navds-alert--error {
border-color: var(--navds-color-error-border);
background-color: var(--navds-color-error-background);
}
.navds-alert--error > span > svg {
color: var(--navds-color-red-60);
}
.navds-alert--warning {
border-color: var(--navds-color-warning-border);
background-color: var(--navds-color-warning-background);
border-color: var(--navds-alert-color-warning-border);
background-color: var(--navds-alert-color-warning-background);
}
.navds-alert--warning > span > svg {
color: var(--navds-color-orange-40);
.navds-alert--warning > .navds-alert__icon {
color: var(--navds-alert-color-warning-icon);
background: radial-gradient(
circle,
var(--navds-color-darkgray) 50%,
var(--navds-alert-color-warning-icon-background) 50%,
0,
transparent
);
}
.navds-alert--info {
border-color: var(--navds-color-info-border);
background-color: var(--navds-color-info-background);
border-color: var(--navds-alert-color-info-border);
background-color: var(--navds-alert-color-info-background);
}
.navds-alert--info > span > svg {
color: var(--navds-color-lightblue-70);
.navds-alert--info > .navds-alert__icon {
color: var(--navds-alert-color-info-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-info-icon-background) 50%,
0,
transparent
);
}
.navds-alert--success {
border-color: var(--navds-color-success-border);
background-color: var(--navds-color-success-background);
border-color: var(--navds-alert-color-success-border);
background-color: var(--navds-alert-color-success-background);
}
.navds-alert--success > span > svg {
color: var(--navds-color-green-70);
.navds-alert--success > .navds-alert__icon {
color: var(--navds-alert-color-success-icon);
background: radial-gradient(
circle,
var(--navds-alert-color-success-icon-background) 50%,
0,
transparent
);
}
.navds-alert--inline {
background-color: transparent;
border-color: transparent;
padding: 0;
}
+5 -2
View File
@@ -9,7 +9,8 @@
* https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
*/
.sr-only {
.sr-only,
.navds-sr-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
@@ -32,7 +33,9 @@
*/
.sr-only.focusable:active,
.sr-only.focusable:focus {
.sr-only.focusable:focus,
.navds-sr-only.focusable:active,
.navds-sr-only.focusable:focus {
clip: auto;
height: auto;
margin: 0;
+153 -87
View File
@@ -1,47 +1,72 @@
:root {
/* Primary */
--navds-button-color-primary-text: var(--navds-color-white);
--navds-button-color-primary-border-focus: var(--navds-color-white);
--navds-button-color-primary-background: var(--navds-color-action-default);
--navds-button-color-primary-background-hover: var(
--navds-color-action-hover
);
--navds-button-color-primary-background-active: var(
--navds-color-action-active
);
/* Secondary */
--navds-button-color-secondary-text: var(--navds-color-action-default);
--navds-button-color-secondary-text-hover: var(--navds-color-text-inverse);
--navds-button-color-secondary-text-active: var(--navds-color-text-inverse);
--navds-button-color-secondary-border: var(--navds-color-action-default);
--navds-button-color-secondary-border-focus-active-hover: var(
--navds-color-white
);
--navds-button-color-secondary-background: var(--navds-color-background);
--navds-button-color-secondary-background-hover: var(
--navds-color-action-hover
);
--navds-button-color-secondary-background-active: var(
--navds-color-action-active
);
/* Tertiary */
--navds-button-color-tertiary-text: var(--navds-color-action-default);
--navds-button-color-tertiary-text-active: var(--navds-color-text-inverse);
--navds-button-color-tertiary-border-hover: var(--navds-color-action-default);
--navds-button-color-tertiary-border-focus: var(--navds-color-action-default);
--navds-button-color-tertiary-border-active: var(--navds-color-white);
--navds-button-color-tertiary-background-active: var(
--navds-color-action-active
);
/* Danger */
--navds-button-color-danger-text: var(--navds-color-white);
--navds-button-color-danger-background: var(--navds-color-danger-default);
--navds-button-color-danger-background-hover: var(--navds-color-danger-hover);
--navds-button-color-danger-background-active: var(
--navds-color-danger-active
);
--navds-button-color-danger-border-focus: var(--navds-color-white);
/* Disabled */
--navds-button-color-text-disabled: var(--navds-color-text-inverse);
--navds-button-color-background-disabled: var(--navds-color-disabled);
}
.navds-button {
display: inline-flex;
cursor: pointer;
background-color: var(--navds-color-background);
color: var(--navds-color-action-default);
margin: 0;
text-align: center;
text-decoration: none;
border-color: var(--navds-color-action-default);
border: none;
background: none;
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(var(--navds-spacing-3) - 2px) var(--navds-spacing-3);
min-width: 48px;
padding: 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: 0.25rem calc(var(--navds-spacing-4) - 2px);
min-height: 32px;
.navds-button--small {
padding-top: 0.375rem;
padding-bottom: 0.375rem;
min-width: 32px;
}
.navds-button:focus {
@@ -49,94 +74,135 @@
box-shadow: var(--navds-shadow-focus);
}
/**************************
* .navds-button--primary *
**************************/
.navds-button--primary:hover,
.navds-button--primary:active {
color: var(--navds-color-text-inverse);
background-color: var(--navds-color-action-hover);
border-color: transparent;
.navds-button__inner {
margin: auto;
display: flex;
align-items: center;
gap: var(--navds-spacing-2);
}
.navds-button--primary:active {
background-color: var(--navds-color-action-active);
.navds-button svg {
font-size: 1.5rem;
}
/****************************
.navds-button--small svg {
font-size: 1.25rem;
}
/*************************
* .navds-button--primary *
*************************/
.navds-button--primary {
background-color: var(--navds-button-color-primary-background);
color: var(--navds-button-color-primary-text);
}
.navds-button--primary:hover {
background-color: var(--navds-button-color-primary-background-hover);
}
.navds-button--primary:active {
background-color: var(--navds-button-color-primary-background-active);
}
.navds-button--primary:focus {
box-shadow: inset 0 0 0 1px var(--navds-button-color-primary-border-focus),
var(--navds-shadow-focus);
}
/**************************
* .navds-button--secondary *
****************************/
**************************/
.navds-button--secondary {
border-color: transparent;
background-color: transparent;
color: var(--navds-button-color-secondary-text);
background-color: var(--navds-button-color-secondary-background);
box-shadow: inset 0 0 0 2px var(--navds-button-color-secondary-border);
}
.navds-button--secondary:hover {
color: var(--navds-button-color-secondary-text-hover);
background-color: var(--navds-button-color-secondary-background-hover);
box-shadow: none;
}
.navds-button--secondary:hover,
.navds-button--secondary:focus {
border-color: var(--navds-color-action-default);
box-shadow: inset 0 0 0 2px var(--navds-button-color-secondary-border),
var(--navds-shadow-focus);
}
.navds-button--secondary:active {
color: var(--navds-color-text-inverse);
border-color: var(--navds-color-action-active);
background-color: var(--navds-color-action-active);
color: var(--navds-button-color-secondary-text-active);
background-color: var(--navds-button-color-secondary-background-active);
box-shadow: none;
}
.navds-button--secondary:focus:hover,
.navds-button--secondary:focus:active {
box-shadow: inset 0 0 0 1px
var(--navds-button-color-secondary-border-focus-active-hover),
var(--navds-shadow-focus);
}
/****************************
* .navds-button--tertiary *
****************************/
.navds-button--tertiary {
color: var(--navds-button-color-tertiary-text);
}
.navds-button--tertiary:hover {
box-shadow: inset 0 0 0 2px var(--navds-button-color-tertiary-border-hover);
}
.navds-button--tertiary:focus {
box-shadow: inset 0 0 0 2px var(--navds-button-color-tertiary-border-focus),
var(--navds-shadow-focus);
}
.navds-button--tertiary:active {
color: var(--navds-button-color-tertiary-text-active);
background-color: var(--navds-button-color-tertiary-background-active);
box-shadow: inset 0 0 0 1px var(--navds-button-color-tertiary-border-active);
}
.navds-button--tertiary:active:focus {
box-shadow: inset 0 0 0 1px var(--navds-button-color-tertiary-border-active),
var(--navds-shadow-focus);
}
/*************************
* .navds-button--action *
* .navds-button--danger *
*************************/
.navds-button--action {
background-color: var(--navds-color-action-default);
border-color: var(--navds-color-action-default);
}
.navds-button--danger {
background-color: var(--navds-color-danger-default);
border-color: var(--navds-color-danger-default);
}
.navds-button--action,
.navds-button--danger {
color: white;
border-width: 1px;
}
.navds-button--action:hover {
background-color: var(--navds-color-action-hover);
border-color: var(--navds-color-action-hover);
background-color: var(--navds-button-color-danger-background);
color: var(--navds-button-color-danger-text);
}
.navds-button--danger:hover {
background-color: var(--navds-color-danger-hover);
border-color: var(--navds-color-danger-hover);
}
.navds-button--action:active {
background-color: var(--navds-color-action-active);
background-color: var(--navds-button-color-danger-background-hover);
}
.navds-button--danger:active {
background-color: var(--navds-color-danger-active);
background-color: var(--navds-button-color-danger-background-active);
}
.navds-button--action:focus,
.navds-button--danger:focus {
border-color: white;
box-shadow: inset 0 0 0 1px var(--navds-button-color-danger-border-focus),
var(--navds-shadow-focus);
}
/**************************
* .navds-button:disabled *
**************************/
.navds-button:disabled:disabled {
background-color: var(--navds-color-disabled);
color: var(--navds-color-text-inverse);
.navds-button:disabled {
color: var(--navds-button-color-text-disabled);
background-color: var(--navds-button-color-background-disabled);
cursor: not-allowed;
border-width: 0;
box-shadow: none;
transform: none;
}
+25 -11
View File
@@ -1,31 +1,45 @@
:root {
--navds-card-micro-color-text: var(--navds-color-text-primary);
--navds-card-micro-color-background: var(--navds-color-orange-20);
--navds-card-micro-color-border: transparent;
--navds-card-micro-color-text-hover: var(--navds-color-blue-50);
--navds-card-micro-color-background-hover: var(--navds-color-white);
--navds-card-micro-color-border-hover: var(--navds-color-blue-50);
--navds-card-micro-color-text-focus: var(--navds-color-blue-50);
--navds-card-micro-color-background-focus: var(--navds-color-white);
--navds-card-micro-color-shadow-focus: var(--navds-color-blue-80);
--navds-card-micro-color-background-active: var(--navds-color-blue-70);
--navds-card-micro-color-text-active: var(--navds-color-white);
}
/*
MicroCard
*/
.navds-card__micro {
border-radius: 1rem;
color: var(--navds-color-text-primary);
color: var(--navds-card-micro-color-text);
display: inline-flex;
padding: var(--navds-spacing-1) var(--navds-spacing-2);
text-decoration: none;
background-color: var(--navds-color-orange-20);
border: 1px solid transparent;
background-color: var(--navds-card-micro-color-background);
border: 1px solid var(--navds-card-micro-color-border);
}
.navds-card__micro:hover {
background-color: var(--navds-color-white);
border-color: var(--navds-color-blue-50);
color: var(--navds-color-blue-50);
background-color: var(--navds-card-micro-color-background-hover);
border-color: var(--navds-card-micro-color-border-hover);
color: var(--navds-card-micro-color-text-hover);
}
.navds-card__micro:focus {
background-color: var(--navds-color-white);
color: var(--navds-color-blue-50);
background-color: var(--navds-card-micro-color-background-focus);
color: var(--navds-card-micro-color-text-focus);
outline: none;
box-shadow: var(--navds-shadow-focus);
box-shadow: 0 0 0 3px var(--navds-card-micro-color-shadow-focus);
}
.navds-card__micro:active {
background-color: var(--navds-color-blue-70);
color: var(--navds-color-white);
background-color: var(--navds-card-micro-color-background-active);
color: var(--navds-card-micro-color-text-active);
}
-8
View File
@@ -1,11 +1,3 @@
.navds-copy-to-clipboard {
display: inline-flex;
align-items: center;
column-gap: 0.5em;
padding: var(--navds-spacing-1);
min-height: 32px;
}
.navds-copy-to-clipboard__popover {
padding: var(--navds-spacing-1);
}
+3 -3
View File
@@ -1,13 +1,13 @@
.navds-checkbox-group--s > .navds-checkboxes {
.navds-checkbox-group--small > .navds-checkboxes {
display: flex;
flex-direction: column;
gap: 4px;
}
.navds-fieldset.navds-checkbox-group--m > .navds-checkboxes {
.navds-fieldset.navds-checkbox-group--medium > .navds-checkboxes {
margin-top: 0;
}
.navds-fieldset.navds-checkbox-group--m > .navds-fieldset__error {
.navds-fieldset.navds-checkbox-group--medium > .navds-fieldset__error {
margin-top: 0;
}
+41 -19
View File
@@ -1,3 +1,25 @@
:root {
--navds-checkbox-color-background: var(--navds-color-white);
--navds-checkbox-color-border: var(--navds-color-gray-60);
--navds-checkbox-color-label-hover: var(--navds-color-blue-50);
--navds-checkbox-color-border-hover: var(--navds-color-blue-50);
--navds-checkbox-color-background-hover: var(--navds-color-blue-10);
--navds-checkbox-color-description: var(--navds-color-gray-80);
--navds-checkbox-color-border-checked: var(--navds-color-blue-50);
--navds-checkbox-color-background-checked: var(--navds-color-blue-50);
--navds-checkbox-color-shadow-error: var(--navds-color-red-50);
--navds-checkbox-color-border-error: var(--navds-color-red-50);
/* Disabled */
--navds-checkbox-color-label-disabled: var(--navds-color-gray-40);
--navds-checkbox-color-border-disabled: var(--navds-color-gray-60);
--navds-checkbox-color-background-disabled: var(--navds-color-gray-10);
--navds-checkbox-color-border-checked-disabled: var(--navds-color-gray-40);
--navds-checkbox-color-background-checked-disabled: var(
--navds-color-gray-40
);
}
.navds-checkbox {
position: relative;
padding: var(--navds-spacing-3) 0;
@@ -24,7 +46,7 @@
.navds-checkbox__description {
padding-left: calc(48px - 12px);
color: var(--navds-color-gray-80);
color: var(--navds-checkbox-color-description);
}
.navds-checkbox--with-description {
@@ -45,37 +67,37 @@
.navds-checkbox__label::before {
content: "";
background-color: white;
border: 1px solid var(--navds-color-border);
background-color: var(--navds-checkbox-color-background);
border: 1px solid var(--navds-checkbox-color-border);
width: 1.5rem;
height: 1.5rem;
border-radius: 4px;
flex-shrink: 0;
}
.navds-checkbox--s {
.navds-checkbox--small {
padding: var(--navds-spacing-1) 0;
}
.navds-checkbox--s > .navds-checkbox__input {
.navds-checkbox--small > .navds-checkbox__input {
width: 24px;
height: 24px;
top: 2px;
left: 0;
}
.navds-checkbox--s > .navds-checkbox__label::before {
.navds-checkbox--small > .navds-checkbox__label::before {
margin-top: -2px;
margin-bottom: -2px;
}
.navds-checkbox__input:hover + .navds-checkbox__label {
color: var(--navds-color-blue-50);
color: var(--navds-checkbox-color-label-hover);
}
.navds-checkbox__input:hover + .navds-checkbox__label::before {
border-color: var(--navds-color-blue-50);
background-color: var(--navds-color-blue-10);
border-color: var(--navds-checkbox-color-border-hover);
background-color: var(--navds-checkbox-color-background-hover);
}
.navds-checkbox__input:focus + .navds-checkbox__label::before {
@@ -87,8 +109,8 @@
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);
border: 2px solid var(--navds-checkbox-color-border-checked);
background-color: var(--navds-checkbox-color-background-checked);
}
.navds-checkbox__input:checked:focus + .navds-checkbox__label::before {
@@ -99,26 +121,26 @@
.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);
box-shadow: 0 0 0 1px var(--navds-checkbox-color-shadow-error);
border-color: var(--navds-checkbox-color-border-error);
}
.navds-checkbox--s .navds-error-message {
.navds-checkbox--small .navds-error-message {
margin-top: 4px;
}
.navds-checkbox__input:disabled,
.navds-checkbox__input:disabled + .navds-checkbox__label {
color: var(--navds-color-gray-40);
color: var(--navds-checkbox-color-label-disabled);
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);
background-color: var(--navds-checkbox-color-background-disabled);
border-color: var(--navds-checkbox-color-border-disabled);
}
.navds-checkbox__input:disabled:checked + .navds-checkbox__label::before {
background-color: var(--navds-color-gray-40);
border-color: var(--navds-color-gray-40);
background-color: var(--navds-checkbox-color-background-checked-disabled);
border-color: var(--navds-checkbox-color-border-checked-disabled);
}
+46 -10
View File
@@ -1,10 +1,40 @@
:root {
--navds-confirmation-panel-color-background: var(
--navds-color-warning-background
);
--navds-confirmation-panel-color-background-checked: var(
--navds-color-success-background
);
--navds-confirmation-panel-color-border-checked: var(
--navds-color-success-background
);
--navds-confirmation-panel-color-background-error: var(
--navds-color-error-background
);
--navds-confirmation-panel-color-checkbox-background-checked-hover: var(
--navds-color-green-70
);
--navds-confirmation-panel-color-checkbox-border-checked-hover: var(
--navds-color-green-70
);
--navds-confirmation-panel-color-checkbox-background-checked: var(
--navds-color-green-50
);
--navds-confirmation-panel-color-checkbox-border-checked: var(
--navds-color-green-50
);
--navds-confirmation-panel-color-checkbox-label-checked: var(
--navds-color-darkgray
);
}
.navds-confirmation-panel {
display: flex;
flex-direction: column;
gap: var(--navds-spacing-4);
padding: var(--navds-spacing-4);
border-radius: 4px;
background-color: #ffeccc;
background-color: var(--navds-confirmation-panel-color-background);
transition: background-color linear 100ms;
}
@@ -12,18 +42,18 @@
max-width: 80ch;
}
.navds-confirmation-panel--s {
.navds-confirmation-panel--small {
padding: var(--navds-spacing-3);
gap: var(--navds-spacing-2);
}
.navds-confirmation-panel--checked {
background-color: #ccf1d6;
border-color: #ccf1d6;
background-color: var(--navds-confirmation-panel-color-background-checked);
border-color: var(--navds-confirmation-panel-color-border-checked);
}
.navds-confirmation-panel--error {
background-color: var(--navds-color-error-background);
background-color: var(--navds-confirmation-panel-color-background-error);
border: 1px solid transparent;
}
@@ -36,23 +66,29 @@
.navds-confirmation-panel--checked
.navds-checkbox__input:hover
+ .navds-checkbox__label {
color: var(--navds-color-darkgray);
color: var(--navds-confirmation-panel-color-checkbox-label-checked);
}
.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-color: var(
--navds-confirmation-panel-color-checkbox-background-checked
);
border-color: var(--navds-confirmation-panel-color-checkbox-border-checked);
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);
background-color: var(
--navds-confirmation-panel-color-checkbox-background-checked-hover
);
border-color: var(
--navds-confirmation-panel-color-checkbox-border-checked-hover
);
}
.navds-confirmation-panel--checked
+5 -1
View File
@@ -1,4 +1,8 @@
:root {
--navds-error-message-color-text: var(--navds-color-text-error);
}
.navds-error-message {
display: block;
color: var(--navds-color-red-50);
color: var(--navds-error-message-color-text);
}
+11 -6
View File
@@ -1,10 +1,15 @@
.navds-error-summary {
background-color: #fff;
padding: var(--navds-spacing-4);
border: 4px solid #ba3a26;
:root {
--navds-error-summary-color-background: var(--navds-color-white);
--navds-error-summary-color-border: var(--navds-color-error-border);
}
.navds-error-summary--s {
.navds-error-summary {
background-color: var(--navds-error-summary-color-background);
padding: var(--navds-spacing-4);
border: 4px solid var(--navds-error-summary-color-border);
}
.navds-error-summary--small {
padding: var(--navds-spacing-2);
}
@@ -20,6 +25,6 @@
gap: 0.25rem;
}
.navds-error-summary--s > .navds-error-summary__list {
.navds-error-summary--small > .navds-error-summary__list {
margin: 0.5rem 0;
}
+1 -1
View File
@@ -9,7 +9,7 @@
margin-top: 8px;
}
.navds-fieldset--s > :not(:first-child):not(:empty) {
.navds-fieldset--small > :not(:first-child):not(:empty) {
margin-top: 4px;
}
+2 -2
View File
@@ -3,8 +3,8 @@
margin-top: 8px;
}
.navds-form-field--s > :not(:first-child):not(:empty),
.navds-form-field--s > input:not(:first-child) {
.navds-form-field--small > :not(:first-child):not(:empty),
.navds-form-field--small > input:not(:first-child) {
margin-top: 4px;
}
+3 -3
View File
@@ -1,13 +1,13 @@
.navds-radio-group--s > .navds-radio-buttons {
.navds-radio-group--small > .navds-radio-buttons {
display: flex;
flex-direction: column;
gap: 4px;
}
.navds-fieldset.navds-radio-group--m > .navds-radio-buttons {
.navds-fieldset.navds-radio-group--medium > .navds-radio-buttons {
margin-top: 0;
}
.navds-fieldset.navds-radio-group--m > .navds-fieldset__error {
.navds-fieldset.navds-radio-group--medium > .navds-fieldset__error {
margin-top: 0;
}
+49 -22
View File
@@ -1,3 +1,27 @@
:root {
--navds-radio-color-description: var(--navds-color-gray-80);
--navds-radio-color-background: var(--navds-color-white);
--navds-radio-color-border: var(--navds-color-gray-60);
--navds-radio-color-label-hover: var(--navds-color-blue-50);
--navds-radio-color-border-hover: var(--navds-color-blue-50);
--navds-radio-color-background-hover: var(--navds-color-blue-10);
--navds-radio-color-border-checked: var(--navds-color-blue-50);
--navds-radio-color-shadow-checked: var(--navds-color-blue-50);
--navds-radio-color-shadow-checked-focus: var(--navds-color-blue-80);
--navds-radio-color-shadow-background-checked-focus: var(--navds-color-white);
--navds-radio-color-shadow-dot-checked-focus: var(--navds-color-blue-50);
--navds-radio-color-shadow-error: var(--navds-color-red-50);
--navds-radio-color-border-error: var(--navds-color-red-50);
/* Disabled */
--navds-radio-color-background-disabled: var(--navds-color-gray-10);
--navds-radio-color-border-disabled: var(--navds-color-gray-60);
--navds-radio-color-label-disabled: var(--navds-color-gray-40);
--navds-radio-color-background-disabled-checked: var(--navds-color-gray-40);
--navds-radio-color-border-disabled-checked: var(--navds-color-gray-40);
--navds-radio-color-shadow-disabled-checked: var(--navds-color-gray-40);
}
.navds-radio {
position: relative;
padding: var(--navds-spacing-3) 0;
@@ -33,7 +57,7 @@
.navds-radio__description {
padding-left: calc(48px - 12px);
color: var(--navds-color-gray-80);
color: var(--navds-radio-color-description);
}
.navds-radio--with-description {
@@ -46,8 +70,8 @@
.navds-radio__label::before {
content: "";
background-color: white;
border: 1px solid var(--navds-color-border);
background-color: var(--navds-radio-color-background);
border: 1px solid var(--navds-radio-color-border);
width: 1.5rem;
height: 1.5rem;
border-radius: 4px;
@@ -55,29 +79,29 @@
border-radius: 50%;
}
.navds-radio--s {
.navds-radio--small {
padding: var(--navds-spacing-1) 0;
}
.navds-radio--s > .navds-radio__input {
.navds-radio--small > .navds-radio__input {
width: 24px;
height: 24px;
top: 2px;
left: 0;
}
.navds-radio--s > .navds-radio__label::before {
.navds-radio--small > .navds-radio__label::before {
margin-top: -2px;
margin-bottom: -2px;
}
.navds-radio__input:hover + .navds-radio__label {
color: var(--navds-color-blue-50);
color: var(--navds-radio-color-label-hover);
}
.navds-radio__input:hover + .navds-radio__label::before {
border-color: var(--navds-color-blue-50);
background-color: var(--navds-color-blue-10);
border-color: var(--navds-radio-color-border-hover);
background-color: var(--navds-radio-color-background-hover);
}
.navds-radio__input:focus + .navds-radio__label::before {
@@ -85,40 +109,43 @@
}
.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;
border: 2px solid var(--navds-radio-color-border-checked);
box-shadow: 0 0 0 3px #fff inset,
0 0 0 2rem var(--navds-radio-color-shadow-checked) 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;
box-shadow: 0 0 0 3px var(--navds-radio-color-shadow-checked-focus),
0 0 0 3px var(--navds-radio-color-shadow-background-checked-focus) inset,
0 0 0 2rem var(--navds-radio-color-shadow-dot-checked-focus) 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);
box-shadow: 0 0 0 1px var(--navds-radio-color-shadow-error);
border-color: var(--navds-radio-color-border-error);
}
.navds-radio--s .navds-error-message {
.navds-radio--small .navds-error-message {
margin-top: 4px;
}
.navds-radio__input:disabled,
.navds-radio__input:disabled + .navds-radio__label {
color: var(--navds-color-gray-40);
color: var(--navds-radio-color-label-disabled);
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);
background-color: var(--navds-radio-color-background-disabled);
border-color: var(--navds-radio-color-border-disabled);
}
.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;
background-color: var(--navds-radio-color-background-disabled-checked);
border-color: var(--navds-radio-color-border-disabled-checked);
box-shadow: 0 0 0 3px #fff inset,
0 0 0 2rem var(--navds-radio-color-shadow-disabled-checked) inset;
}
+20 -7
View File
@@ -1,9 +1,17 @@
.navds-search-field__input-wrapper {
display: flex;
:root {
--navds-search-field-color-shadow-error: var(--navds-color-red-50);
--navds-search-field-color-border-error: var(--navds-color-red-50);
--navds-search-field-color-clearbutton-border: var(--navds-color-gray-60);
}
.navds-form-field--s .navds-search-field__input {
padding: 0.25rem;
.navds-search-field__input-wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.navds-form-field--small .navds-search-field__input {
padding: 0.15rem;
min-height: 32px;
}
@@ -22,11 +30,16 @@
}
.navds-search-field__input-wrapper :focus {
z-index: 1;
z-index: var(--navds-z-index-focus);
}
.navds-search-field__button,
.navds-search-field__clear-button {
flex-shrink: 0;
}
.navds-search-field--error
.navds-search-field__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-color-red-50) inset;
border-color: var(--navds-color-red-50);
box-shadow: 0 0 0 1px var(--navds-search-field-color-shadow-error) inset;
border-color: var(--navds-search-field-color-border-error);
}
+21 -13
View File
@@ -1,9 +1,20 @@
:root {
--navds-select-color-background: var(--navds-color-white);
--navds-select-color-border: var(--navds-color-gray-60);
--navds-select-color-border-hover: var(--navds-color-blue-50);
--navds-select-color-border-error: var(--navds-color-red-50);
--navds-select-color-shadow-error: var(--navds-color-red-50);
--navds-select-color-border-disabled: var(--navds-color-gray-40);
--navds-select-color-background-disabled: var(--navds-color-gray-10);
--navds-select-color-text-disabled: var(--navds-color-darkgray);
}
.navds-select__input {
appearance: none;
padding: 0.5rem;
background-color: white;
background-color: var(--navds-select-color-background);
border-radius: 4px;
border: 1px solid var(--navds-color-gray-40);
border: 1px solid var(--navds-select-color-border);
width: 100%;
box-sizing: border-box;
min-height: 48px;
@@ -13,7 +24,7 @@
}
.navds-select__input:hover {
border-color: var(--navds-color-blue-50);
border-color: var(--navds-select-color-border-hover);
}
.navds-select__input:focus {
@@ -35,7 +46,7 @@
pointer-events: none;
}
.navds-form-field--s .navds-select__input {
.navds-form-field--small .navds-select__input {
min-height: 32px;
padding: 0.25rem;
}
@@ -44,19 +55,16 @@
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);
box-shadow: 0 0 0 1px var(--navds-select-color-shadow-error);
border-color: var(--navds-select-color-border-error);
}
/*
Disabled handling
TODO: Oppdatere farger her
*/
/* Disabled handling */
.navds-select__input:disabled,
.navds-select__input[read-only] {
background-color: var(--navds-color-gray-10);
border-color: var(--navds-color-gray-40);
background-color: var(--navds-select-color-background-disabled);
border-color: var(--navds-select-color-border-disabled);
box-shadow: none;
color: var(--navds-color-darkgray);
color: var(--navds-select-color-text-disabled);
cursor: not-allowed;
}
+32 -14
View File
@@ -1,20 +1,31 @@
:root {
--navds-text-field-color-background: var(--navds-color-white);
--navds-text-field-color-border: var(--navds-color-gray-60);
--navds-text-field-color-border-hover: var(--navds-color-blue-50);
--navds-text-field-color-border-error: var(--navds-color-red-50);
--navds-text-field-color-shadow-error: var(--navds-color-red-50);
--navds-text-field-color-border-disabled: var(--navds-color-gray-40);
--navds-text-field-color-background-disabled: var(--navds-color-gray-10);
--navds-text-field-color-text-disabled: var(--navds-color-darkgray);
}
.navds-text-field__input {
appearance: none;
padding: 0.5rem;
background-color: white;
background-color: var(--navds-text-field-color-background);
border-radius: 4px;
border: 1px solid var(--navds-color-border);
border: 1px solid var(--navds-text-field-color-border);
min-height: 48px;
width: 100%;
}
.navds-form-field--s > .navds-text-field__input {
padding: 0.25rem;
.navds-form-field--small > .navds-text-field__input {
padding: 0.15rem;
min-height: 32px;
}
.navds-text-field__input:hover {
border-color: var(--navds-color-blue-50);
border-color: var(--navds-text-field-color-border-hover);
}
.navds-text-field__input:focus {
@@ -27,19 +38,26 @@
*/
.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);
box-shadow: 0 0 0 1px var(--navds-text-field-color-shadow-error);
border-color: var(--navds-text-field-color-border-error);
}
/*
TODO: Oppdater denne til riktige farger
Disabled handling
*/
/* Disabled handling */
.navds-text-field__input:disabled,
.navds-text-field__input[readonly] {
background-color: #f1f1f1;
border-color: #6a6a6a;
background-color: var(--navds-text-field-color-background-disabled);
border-color: var(--navds-text-field-color-border-disabled);
box-shadow: none;
color: #262626;
color: var(--navds-text-field-color-text-disabled);
cursor: not-allowed;
}
/**
* Removes default search icon
*/
.navds-text-field__input[type="search"]::-webkit-search-decoration,
.navds-text-field__input[type="search"]::-webkit-search-cancel-button,
.navds-text-field__input[type="search"]::-webkit-search-results-button,
.navds-text-field__input[type="search"]::-webkit-search-results-decoration {
-webkit-appearance: none;
}
+25 -13
View File
@@ -1,3 +1,16 @@
:root {
--navds-textarea-color-background: var(--navds-color-white);
--navds-textarea-color-border: var(--navds-color-gray-60);
--navds-textarea-color-border-hover: var(--navds-color-blue-50);
--navds-textarea-color-border-error: var(--navds-color-red-50);
--navds-textarea-color-shadow-error: var(--navds-color-red-50);
--navds-textarea-color-counter-text: var(--navds-color-gray-40);
--navds-textarea-color-counter-text-error: var(--navds-color-red-50);
--navds-textarea-color-text-disabled: var(--navds-color-darkgray);
--navds-textarea-color-border-disabled: var(--navds-color-gray-40);
--navds-textarea-color-background-disabled: var(--navds-color-gray-10);
}
.navds-textarea__wrapper {
position: relative;
width: 100%;
@@ -6,9 +19,9 @@
.navds-textarea__input {
appearance: none;
padding: var(--navds-spacing-2);
background-color: white;
background-color: var(--navds-textarea-color-background);
border-radius: 4px;
border: 1px solid var(--navds-color-border);
border: 1px solid var(--navds-textarea-color-border);
resize: none;
width: 100%;
transition: height 0.1s ease-out;
@@ -21,7 +34,7 @@
}
.navds-textarea__input:hover {
border-color: var(--navds-color-blue-50);
border-color: var(--navds-textarea-color-border-hover);
}
.navds-textarea__input:focus {
@@ -29,18 +42,18 @@
box-shadow: var(--navds-shadow-focus);
}
.navds-form-field--s .navds-textarea__input {
.navds-form-field--small .navds-textarea__input {
padding: var(--navds-spacing-1);
min-height: 32px;
}
.navds-form-field--s .navds-textarea--counter.navds-textarea__input {
.navds-form-field--small .navds-textarea--counter.navds-textarea__input {
padding-bottom: var(--navds-spacing-7);
}
.navds-textarea__counter {
pointer-events: none;
color: var(--navds-color-gray-40);
color: var(--navds-textarea-color-counter-text);
font-style: italic;
position: absolute;
text-align: right;
@@ -50,7 +63,7 @@
}
.navds-textarea__counter--error {
color: var(--navds-color-red-50);
color: var(--navds-textarea-color-counter-text-error);
}
/**
@@ -58,19 +71,18 @@
*/
.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);
box-shadow: 0 0 0 1px var(--navds-textarea-color-shadow-error);
border-color: var(--navds-textarea-color-border-error);
}
/*
TODO: Oppdater denne til riktige farger
Disabled handling
*/
.navds-textarea__input:disabled,
.navds-textarea__input[readonly] {
background-color: #f1f1f1;
border-color: #6a6a6a;
background-color: var(--navds-textarea-color-background-disabled);
border-color: var(--navds-textarea-color-border-disabled);
box-shadow: none;
color: #262626;
color: var(--navds-textarea-color-text-disabled);
cursor: not-allowed;
}
+76
View File
@@ -0,0 +1,76 @@
:root {
--navds-guide-panel-color-background: var(--navds-color-background);
--navds-guide-panel-color-border: var(--navds-color-blue-40);
--navds-guide-panel-color-illustration-background: var(--navds-color-blue-20);
}
/**
* GuidePanel component
*/
.navds-guide-panel {
position: relative;
padding-left: 2.5rem;
}
.navds-guide-panel__content {
background-color: var(--navds-guide-panel-color-background);
border-radius: 4px;
border: 2px solid var(--navds-guide-panel-color-border);
min-height: 7.25rem;
padding: 1.5rem;
padding-left: 3.5rem;
}
.navds-guide-panel--poster {
padding-left: 0;
padding-top: 3.125rem;
}
.navds-guide-panel--poster .navds-guide-panel__content {
padding: 2rem;
padding-top: 4.25rem;
}
.navds-guide-panel .navds-guide {
position: absolute;
top: 1rem;
transform: translateX(-50%);
}
.navds-guide-panel--poster .navds-guide {
left: 50%;
top: 0;
}
/**
* Guide component
*/
.navds-guide {
display: flex;
align-items: center;
justify-content: center;
}
/* Guide illustration frame */
.navds-guide__illustration {
background: var(--navds-guide-panel-color-illustration-background);
border-radius: 50%;
overflow: hidden;
}
.navds-guide__illustration svg,
.navds-guide__illustration img {
height: 100%;
width: 100%;
}
/* Illustration sizes */
.navds-guide__illustration--small {
height: 5rem;
width: 5rem;
}
.navds-guide__illustration--medium {
height: 6.25rem;
width: 6.25rem;
}
-63
View File
@@ -1,63 +0,0 @@
.navds-header {
display: flex;
justify-content: center;
background-color: var(--navds-color-background);
padding-top: 1.5rem;
padding-bottom: 1.5rem;
padding-left: calc((100vw - 100%) / 2);
padding-right: calc((100vw - 100%) / 2);
margin-left: calc((100vw - 100%) / -2);
margin-right: calc((100vw - 100%) / -2);
}
.navds-header__wrapper {
width: 100%;
max-width: 56.5rem;
text-align: start;
}
.navds-header__title {
display: flex;
margin: 0 auto;
width: 100%;
position: relative;
flex-direction: column;
}
.navds-header--left > .navds-header__wrapper {
text-align: start;
}
.navds-header--center > .navds-header__wrapper {
text-align: center;
}
.navds-header__illustration {
margin-right: 1.5rem;
pointer-events: none;
}
.navds-header__illustration > svg {
width: 5rem;
height: 5rem;
}
.navds-header--situation {
box-shadow: 0 -4px 0 var(--navds-color-orange-40) inset;
}
.navds-header--product {
box-shadow: 0 -4px 0 var(--navds-color-green-40) inset;
}
.navds-header--guide {
box-shadow: 0 -4px 0 var(--navds-color-deepblue-40) inset;
}
@media (max-width: 649px) {
.navds-header__illustration > svg {
width: 3rem;
height: 3rem;
}
.navds-header__title {
font-size: var(--navds-font-size-title-xl);
}
}
+54
View File
@@ -0,0 +1,54 @@
:root {
--navds-help-text-color-button-background: transparent;
--navds-help-text-color-icon: var(--navds-color-blue-50);
--navds-help-text-color-icon-hover: var(--navds-color-white);
--navds-help-text-color-icon-background-hover: var(--navds-color-blue-50);
--navds-help-text-color-icon-shadow-hover: var(--navds-color-blue-50);
--navds-help-text-color-icon-focus: var(--navds-color-white);
--navds-help-text-color-icon-background-focus: var(--navds-color-blue-50);
--navds-help-text-color-icon-shadow-focus: var(--navds-color-blue-80);
--navds-help-text-color-popover-background: var(--navds-color-lightblue-10);
}
.navds-help-text__button {
margin: 0;
padding: 0;
border: 0;
cursor: pointer;
background-color: var(--navds-help-text-color-button-background);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.navds-help-text__button:focus {
outline: none;
}
.navds-help-text__icon {
border-radius: 50%;
font-size: 1.5rem;
color: var(--navds-help-text-color-icon);
}
.navds-help-text__button:hover > .navds-help-text__icon {
color: var(--navds-help-text-color-icon-hover);
background: var(--navds-help-text-color-icon-background-hover);
box-shadow: 0 0 0 2px var(--navds-help-text-color-icon-shadow-hover);
}
.navds-help-text__button:focus > .navds-help-text__icon {
outline: none;
color: var(--navds-help-text-color-icon-focus);
background: var(--navds-help-text-color-icon-background-focus);
box-shadow: 0 0 0 3px var(--navds-help-text-color-icon-shadow-focus);
}
.navds-help-text__popover > .navds-popover__arrow::before {
background-color: var(--navds-help-text-color-popover-background);
}
.navds-help-text__popover.navds-popover {
background-color: var(--navds-help-text-color-popover-background);
}
+6 -2
View File
@@ -6,12 +6,12 @@
@import "accordion-menu.css";
@import "alert.css";
@import "button.css";
@import "card.css";
@import "content-container.css";
@import "copy-to-clipboard.css";
@import "header.css";
@import "internal-header.css";
@import "guide-panel.css";
@import "form/index.css";
@import "help-text.css";
@import "link.css";
@import "loader.css";
@import "modal.css";
@@ -20,3 +20,7 @@
@import "panel.css";
@import "link-panel.css";
@import "speech-bubble.css";
/* Navno spesific packages */
@import "page-header.css";
@import "card.css";
+12 -6
View File
@@ -1,3 +1,9 @@
:root {
--navds-internal-header-color-background: var(--navds-color-darkgray);
--navds-internal-header-color-border: var(--navds-color-gray-40);
--navds-internal-header-color-text: var(--navds-color-text-inverse);
}
/**************************
* .navds-header *
**************************/
@@ -5,8 +11,8 @@
.navds-interal-header {
display: flex;
align-items: center;
background: var(--navds-color-darkgray);
color: white;
background: var(--navds-internal-header-color-background);
color: var(--navds-internal-header-color-text);
max-width: 100vw;
min-height: 50px;
}
@@ -22,13 +28,13 @@
.navds-interal-header__title {
padding: 0 var(--navds-spacing-6);
border-right: 1px solid var(--navds-color-gray-40);
border-right: 1px solid var(--navds-internal-header-color-border);
display: flex;
align-self: stretch;
align-items: center;
text-decoration: none;
margin: 0;
color: var(--navds-color-text-inverse);
color: var(--navds-internal-header-color-text);
}
.navds-interal-header__title > span > a {
@@ -46,10 +52,10 @@
**************************/
.navds-interal-header__user {
color: var(--navds-color-text-inverse);
color: var(--navds-internal-header-color-text);
padding: 0 var(--navds-spacing-6);
margin-left: auto;
border-left: 1px solid var(--navds-color-gray-40);
border-left: 1px solid var(--navds-internal-header-color-border);
display: flex;
align-self: stretch;
align-items: center;
+21 -10
View File
@@ -1,19 +1,26 @@
.navds-link-panel {
display: flex;
justify-content: space-between;
align-items: center;
text-decoration: none;
color: var(--navds-color-gray-90);
:root {
--navds-link-panel-color-text: var(--navds-color-gray-90);
--navds-link-panel-color-border-hover: var(--navds-color-blue-50);
--navds-link-panel-color-title-hover: var(--navds-color-text-link);
}
.navds-link-panel:hover .navds-link-panel-title {
.navds-link-panel {
text-decoration: none;
color: var(--navds-link-panel-color-text);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--navds-spacing-2);
}
.navds-link-panel:hover .navds-link-panel__title {
text-decoration: underline;
color: var(--navds-color-text-link);
color: var(--navds-link-panel-color-title-hover);
}
.navds-link-panel:hover {
box-shadow: var(--navds-shadow-hover);
border-color: var(--navds-color-blue-50);
border-color: var(--navds-link-panel-color-border-hover);
}
.navds-link-panel:focus {
@@ -22,12 +29,16 @@
}
.navds-link-panel__chevron {
flex-shrink: 0;
font-size: 1.5rem;
transition: transform 200ms;
flex-shrink: 0;
}
.navds-link-panel:hover > .navds-link-panel__chevron,
.navds-link-panel:focus-within > .navds-link-panel__chevron {
transform: translateX(4px);
}
.navds-link-panel__description {
margin-top: var(--navds-spacing-2);
}
+26 -12
View File
@@ -1,16 +1,30 @@
:root {
--navds-link-color-text: var(--navds-color-text-link);
--navds-link-color-text-focus: var(--navds-color-text-inverse);
--navds-link-color-text-active: var(--navds-color-text-inverse);
--navds-link-color-background-focus: var(--navds-text-focus);
--navds-link-color-background-active: var(--navds-text-focus);
--navds-link-color-icon: var(--navds-color-text-link);
--navds-link-color-icon-focus: var(--navds-color-text-inverse);
--navds-link-color-on-info-background: var(--navds-color-text-primary);
--navds-link-color-on-error-background: var(--navds-color-text-primary);
}
.navds-link {
color: var(--navds-color-text-link);
color: var(--navds-link-color-text);
text-decoration: underline;
display: inline-grid;
grid-auto-flow: column;
display: inline-flex;
align-items: center;
gap: 0.25rem;
gap: var(--navds-spacing-1);
}
.navds-alert--info .navds-link {
color: var(--navds-link-color-on-info-background);
}
.navds-alert--error .navds-link,
.navds-alert--info .navds-link,
.navds-confirmation-panel--error .navds-link {
color: var(--navds-color-text-primary);
color: var(--navds-link-color-on-error-background);
}
.navds-link:hover {
@@ -19,24 +33,24 @@
.navds-link:focus {
outline: none;
color: var(--navds-color-text-inverse);
color: var(--navds-link-color-text-focus);
text-decoration: none;
background-color: var(--navds-text-focus);
background-color: var(--navds-link-color-background-focus);
box-shadow: var(--navds-text-shadow);
}
.navds-link:active {
outline: none;
color: var(--navds-color-text-inverse);
color: var(--navds-link-color-text-active);
text-decoration: none;
background-color: var(--navds-text-focus);
background-color: var(--navds-link-color-background-active);
box-shadow: var(--navds-text-shadow);
}
.navds-link svg {
color: var(--navds-color-text-link);
color: var(--navds-link-color-icon);
}
.navds-link:focus svg {
color: var(--navds-color-text-inverse);
color: var(--navds-link-color-icon-focus);
}
+30 -18
View File
@@ -1,3 +1,15 @@
:root {
--navds-loader-color-foreground: var(--navds-color-gray-40);
--navds-loader-color-background: var(--navds-color-gray-10);
--navds-loader-color-neutral-foreground: var(--navds-color-gray-40);
--navds-loader-color-interaction-foreground: var(--navds-color-blue-50);
--navds-loader-color-inverted-foreground: var(--navds-color-white);
--navds-loader-color-inverted-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-transparent-background: transparent;
--navds-loader-color-on-button-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-on-button-foreground: currentColor;
}
.navds-loader {
width: 1.5rem;
display: inline-block;
@@ -9,54 +21,54 @@
animation: loader-dasharray 1.4s ease-in-out infinite;
stroke-dasharray: 80px, 200px;
stroke-dashoffset: 0;
stroke: var(--navds-color-gray-40);
stroke: var(--navds-loader-color-foreground);
}
.navds-loader__background {
stroke: var(--navds-color-gray-10);
stroke: var(--navds-loader-color-background);
}
.navds-loader--neutral .navds-loader__foreground {
stroke: var(--navds-color-gray-40);
stroke: var(--navds-loader-color-neutral-foreground);
}
.navds-loader--interaction .navds-loader__foreground {
stroke: var(--navds-color-blue-50);
stroke: var(--navds-loader-color-interaction-foreground);
}
.navds-loader--inverted .navds-loader__foreground {
stroke: white;
stroke: var(--navds-loader-color-inverted-foreground);
}
.navds-loader--inverted .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
stroke: var(--navds-loader-color-inverted-background);
}
.navds-loader--transparent .navds-loader__background {
stroke: transparent;
stroke: var(--navds-loader-color-transparent-background);
}
.navds-loader--2xl {
.navds-loader--2xlarge {
width: 4rem;
}
.navds-loader--xl {
.navds-loader--xlarge {
width: 2.5rem;
}
.navds-loader--l {
.navds-loader--large {
width: 2rem;
}
.navds-loader--m {
.navds-loader--medium {
width: 1.5rem;
}
.navds-loader--s {
.navds-loader--small {
width: 1.25rem;
}
.navds-loader--xs {
.navds-loader--xsmall {
width: 1rem;
}
@@ -65,20 +77,20 @@
*/
.navds-button .navds-loader .navds-loader__foreground {
stroke: currentColor;
stroke: var(--navds-loader-color-on-button-foreground);
}
.navds-button:hover .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button:active .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button--action .navds-loader .navds-loader__background,
.navds-button--primary .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: rgba(255, 255, 255, 0.3);
stroke: var(--navds-loader-color-on-button-background);
}
@keyframes loader-rotate {
+12 -5
View File
@@ -1,16 +1,23 @@
:root {
--navds-modal-color-background: var(--navds-color-background);
--navds-modal-color-overlay: var(--navds-color-modal-overlay);
}
.ReactModal__Body--open {
overflow: hidden;
}
.navds-modal {
background-color: var(--navds-color-background);
padding: var(--navds-spacing-4);
background-color: var(--navds-modal-color-background);
border-radius: 4px;
display: block;
position: relative;
overflow: auto;
max-height: 100%;
z-index: var(--navds-z-index-modal-content);
}
.navds-modal__content {
padding: var(--navds-spacing-4);
}
.navds-modal:focus,
@@ -21,12 +28,12 @@
.navds-modal__overlay {
position: fixed;
z-index: var(--navds-z-index-modal-overlay);
z-index: var(--navds-z-index-modal);
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--navds-color-modal-overlay);
background-color: var(--navds-modal-color-overlay);
padding: var(--navds-spacing-4);
display: flex;
align-items: center;
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.7.4",
"version": "0.8.3",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
@@ -18,13 +18,13 @@
"main": "./dist/index.css",
"scripts": {
"build": "postcss --use postcss-import -o dist/index.css index.css",
"watch-css": "postcss -w --use postcss-import -o dist/index.css index.css"
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^0.4.4",
"@navikt/ds-tokens": "^0.5.1",
"normalize.css": "^8.0.1",
"postcss": "^8.2.7",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
"postcss-import": "^14.0.0"
"postcss-import": "^14.0.2"
}
}
+70
View File
@@ -0,0 +1,70 @@
:root {
--navds-page-header-color-background: var(--navds-color-background);
--navds-page-header-color-shadow-situation: var(--navds-color-orange-40);
--navds-page-header-color-shadow-product: var(--navds-color-green-40);
--navds-page-header-color-shadow-guide: var(--navds-color-deepblue-40);
}
.navds-page-header {
display: flex;
justify-content: center;
background-color: var(--navds-page-header-color-background);
padding-top: 1.5rem;
padding-bottom: 1.5rem;
padding-left: calc((100vw - 100%) / 2);
padding-right: calc((100vw - 100%) / 2);
margin-left: calc((100vw - 100%) / -2);
margin-right: calc((100vw - 100%) / -2);
}
.navds-page-header__wrapper {
width: 100%;
max-width: 56.5rem;
text-align: start;
}
.navds-page-header__title {
display: flex;
margin: 0 auto;
width: 100%;
position: relative;
flex-direction: column;
}
.navds-page-header--left > .navds-page-header__wrapper {
text-align: start;
}
.navds-page-header--center > .navds-page-header__wrapper {
text-align: center;
}
.navds-page-header__illustration {
margin-right: 1.5rem;
pointer-events: none;
}
.navds-page-header__illustration > svg {
width: 5rem;
height: 5rem;
}
.navds-page-header--situation {
box-shadow: 0 -4px 0 var(--navds-page-header-color-shadow-situation) inset;
}
.navds-page-header--product {
box-shadow: 0 -4px 0 var(--navds-page-header-color-shadow-product) inset;
}
.navds-page-header--guide {
box-shadow: 0 -4px 0 var(--navds-page-header-color-shadow-guide) inset;
}
@media (max-width: 649px) {
.navds-page-header__illustration > svg {
width: 3rem;
height: 3rem;
}
.navds-page-header__title {
font-size: var(--navds-font-size-title-xl);
}
}
+7 -3
View File
@@ -1,11 +1,15 @@
:root {
--navds-panel-color-background: var(--navds-color-white);
--navds-panel-color-border: var(--navds-color-border);
}
.navds-panel {
background-color: var(--navds-color-white);
display: block;
background-color: var(--navds-panel-color-background);
padding: var(--navds-spacing-4);
border-radius: var(--navds-border-radius);
border: 1px solid transparent;
}
.navds-panel--border {
border-color: var(--navds-color-border);
border-color: var(--navds-panel-color-border);
}
+24 -15
View File
@@ -1,9 +1,20 @@
:root {
--navds-popover-color-background: var(--navds-color-background);
--navds-popover-color-border: var(--navds-color-gray-40);
--navds-popover-color-shadow: var(--navds-color-gray-20);
}
.navds-popover {
z-index: var(--navds-z-index-popover-default);
background-color: var(--navds-color-background);
box-shadow: 0 0.05rem 0.25rem 0.125rem rgba(0, 0, 0, 0.08);
border: var(--navds-border-default);
border-radius: 2px;
z-index: var(--navds-z-index-popover);
background-color: var(--navds-popover-color-background);
box-shadow: 0 2px 4px 0 var(--navds-popover-color-shadow);
border: 1px solid;
border-color: var(--navds-popover-color-border);
border-radius: 4px;
}
.navds-popover__content {
padding: var(--navds-spacing-4);
}
.navds-popover--hidden {
@@ -16,22 +27,20 @@
}
.navds-popover__arrow {
z-index: var(--navds-z-index-popover-arrow);
z-index: -1;
}
.navds-popover__arrow::before {
content: "";
display: block;
content: "";
transform: rotate(45deg);
background-color: var(--navds-popover-color-background);
border: 1px solid;
border-color: var(--navds-popover-color-border);
width: 1rem;
height: 1rem;
transform: rotate(45deg);
background-color: var(--navds-color-background);
border: var(--navds-border-default);
}
.navds-popover__arrow::before .navds-popover--small {
width: 0.67rem;
height: 0.67rem;
top: 0;
left: 0;
}
.navds-popover[data-popper-placement^="top"] > .navds-popover__arrow {
+19 -6
View File
@@ -1,3 +1,13 @@
:root {
--navds-speechbubble-color-background: var(--navds-color-gray-10);
--navds-speechbubble-color-shadow: var(--navds-color-gray-20);
--navds-speechbubble-color-illustration: var(--navds-color-darkgray);
--navds-speechbubble-color-illustration-background: var(
--navds-color-gray-20
);
--navds-speechbubble-color-detail-text: var(--navds-color-gray-60);
}
.navds-speechbubble {
display: flex;
align-items: flex-end;
@@ -23,8 +33,8 @@
.navds-speechbubble__illustration {
align-items: center;
background: var(--navds-color-gray-20);
color: var(--navds-color-darkgray);
background: var(--navds-speechbubble-color-illustration-background);
color: var(--navds-speechbubble-color-illustration);
border-radius: 50%;
display: flex;
flex-shrink: 0;
@@ -42,10 +52,10 @@
.navds-speechbubble__bubble {
padding: 1rem;
box-shadow: 0 2px 4px 0 var(--navds-color-gray-20);
box-shadow: 0 2px 4px 0 var(--navds-speechbubble-color-shadow);
width: fit-content;
max-width: 37.5rem;
background-color: var(--navds-color-gray-10);
background-color: var(--navds-speechbubble-color-background);
border-radius: 12px;
border-bottom-left-radius: 2px;
display: flex;
@@ -61,9 +71,12 @@
.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);
color: var(--navds-speechbubble-color-detail-text);
}
.navds-speechbubble--right .navds-speechbubble__top-text {
align-self: flex-end;
}
+40 -16
View File
@@ -1,30 +1,54 @@
.navds-tag {
border-radius: 4px;
border: var(--navds-border-default);
background-color: var(--navds-color-tag-info-background);
border-color: var(--navds-color-tag-info-border);
display: inline-block;
:root {
--navds-tag-color-border: var(--navds-color-gray-40);
--navds-tag-color-background: var(--navds-color-gray-10);
--navds-tag-color-info-background: var(--navds-color-tag-info-background);
--navds-tag-color-info-border: var(--navds-color-tag-info-border);
--navds-tag-color-warning-background: var(
--navds-color-tag-warning-background
);
--navds-tag-color-warning-border: var(--navds-color-tag-warning-border);
--navds-tag-color-success-background: var(
--navds-color-tag-success-background
);
--navds-tag-color-success-border: var(--navds-color-tag-success-border);
--navds-tag-color-error-background: var(--navds-color-tag-error-background);
--navds-tag-color-error-border: var(--navds-color-tag-error-border);
}
/* Padding calculated based on 16px font for 24px tall tag */
padding: 0.0625rem var(--navds-spacing-2);
.navds-tag {
border: 1px solid;
border-color: var(--navds-tag-color-border);
border-radius: 4px;
background-color: var(--navds-tag-color-background);
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.125rem var(--navds-spacing-3);
min-height: 32px;
}
.navds-tag--small {
min-height: 24px;
padding-right: var(--navds-spacing-1);
padding-left: var(--navds-spacing-1);
}
.navds-tag--error {
background-color: var(--navds-color-tag-error-background);
border-color: var(--navds-color-tag-error-border);
background-color: var(--navds-tag-color-error-background);
border-color: var(--navds-tag-color-error-border);
}
.navds-tag--success {
background-color: var(--navds-color-tag-success-background);
border-color: var(--navds-color-tag-success-border);
background-color: var(--navds-tag-color-success-background);
border-color: var(--navds-tag-color-success-border);
}
.navds-tag--warning {
background-color: var(--navds-color-tag-warning-background);
border-color: var(--navds-color-tag-warning-border);
background-color: var(--navds-tag-color-warning-background);
border-color: var(--navds-tag-color-warning-border);
}
.navds-tag--info {
background-color: var(--navds-color-tag-info-background);
border-color: var(--navds-color-tag-info-border);
background-color: var(--navds-tag-color-info-background);
border-color: var(--navds-tag-color-info-border);
}
+66 -47
View File
@@ -1,64 +1,75 @@
/* Title */
.navds-title {
/* Heading */
.navds-heading {
font-weight: var(--navds-font-weight-bold);
margin: 0;
}
.navds-title--2xl {
font-size: var(--navds-font-size-title-2xl);
.navds-heading--2xlarge {
font-size: var(--navds-font-size-heading-2xl);
letter-spacing: -0.01em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-heading-2xl);
}
.navds-title--2xl.navds-typo--spacing {
.navds-heading--2xlarge.navds-typo--spacing {
margin-bottom: var(--navds-spacing-5);
}
.navds-title--xl {
font-size: var(--navds-font-size-title-xl);
.navds-heading--xlarge {
font-size: var(--navds-font-size-heading-xl);
letter-spacing: -0.008em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-heading-xl);
}
.navds-title--xl.navds-typo--spacing {
.navds-heading--xlarge.navds-typo--spacing {
margin-bottom: var(--navds-spacing-4);
}
.navds-title--l {
font-size: var(--navds-font-size-title-l);
.navds-heading--large {
font-size: var(--navds-font-size-heading-l);
letter-spacing: -0.004em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-heading-l);
}
.navds-title--l.navds-typo--spacing {
.navds-heading--large.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
.navds-title--m {
font-size: var(--navds-font-size-title-m);
.navds-heading--medium {
font-size: var(--navds-font-size-heading-m);
letter-spacing: -0.002em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-heading-m);
}
.navds-title--m.navds-typo--spacing {
.navds-heading--medium.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
.navds-title--s {
font-size: var(--navds-font-size-title-s);
.navds-heading--small {
font-size: var(--navds-font-size-heading-s);
letter-spacing: -0.001em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-heading-s);
}
.navds-title--s.navds-typo--spacing {
.navds-heading--small.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
.navds-heading--xsmall {
font-size: var(--navds-font-size-heading-xs);
letter-spacing: -0.001em;
line-height: var(--navds-font-line-height-heading-xs);
}
.navds-heading--xsmall.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
/* Ingress */
.navds-ingress {
font-size: var(--navds-font-size-xl);
font-weight: var(--navds-font-weight-regular);
letter-spacing: -0.001em;
line-height: var(--navds-font-line-height-m);
line-height: var(--navds-font-line-height-xl);
margin: 0;
}
@@ -69,15 +80,9 @@
/* Body */
.navds-body-long {
font-size: var(--navds-font-size-l);
font-weight: var(--navds-font-weight-regular);
letter-spacing: 0;
line-height: var(--navds-font-line-height-m);
margin: 0;
}
.navds-body-short {
font-size: var(--navds-font-size-l);
letter-spacing: 0;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-xl);
margin: 0;
}
@@ -85,30 +90,44 @@
margin-bottom: var(--navds-spacing-7);
}
.navds-body-long--small {
font-size: var(--navds-font-size-m);
letter-spacing: 0.002em;
line-height: var(--navds-font-line-height-l);
}
.navds-body-long--small.navds-typo--spacing {
margin-bottom: var(--navds-spacing-6);
}
.navds-body-short {
font-size: var(--navds-font-size-l);
font-weight: var(--navds-font-weight-regular);
letter-spacing: 0;
line-height: var(--navds-font-line-height-l);
margin: 0;
}
.navds-body-short.navds-typo--spacing {
margin-bottom: var(--navds-spacing-3);
}
.navds-body--s {
.navds-body-short--small {
font-size: var(--navds-font-size-m);
letter-spacing: 0.002em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-m);
}
.navds-body-long.navds-body--s.navds-typo--spacing {
margin-bottom: var(--navds-spacing-6);
}
.navds-body-short.navds-body--s.navds-typo--spacing {
.navds-body-short--small.navds-typo--spacing {
margin-bottom: var(--navds-spacing-2);
}
/* Label */
.navds-label {
font-size: var(--navds-font-size-l);
letter-spacing: 0;
line-height: var(--navds-font-line-height-s);
font-weight: var(--navds-font-weight-bold);
letter-spacing: 0;
line-height: var(--navds-font-line-height-l);
margin: 0;
}
@@ -116,22 +135,22 @@
margin-bottom: var(--navds-spacing-3);
}
.navds-label--s {
.navds-label--small {
font-size: var(--navds-font-size-m);
letter-spacing: 0.002em;
line-height: var(--navds-font-line-height-s);
line-height: var(--navds-font-line-height-m);
}
.navds-label--s.navds-typo--spacing {
.navds-label--small.navds-typo--spacing {
margin-bottom: var(--navds-spacing-2);
}
/* Small text */
.navds-detail {
font-size: var(--navds-font-size-s);
letter-spacing: 0.004em;
line-height: var(--navds-font-line-height-s);
font-weight: var(--navds-font-weight-bold);
letter-spacing: 0.004em;
line-height: var(--navds-font-line-height-m);
margin: 0;
}
@@ -139,10 +158,10 @@
margin-bottom: var(--navds-spacing-2);
}
.navds-detail--s {
.navds-detail--small {
font-weight: var(--navds-font-weight-regular);
}
.navds-detail--s.navds-typo--spacing {
.navds-detail--small.navds-typo--spacing {
margin-bottom: var(--navds-spacing-2);
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "0.5.2",
"version": "0.5.3",
"private": false,
"description": "NAVs egne ikoner i SVG og React format",
"repository": {
@@ -29,22 +29,22 @@
"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.mjs",
"clean": "rimraf src esm cjs png NAV-ikonpakke-png.zip NAV-ikonpakke-svg.zip",
"clean": "rimraf src 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"
"build": "yarn clean && yarn create-icons && tsc && tsc -p tsconfig-esm.json && yarn create-package-json-pointers-to-esm && yarn run convert-icons && yarn zip-icons"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
},
"devDependencies": {
"@svgr/cli": "^5.4.0",
"@svgr/cli": "^5.5.0",
"copyfiles": "^2.4.1",
"dotenv": "^8.2.0",
"dotenv": "^10.0.0",
"lodash.kebabcase": "^4.1.1",
"lodash.startcase": "4.4.0",
"react": "^16.8.0 || ^17.0.0",
"rimraf": "3.0.2",
"sharp": "0.27.1",
"sharp": "0.29.1",
"zip-dir": "^2.0.0"
}
}
+1
View File
@@ -0,0 +1 @@
import "@testing-library/jest-dom/extend-expect";
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
transform: {
"^.+\\.tsx?$": "ts-jest",
},
setupFilesAfterEnv: ["<rootDir>/jest-setup.ts"],
testEnvironment: "jsdom",
};
+22 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.7.6",
"version": "0.9.2",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
@@ -30,24 +30,36 @@
"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"
"watch": "tsc --watch -p tsconfig-esm.json",
"test": "jest"
},
"dependencies": {
"@material-ui/core": "^4.12.2",
"@navikt/ds-icons": "^0.5.2",
"@popperjs/core": "^2.5.4",
"@material-ui/core": "^4.12.3",
"@navikt/ds-icons": "^0.5.3",
"@popperjs/core": "^2.10.1",
"classnames": "^2.2.6",
"copy-to-clipboard": "^3.3.1",
"react-collapse": "^5.1.0",
"react-merge-refs": "^1.1.0",
"react-modal": "3.12.1",
"react-popper": "^2.2.4",
"short-uuid": "^4.2.0"
"react-modal": "3.14.3",
"react-popper": "^2.2.5",
"uuid": "^8.3.2"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.0",
"@testing-library/user-event": "^13.2.1",
"@types/faker": "^5.5.8",
"@types/jest": "^27.0.1",
"@types/react-router-dom": "^5.1.9",
"@types/styled-components": "^5.1.14",
"copyfiles": "^2.4.1",
"react-router-dom": "^5.2.0",
"rimraf": "3.0.2"
"faker": "^5.5.3",
"jest": "^27.2.0",
"react-router-dom": "^5.3.0",
"rimraf": "3.0.2",
"styled-components": "^5.3.1",
"ts-jest": "^27.0.5"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
@@ -1,11 +1,23 @@
import React, { forwardRef, HTMLAttributes } from "react";
import React, { forwardRef } from "react";
import cl from "classnames";
import MenuItems from "./MenuItems";
import Collapsable, {
AccordionMenuCollapsableType,
} from "./AccordionMenuCollapsable";
import Item, { AccordionMenuItemType } from "./AccordionMenuItem";
export interface AccordionMenuProps extends HTMLAttributes<HTMLElement> {
export interface AccordionMenuProps extends React.HTMLAttributes<HTMLElement> {
children: React.ReactNode;
}
interface AccordionMenuComponent
extends React.ForwardRefExoticComponent<
AccordionMenuProps & React.RefAttributes<HTMLElement>
> {
Collapsable: AccordionMenuCollapsableType;
Item: AccordionMenuItemType;
}
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
({ children, className, ...rest }, ref) => {
return (
@@ -19,6 +31,9 @@ const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
</nav>
);
}
);
) as AccordionMenuComponent;
AccordionMenu.Collapsable = Collapsable;
AccordionMenu.Item = Item;
export default AccordionMenu;
@@ -10,35 +10,38 @@ export interface AccordionMenuCollapsableProps
children: React.ReactNode;
}
const AccordionMenuCollapsable = forwardRef<
HTMLDivElement,
AccordionMenuCollapsableProps
>(({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
export type AccordionMenuCollapsableType = React.ForwardRefExoticComponent<
AccordionMenuCollapsableProps & React.RefAttributes<HTMLDivElement>
>;
return (
<div
ref={ref}
className={cl("navds-accordion-menu-collapsable", className, {
"navds-accordion-menu-collapsable--open": isOpen,
})}
{...rest}
>
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-accordion-menu-collapsable__button"
const Collapsable: AccordionMenuCollapsableType = forwardRef(
({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
return (
<div
ref={ref}
className={cl("navds-accordion-menu-collapsable", className, {
"navds-accordion-menu-collapsable--open": isOpen,
})}
{...rest}
>
{title}
<Expand
role="img"
focusable="false"
aria-label={isOpen ? "Pil peker opp" : "Pil peker ned"}
className="navds-accordion-menu-collapsable__expand-icon"
/>
</button>
{isOpen && <MenuItems>{children}</MenuItems>}
</div>
);
});
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-accordion-menu-collapsable__button"
>
{title}
<Expand
role="img"
focusable="false"
aria-label={isOpen ? "Pil peker opp" : "Pil peker ned"}
className="navds-accordion-menu-collapsable__expand-icon"
/>
</button>
{isOpen && <MenuItems>{children}</MenuItems>}
</div>
);
}
);
export default AccordionMenuCollapsable;
export default Collapsable;
@@ -1,26 +1,25 @@
import React, { forwardRef } from "react";
import { OverridableComponent } from "../util";
import { OverridableComponent } from "..";
import cl from "classnames";
export type AccordionMenuItemType = OverridableComponent<AccordionMenuItemProps>;
export interface AccordionMenuItemProps {
props: {
children: React.ReactNode;
active?: boolean;
} & React.HTMLAttributes<HTMLAnchorElement>;
defaultComponent: "a";
export interface AccordionMenuItemProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
children: React.ReactNode;
/**
* Sets active styling if true
* @default false
*/
active?: boolean;
}
const AccordionMenuItem: AccordionMenuItemType = forwardRef(
export type AccordionMenuItemType = OverridableComponent<
AccordionMenuItemProps,
HTMLAnchorElement
>;
const Item: AccordionMenuItemType = forwardRef(
(
{
children,
component: Component = "a",
active = false,
className,
...rest
},
{ children, as: Component = "a", active = false, className, ...rest },
ref
) => {
return (
@@ -37,4 +36,4 @@ const AccordionMenuItem: AccordionMenuItemType = forwardRef(
}
);
export default AccordionMenuItem;
export default Item;
+3 -6
View File
@@ -1,6 +1,3 @@
export { default as AccordionMenu } from "./AccordionMenu";
export { default as AccordionMenuCollapsable } from "./AccordionMenuCollapsable";
export {
default as AccordionMenuItem,
AccordionMenuItemType,
} from "./AccordionMenuItem";
export { default as AccordionMenu, AccordionMenuProps } from "./AccordionMenu";
export { AccordionMenuCollapsableProps } from "./AccordionMenuCollapsable";
export { AccordionMenuItemProps } from "./AccordionMenuItem";
@@ -1,9 +1,5 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import {
AccordionMenu,
AccordionMenuItem,
AccordionMenuCollapsable,
} from "../../index";
import { AccordionMenu } from "../../index";
<Meta title="ds-react/accordion-menu/intro" />
@@ -11,59 +7,59 @@ import {
```jsx
<AccordionMenu>
<AccordionMenuItem href="#leo">Leo</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla" active>
<AccordionMenu.item href="#leo">Leo</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla" active>
Nulla
</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
<AccordionMenuCollapsable title="Accumsan">
<AccordionMenuItem href="#justo" aria-current="page">
</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.item href="#justo" aria-current="page">
Justo
</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla">Nulla</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
</AccordionMenuCollapsable>
</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla">Nulla</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
```
<Canvas>
<AccordionMenu>
<AccordionMenuItem href="#leo">Leo</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla" active>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
<AccordionMenuCollapsable title="Accumsan">
<AccordionMenuItem href="#justo" aria-current="page">
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</AccordionMenuItem>
<AccordionMenuCollapsable title="Proin">
<AccordionMenuItem href="#nulla">Nulla</AccordionMenuItem>
<AccordionMenuItem href="#luctus">Luctus</AccordionMenuItem>
</AccordionMenuCollapsable>
</AccordionMenuCollapsable>
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla">Nulla</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
</Canvas>
Accordion-menu støtter opp til maks to-nivårer av `AccordionMenuCollapsable` akkurat nå.
Accordion-menu støtter opp til maks to-nivårer av `AccordionMenu.Collapsable` akkurat nå.
`AccordionMenuItem` er implementert med `OverridableComponent`, noe som
`AccordionMenu.Item` er implementert med `OverridableComponent`, noe som
gjør at man kan ta i bruk eks react-router slik:
```jsx
<Item
component={NavLink}
<AccordionMenu.item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Lenketekst
</Item>
</AccordionMenu.item>
```
Her er `NavLink` fra `react-router-dom` brukt, og man får da
@@ -1,29 +1,10 @@
import * as React from "react";
import {
AccordionMenu,
AccordionMenuItem as Item,
AccordionMenuCollapsable as Collapsable,
} from "../index";
import { AccordionMenu } from "../index";
import { NavLink, HashRouter as Router } from "react-router-dom";
export default {
title: "ds-react/accordion-menu",
component: { AccordionMenu },
parameters: {
backgrounds: {
default: "light",
values: [
{
name: "light",
value: "#F1F1F1",
},
{
name: "white",
value: "#fff",
},
],
},
},
};
export const All = () => (
@@ -34,113 +15,113 @@ export const All = () => (
}}
>
<AccordionMenu>
<Item href="#leo">Leo</Item>
<Collapsable title="Proin">
<Item href="#nulla" active>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</Item>
<Item href="#luctus">Luctus</Item>
</Collapsable>
<Collapsable title="Accumsan">
<Item href="#justo" aria-current="page">
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</Item>
<Item href="#pariatur" active aria-current="page">
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur" active aria-current="page">
Pariatur
</Item>
<Collapsable title="Proin">
<Item href="#nulla" active>
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</Item>
<Item href="#luctus">Luctus</Item>
</Collapsable>
</Collapsable>
<Item href="#justo" active>
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item href="#justo" active>
Justo
</Item>
<Item href="#pariatur">Pariatur</Item>
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur">Pariatur</AccordionMenu.Item>
</AccordionMenu>
</div>
);
export const ReactRouter = () => (
<AccordionMenu>
<Collapsable title="Nivå 1 – 3 rems høy">
<Item
component={NavLink}
<AccordionMenu.Collapsable title="Nivå 1 – 3 rems høy">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Nivå 2 innrykk 2 rems
</Item>
<Item
component={NavLink}
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/2"
>
Subtitle 3
</Item>
</Collapsable>
<Collapsable title="Skjema og søknad">
<Collapsable title="Satser">
<Item
component={NavLink}
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Skjema og søknad">
<AccordionMenu.Collapsable title="Satser">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/3"
>
Nivå 3 – 3 rems innrykk Har du rett til dagpenger når du mottar annen
økonomisk støtte fra NAV?
</Item>
</Collapsable>
<Item
component={NavLink}
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/4"
>
Subtitle 2
</Item>
<Item
component={NavLink}
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/5"
>
Subtitle 3
</Item>
</Collapsable>
<Collapsable title="Sakbehandlingstider">
<Collapsable title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
<Item
component={NavLink}
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Sakbehandlingstider">
<AccordionMenu.Collapsable title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/6"
>
Subtitle 5
</Item>
</Collapsable>
</Collapsable>
<Item
component={NavLink}
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/7"
>
Internasjonalt
</Item>
<Collapsable title="Meld fra om endringer lang tittel på første nivå">
<Item
component={NavLink}
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Meld fra om endringer lang tittel på første nivå">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/8"
>
Subtitle 6
</Item>
</Collapsable>
<Item
component={NavLink}
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/9"
>
Nivå 1
</Item>
</AccordionMenu.Item>
</AccordionMenu>
);
+25 -100
View File
@@ -1,108 +1,33 @@
import React, { forwardRef, useEffect, useState } from "react";
import cl from "classnames";
import { UnmountClosed, Collapse } from "react-collapse";
import { Expand, ExpandFilled } from "@navikt/ds-icons";
import { useId } from "..";
import React, { forwardRef } from "react";
import AccordionItem, { AccordionItemType } from "./AccordionItem";
import AccordionContent, { AccordionContentType } from "./AccordionContent";
import AccordionHeader, { AccordionHeaderType } from "./AccordionHeader";
export interface AccordionProps
extends React.HTMLAttributes<HTMLButtonElement> {
/**
* Component content
*/
children: React.ReactNode;
/**
* Content on interactive surface of component
*/
heading: React.ReactNode;
/**
* Opens component if 'true', closes if 'false'
* Using this props removes automatic control of open-state
* @default false
*/
open?: boolean;
/**
* Callback for when user interacts with component
*/
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
/**
* Removes content-element from dom when closed
* @default false
*/
renderContentWhenClosed?: boolean;
interface AccordionComponent
extends React.ForwardRefExoticComponent<
AccordionProps & React.RefAttributes<HTMLDivElement>
> {
Item: AccordionItemType;
Header: AccordionHeaderType;
Content: AccordionContentType;
}
const Accordion = forwardRef<HTMLButtonElement, AccordionProps>(
(
{
children,
heading,
open = false,
className,
renderContentWhenClosed = false,
onClick,
id,
...rest
},
ref
) => {
const [internalOpen, setInternalOpen] = useState<boolean>(open);
export interface AccordionProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Content inside accordion
*/
children: React.ReactNode;
}
const buttonId = useId(id);
const contentId = useId();
const Accordion = forwardRef<HTMLDivElement, AccordionProps>(
({ className, ...rest }, ref) => (
<div {...rest} className={cl("navds-accordion", className)} ref={ref} />
)
) as AccordionComponent;
useEffect(() => {
setInternalOpen(open);
}, [open]);
const CollapseComponent = renderContentWhenClosed
? Collapse
: UnmountClosed;
return (
<div
className={cl("navds-accordion", className, {
"navds-accordion--open": internalOpen,
"navds-accordion--closed": !internalOpen,
})}
>
<button
ref={ref}
id={buttonId}
className="navds-accordion__button"
aria-expanded={open}
aria-controls={contentId}
onClick={onClick ? onClick : () => setInternalOpen((open) => !open)}
{...rest}
>
<span className="navds-accordion__heading navds-title navds-title--s">
{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}>
<div className="navds-accordion__content">{children}</div>
</CollapseComponent>
</div>
</div>
);
}
);
Accordion.Header = AccordionHeader;
Accordion.Content = AccordionContent;
Accordion.Item = AccordionItem;
export default Accordion;
@@ -0,0 +1,59 @@
import cl from "classnames";
import React, { forwardRef, useContext } from "react";
import { Collapse, UnmountClosed } from "react-collapse";
import { useClientLayoutEffect, useId } from "../util";
import { AccordionItemContext } from "./AccordionItem";
export interface AccordionContentProps
extends React.HTMLAttributes<HTMLDivElement> {
/**
* Accordion panel content
*/
children: React.ReactNode;
}
export type AccordionContentType = React.ForwardRefExoticComponent<
AccordionContentProps & React.RefAttributes<HTMLDivElement>
>;
const AccordionContent: AccordionContentType = forwardRef(
({ children, className, id, ...rest }, ref) => {
const context = useContext(AccordionItemContext);
const newId = useId(id);
const setContentId = context && context.setContentId;
useClientLayoutEffect(() => {
setContentId && setContentId(id ? newId : `accordionContent-${newId}`);
}, [setContentId, newId]);
if (context === null) {
console.error(
"<Accordion.Content> has to be used within an <Accordion.Item>"
);
return null;
}
const CollapseComponent = context.renderContentWhenClosed
? Collapse
: UnmountClosed;
return (
<div
ref={ref}
id={context.contentId}
role="region"
aria-labelledby={context.buttonId}
{...rest}
>
<CollapseComponent isOpened={context.open}>
<div className={cl("navds-accordion__content", className)}>
{children}
</div>
</CollapseComponent>
</div>
);
}
);
export default AccordionContent;
@@ -0,0 +1,84 @@
import { Expand, ExpandFilled } from "@navikt/ds-icons";
import cl from "classnames";
import React, { forwardRef, useContext } from "react";
import { AccordionItemContext } from "./AccordionItem";
import { useClientLayoutEffect, useId } from "..";
export interface AccordionHeaderProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Button content
*/
children: React.ReactNode;
}
export type AccordionHeaderType = React.ForwardRefExoticComponent<
AccordionHeaderProps & React.RefAttributes<HTMLButtonElement>
>;
const AccordionHeader: AccordionHeaderType = forwardRef(
({ children, className, id, onClick, ...rest }, ref) => {
const context = useContext(AccordionItemContext);
const newId = useId(id);
const setButtonId = context && context.setButtonId;
useClientLayoutEffect(() => {
setButtonId && setButtonId(id ? newId : `accordionContent-${newId}`);
}, [setButtonId, newId]);
if (context === null) {
console.error(
"<Accordion.Header> has to be used within an <Accordion.Item>"
);
return null;
}
const handleClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
context.toggleOpen();
onClick && onClick(e);
};
return (
<button
ref={ref}
id={context.buttonId}
className={cl(
"navds-accordion__header",
className,
"navds-heading",
"navds-heading--small"
)}
onClick={handleClick}
aria-controls={context.contentId}
{...rest}
>
{children}
<Expand
focusable="false"
role="img"
aria-label={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
className={cl("navds-accordion__expand-icon", {
"navds-accordion__expand-icon--flip": context.open,
})}
/>
<ExpandFilled
focusable="false"
role="img"
aria-label={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
className={cl(
"navds-accordion__expand-icon",
"navds-accordion__expand-icon--filled",
{
"navds-accordion__expand-icon--flip": context.open,
}
)}
/>
</button>
);
}
);
export default AccordionHeader;
@@ -0,0 +1,93 @@
import cl from "classnames";
import React, { createContext, forwardRef, useState } from "react";
export interface AccordionItemProps
extends React.HTMLAttributes<HTMLDivElement> {
/**
* Content inside accordion item
*/
children: React.ReactNode;
/**
* Opens component if 'true', closes if 'false'
* Using this props removes automatic control of open-state
*/
open?: boolean;
/**
* Defaults the accordion to opened state
* @default false
*/
defaultOpen?: boolean;
/**
* Removes content-element from dom when closed
* @default false
*/
renderContentWhenClosed?: boolean;
}
export type AccordionItemType = React.ForwardRefExoticComponent<
AccordionItemProps & React.RefAttributes<HTMLDivElement>
>;
export interface AccordionItemContextProps {
open: boolean;
toggleOpen: () => void;
setButtonId: (id: string) => void;
setContentId: (id: string) => void;
buttonId: string;
contentId: string;
renderContentWhenClosed: boolean;
}
export const AccordionItemContext = createContext<AccordionItemContextProps | null>(
null
);
const AccordionItem: AccordionItemType = forwardRef(
(
{
children,
className,
open,
defaultOpen = false,
renderContentWhenClosed = false,
onClick,
id,
...rest
},
ref
) => {
const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);
const [buttonId, setButtonId] = useState("");
const [contentId, setContentId] = useState("");
return (
<div
className={cl("navds-accordion__item", className, {
"navds-accordion__item--open": open ?? internalOpen,
})}
ref={ref}
{...rest}
>
<AccordionItemContext.Provider
value={{
open: open ?? internalOpen,
toggleOpen: () => {
if (open === undefined) {
setInternalOpen((iOpen) => !iOpen);
}
},
renderContentWhenClosed,
setButtonId,
buttonId,
setContentId,
contentId,
}}
>
{children}
</AccordionItemContext.Provider>
</div>
);
}
);
export default AccordionItem;
@@ -1,4 +1,4 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Meta, Canvas, Props } from "@storybook/addon-docs";
import { Accordion } from "../../index";
<Meta title="ds-react/accordion/intro" />
@@ -6,28 +6,67 @@ import { Accordion } from "../../index";
# 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>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit occaecat nisi
qui nostrud sit.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Aliquip amet irure consectetur occaecat</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do deserunt
amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
<Canvas>
<Accordion 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>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>
Aliquip amet irure consectetur occaecat
</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do
deserunt amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</Canvas>
Accordion-komponeten styrer selv open/closed state, men om man ønsker kan man selv overskrive denne med
`open`-prop + `onClick`-prop.
## Controlled state
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
Accordion-komponeten styrer selv open-state, men om man ønsker kan man selv overskrive denne med
`open`-prop + `onClick`-prop slik det er gjort på eksemplet.
`renderContentWhenClosed`-prop bestemmer om innholdet (children) skal beholdes i dom-strukturen mens
```jsx
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={(open) => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
`renderContentWhenClosed`-prop på `Accordion.Item` bestemmer om innholdet (children) skal beholdes i dom-strukturen mens
Accordion er lukket. Defaulter til `false`.
@@ -1,9 +1,17 @@
import React, { useState } from "react";
import AccordionContent from "../AccordionContent";
import AccordionHeader from "../AccordionHeader";
import AccordionItem from "../AccordionItem";
import { Accordion } from "../index";
export default {
title: "ds-react/accordion",
component: Accordion,
subcomponents: {
AccordionItem,
AccordionContent,
AccordionHeader,
},
};
export const All = () => {
@@ -11,49 +19,74 @@ export const All = () => {
return (
<>
<h1>Accordion</h1>
<Accordion heading="tittel" open={open} onClick={(e) => setOpen(!open)}>
Eu magna fugiat officia sit ullamco reprehenderit reprehenderit officia.
Culpa fugiat irure deserunt irure enim adipisicing qui id. Pariatur
commodo dolore consequat nulla cupidatat commodo nisi sunt. Ad proident
occaecat cillum eu Lorem proident sunt anim officia voluptate. Veniam
ullamco magna elit amet mollit exercitation magna quis ad occaecat in
elit. Labore ad id pariatur consequat consectetur ullamco culpa dolor
dolor. Sunt irure eiusmod velit duis excepteur veniam consectetur eu
occaecat reprehenderit qui anim dolore. Ea voluptate dolore proident
esse aliqua amet magna pariatur incididunt ea excepteur. Aliquip magna
ut ipsum veniam eu laborum id commodo.
</Accordion>
<h1>Open</h1>
<Accordion heading="tittel" open={true} onClick={(e) => null}>
Eu magna fugiat officia sit ullamco reprehenderit reprehenderit officia.
Culpa fugiat irure deserunt irure enim adipisicing qui id. Pariatur
commodo dolore consequat nulla cupidatat commodo nisi sunt. Ad proident
occaecat cillum eu Lorem proident sunt anim officia voluptate. Veniam
ullamco magna elit amet mollit exercitation magna quis ad occaecat in
elit. Labore ad id pariatur consequat consectetur ullamco culpa dolor
dolor. Sunt irure eiusmod velit duis excepteur veniam consectetur eu
occaecat reprehenderit qui anim dolore. Ea voluptate dolore proident
esse aliqua amet magna pariatur incididunt ea excepteur. Aliquip magna
ut ipsum veniam eu laborum id commodo.
</Accordion>
<h1>Long heading</h1>
<Accordion
heading="Consequat incididunt aliquip aliquip fugiat anim cupidatat eu do ipsum pariatur."
open={open}
onClick={(e) => setOpen(!open)}
>
Eu magna fugiat officia sit ullamco reprehenderit reprehenderit officia.
Culpa fugiat irure deserunt irure enim adipisicing qui id. Pariatur
commodo dolore consequat nulla cupidatat commodo nisi sunt. Ad proident
occaecat cillum eu Lorem proident sunt anim officia voluptate. Veniam
ullamco magna elit amet mollit exercitation magna quis ad occaecat in
elit. Labore ad id pariatur consequat consectetur ullamco culpa dolor
dolor. Sunt irure eiusmod velit duis excepteur veniam consectetur eu
occaecat reprehenderit qui anim dolore. Ea voluptate dolore proident
esse aliqua amet magna pariatur incididunt ea excepteur. Aliquip magna
ut ipsum veniam eu laborum id commodo.
</Accordion>
<div>
<h1>Accordion</h1>
<h2>Controlled</h2>
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
<h2>Un-controlled</h2>
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</div>
</>
);
};
+66 -43
View File
@@ -1,4 +1,4 @@
import React, { forwardRef } from "react";
import React, { createContext, forwardRef } from "react";
import cl from "classnames";
import {
ErrorFilled,
@@ -6,80 +6,103 @@ import {
InformationFilled,
SuccessFilled,
} from "@navikt/ds-icons";
import AlertContent, { AlertContentType } from "./AlertContent";
import AlertTitle, { AlertTitleType } from "./AlertTitle";
import { BodyLong } from "..";
export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Alert content
*/
children: React.ReactNode;
/**
* Decides what design the alert will have
*/
variant: "error" | "warning" | "info" | "success";
children: React.ReactNode;
/**
* Changes padding and font-sizes
* @default "m"
* @default "medium"
*/
size?: "m" | "s";
size?: "medium" | "small";
/**
* Toggles full-width Alert
* @default false
*/
fullWidth?: boolean;
/**
* Removes background from Alert
*/
inline?: boolean;
}
const Icon = ({ variant }) => {
const Icon = ({ variant, ...props }) => {
switch (variant) {
case "error":
return (
<ErrorFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
return <ErrorFilled {...props} />;
case "warning":
return (
<WarningFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
return <WarningFilled {...props} />;
case "info":
return (
<InformationFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
return <InformationFilled {...props} />;
case "success":
return (
<SuccessFilled
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
/>
);
return <SuccessFilled {...props} />;
default:
return null;
}
};
export interface AlertContextProps {
size: "medium" | "small";
}
export const AlertContext = createContext<AlertContextProps | null>(null);
interface AlertComponent
extends React.ForwardRefExoticComponent<
AlertProps & React.RefAttributes<HTMLDivElement>
> {
Title: AlertTitleType;
Content: AlertContentType;
}
const Alert = forwardRef<HTMLDivElement, AlertProps>(
({ variant, children, className, size = "m", ...rest }, ref) => (
(
{
children,
className,
variant,
size = "medium",
fullWidth = false,
inline = false,
...rest
},
ref
) => (
<div
{...rest}
ref={ref}
className={cl(
className,
"navds-alert",
`navds-alert--${variant}`,
`navds-alert--${size}`,
"navds-body-long",
{ "navds-body--s": size === "s" }
{ "navds-alert--full-width": fullWidth, "navds-alert--inline": inline }
)}
{...rest}
>
<span>
<span className="sr-only">{`${variant}-ikon`}</span>
<Icon variant={variant} />
</span>
<div>{children}</div>
<Icon
aria-label={`${variant}-ikon`}
focusable="false"
role="img"
variant={variant}
alt={`${variant}-ikon`}
className="navds-alert__icon"
/>
<BodyLong as="div" size={size} className="navds-alert__wrapper">
{children}
</BodyLong>
</div>
)
);
) as AlertComponent;
Alert.Title = AlertTitle;
Alert.Content = AlertContent;
export default Alert;
@@ -0,0 +1,41 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { BodyLong } from "..";
import { AlertContext } from ".";
export interface AlertContentProps
extends React.HTMLAttributes<HTMLDivElement> {
/**
* Alert content
*/
children: React.ReactNode;
}
export type AlertContentType = React.ForwardRefExoticComponent<
AlertContentProps & React.RefAttributes<HTMLDivElement>
>;
const AlertContent: AlertContentType = forwardRef(
({ children, className, ...rest }, ref) => {
const context = useContext(AlertContext);
if (context === null) {
console.warn("AlertContent has to be wrapped in <Alert />");
return null;
}
return (
<BodyLong
{...rest}
as="div"
className={cl(className, "navds-alert__content")}
ref={ref}
size={context.size ?? "medium"}
>
{children}
</BodyLong>
);
}
);
export default AlertContent;
+41
View File
@@ -0,0 +1,41 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { AlertContext, Heading } from "..";
export interface AlertTitleProps extends React.HTMLAttributes<HTMLDivElement> {
/**
* Alert content
*/
children: React.ReactNode;
}
export type AlertTitleType = React.ForwardRefExoticComponent<
AlertTitleProps & React.RefAttributes<HTMLDivElement>
>;
const AlertTitle: AlertTitleType = forwardRef(
({ children, className, ...rest }, ref) => {
const context = useContext(AlertContext);
if (context === null) {
console.warn("AlertTitle has to be wrapped in <Alert />");
return null;
}
const size = context.size === "medium" ? "small" : "xsmall";
return (
<Heading
{...rest}
ref={ref}
className={cl(className, "navds-alert__title")}
as="div"
size={size}
>
{children}
</Heading>
);
}
);
export default AlertTitle;
@@ -1,5 +1,5 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Alert } from "../../index";
import { Alert, Heading, BodyLong } from "../../index";
<Meta title="ds-react/alert/intro" />
@@ -26,7 +26,7 @@ import { Alert } from "../../index";
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`info`, `success`, `warning` og `error`
`info`, `success`, `warning` og `error`.
<Canvas>
<Alert variant="info">Id elit esse enim reprehenderit.</Alert>
@@ -37,19 +37,60 @@ import { Alert } from "../../index";
## Sizing
Alert har to størrelser: Default 64px min-height og small 32px min-height
Alert har to størrelser: Default 64px height og small 32px height default.
<Canvas>
<Alert size="s" variant="info">
<Alert size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="success">
<Alert size="small" variant="success">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="warning">
<Alert size="small" variant="warning">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="s" variant="error">
<Alert size="small" variant="error">
Id elit esse enim reprehenderit.
</Alert>
</Canvas>
## fullWidth
<Canvas>
<div style={{ margin: 32, display: "grid", gap: 16 }}>
<Alert fullWidth variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert fullWidth size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
</div>
</Canvas>
## Med heading
```jsx
<Alert variant="info">
<Heading spacing size="small" level="2">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui laboris
ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat sint commodo
consequat eu aute.
</BodyLong>
</Alert>
```
<Canvas>
<Alert variant="info">
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui laboris
ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat sint commodo
consequat eu aute.
</BodyLong>
</Alert>
</Canvas>
@@ -1,5 +1,6 @@
import React from "react";
import { Alert } from "../index";
import { Alert } from "..";
import { BodyLong, Heading } from "../..";
export default {
title: "ds-react/alert",
@@ -17,21 +18,104 @@ export const All = () => {
return (
<>
<h1>Alert</h1>
{variants.map((variant) => (
{variants.map((variant, i) => (
<Alert key={variant} variant={variant}>
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.
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
<h2>Small</h2>
<div>
{variants.map((variant) => (
<Alert key={variant} variant={variant} size="s">
Exercitation enim nisi veniam nostrud Lorem ipsum ea fugiat. Aute
exercitation voluptate proident sit ex reprehenderit quis ex ut
mollit.
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Alert fullWidth</h2>
{variants.map((variant, i) => (
<Alert fullWidth key={variant} variant={variant}>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
<h2>Small</h2>
<div>
{variants.map((variant, i) => (
<Alert fullWidth key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Inline</h2>
<div>
{variants.map((variant, i) => (
<Alert inline key={variant} variant={variant}>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Inline small</h2>
<div>
{variants.map((variant, i) => (
<Alert inline key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud."
)}
</Alert>
))}
</div>
<h2>Med Heading</h2>
<div>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant}>
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong spacing>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
<Heading level="4" size="xsmall" spacing>
Ullamco eiusmod Lorem eiusmod eu.
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
</Alert>
))}
</div>
<h2>Med Heading small</h2>
<div>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} size="small">
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong spacing>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
<Heading level="4" size="xsmall" spacing>
Ullamco eiusmod Lorem eiusmod eu.
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna.
Fugiat sint commodo consequat eu aute.
</BodyLong>
</Alert>
))}
</div>
+24 -11
View File
@@ -1,5 +1,6 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { BodyShort, OverridableComponent } from "../";
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
@@ -11,12 +12,12 @@ export interface ButtonProps
* Changes design and interactions
* @default "primary"
*/
variant?: "primary" | "secondary" | "action" | "danger";
variant?: "primary" | "secondary" | "tertiary" | "danger";
/**
* Changes padding, height and font-size
* @default "m"
* @default "medium"
*/
size?: "m" | "s";
size?: "medium" | "small";
/**
* Prevent the user from interacting with the button: it cannot be pressed or focused.
* @note Avoid using if possible for accessibility purposes
@@ -25,20 +26,32 @@ export interface ButtonProps
disabled?: boolean;
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant = "primary", className, size = "m", ...rest }, ref) => (
<button
const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
(
{
as: Component = "button",
variant = "primary",
className,
children,
size = "medium",
...rest
},
ref
) => (
<Component
{...rest}
ref={ref}
className={cl(
className,
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`,
"navds-body-short",
{ "navds-body--s": size === "s" }
`navds-button--${size}`
)}
{...rest}
/>
>
<BodyShort as="span" className="navds-button__inner" size={size}>
{children}
</BodyShort>
</Component>
)
);
@@ -1,29 +1,29 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Button, Loader } from "../../index";
import { Success } from "@navikt/ds-react";
import { Success } from "@navikt/ds-icons";
<Meta title="ds-react/button/intro" />
# Hvordan ta i bruk Button
```jsx
<Button>Buttontekst</Button>
<Button>Button</Button>
```
<Canvas>
<Button>Buttontekst</Button>
<Button>Button</Button>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`primary`, `secondary`, `action` og `danger`
`primary`, `secondary`, `tertiary` og `danger`
<Canvas>
<Button variant="primary">Buttontekst</Button>
<Button variant="secondary">Buttontekst</Button>
<Button variant="action">Buttontekst</Button>
<Button variant="danger">Buttontekst</Button>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="danger">Danger</Button>
</Canvas>
## Sizing
@@ -31,35 +31,40 @@ import { Success } from "@navikt/ds-react";
Button har to størrelser: Default 48px min-height og small 32px min-height
<Canvas>
<Button size="s" variant="primary">
Buttontekst
<Button size="small" variant="primary">
Primary
</Button>
<Button size="s" variant="secondary">
Buttontekst
<Button size="small" variant="secondary">
Secondary
</Button>
<Button size="s" variant="action">
Buttontekst
<Button size="small" variant="tertiary">
Tertiary
</Button>
<Button size="s" variant="danger">
Buttontekst
<Button size="small" variant="danger">
Danger
</Button>
</Canvas>
## Med ikon eller `<Loader />`
Hvis man setter ikoner (svg) eller `<Loader />` rett på button vil størrelsen
bli justert automatisk. For å få riktige marginer rundt ikonet må man da wrappe innholdet
i et element
bli justert automatisk og sentrert.
<Canvas>
<Button>
<span>Buttontekst</span> <Loader />
<Loader /> Laster... <Loader />
</Button>
<Button size="s">
<span>Buttontekst</span>
<Button size="small">
<Loader />
Laster...
<Loader />
</Button>
<Button>
<Loader /> <span>Buttontekst</span>
<Success /> Laster... <Success />
</Button>
<Button size="small">
<Success />
Laster...
<Success />
</Button>
</Canvas>
@@ -10,35 +10,35 @@ export default {
const Section = ({ children }) => (
<div
style={{
display: "grid",
display: "flex",
gap: 16,
gridAutoFlow: "column",
justifyContent: "start",
padding: 24,
background: "lightgray",
paddingLeft: 0,
}}
>
{children}
</div>
);
const variants: Array<"primary" | "secondary" | "action" | "danger"> = [
const variants: Array<"primary" | "secondary" | "tertiary" | "danger"> = [
"primary",
"secondary",
"action",
"tertiary",
"danger",
];
const varSwitch = {
primary: "Primary",
secondary: "Secondary",
action: "Action",
tertiary: "Tertiary",
danger: "Danger",
};
export const All = () => {
return (
<>
<div style={{ paddingLeft: "1rem" }}>
<h1>Button</h1>
<Section>
{variants.map((variant) => (
@@ -58,19 +58,15 @@ export const All = () => {
<h2>As link</h2>
<Section>
{variants.map((variant) => (
<a
key={variant}
className={`navds-button navds-button--${variant} navds-body-short`}
href="the-link"
>
<Button as="a" key={variant} variant={variant} href="the-link">
{varSwitch[variant]}
</a>
</Button>
))}
</Section>
<h2>Small</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="s">
<Button key={variant} variant={variant} size="small">
{varSwitch[variant]}
</Button>
))}
@@ -79,26 +75,34 @@ export const All = () => {
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span>{varSwitch[variant]}</span> <Success />
{variant} <Success />
</Button>
))}
</Section>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span className="sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
<h2>Small w/icon</h2>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="s">
<Success /> <span>{varSwitch[variant]}</span>
<Button key={variant} variant={variant} size="small">
<Success /> {variant}
</Button>
))}
</Section>
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="s">
<Button key={variant} variant={variant} size="small">
<span className="sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
</>
</div>
);
};
+25 -23
View File
@@ -1,30 +1,32 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import { OverridableComponent } from "../util";
import { OverridableComponent } from "..";
export interface MicroCardProps {
props: {
children: string;
} & React.HTMLAttributes<HTMLAnchorElement>;
defaultComponent: "a";
export interface MicroCardProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
/**
* Link text
*/
children: React.ReactNode;
}
export const MicroCard: OverridableComponent<MicroCardProps> = forwardRef(
({ className, component: Component = "a", children, ...rest }, ref) => (
<Component
ref={ref}
className={cl(
"navds-card__micro",
"navds-detail",
"navds-detail--s",
className
)}
title={children}
{...rest}
>
{children}
</Component>
)
);
export const MicroCard: OverridableComponent<
MicroCardProps,
HTMLAnchorElement
> = forwardRef(({ className, as: Component = "a", children, ...rest }, ref) => (
<Component
ref={ref}
className={cl(
"navds-card__micro",
"navds-detail",
"navds-detail--small",
className
)}
title={children}
{...rest}
>
{children}
</Component>
));
export default MicroCard;
@@ -1,2 +0,0 @@
export { default as ContentContainer } from "./ContentContainer";
export * from "./ContentContainer";
@@ -1,31 +0,0 @@
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);
}
}
```
@@ -1,33 +0,0 @@
import * as React from "react";
import { ContentContainer } from "../index";
import { BodyLong } from "../../index";
import "./style.css";
export default {
title: "ds-react/content-container",
component: ContentContainer,
parameters: {
layout: "fullscreen",
backgrounds: {
default: "NAV gray",
values: [
{
name: "NAV gray",
value: "#f1f1f1",
},
{
name: "white",
value: "#ffffff",
},
],
},
},
};
export const All = () => {
return (
<ContentContainer className={"navds-story-content-container"}>
<BodyLong size="m">-- Innhold --</BodyLong>
</ContentContainer>
);
};
@@ -1,15 +0,0 @@
.navds-story-content-container {
display: flex;
border-radius: 0.25rem;
justify-content: center;
align-items: center;
margin-bottom: 1.5rem;
min-height: 10rem;
background: repeating-linear-gradient(
45deg,
#d6d6d6,
#d6d6d6 10px,
transparent 10px,
transparent 20px
);
}
@@ -1,18 +1,12 @@
import { Copy } from "@navikt/ds-icons";
import copy from "copy-to-clipboard";
import { Placement } from "@popperjs/core";
import cl from "classnames";
import React, {
forwardRef,
HTMLAttributes,
useEffect,
useRef,
useState,
} from "react";
import copy from "copy-to-clipboard";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import mergeRefs from "react-merge-refs";
import { Popover, Button } from "..";
import { BodyShort, Button, ButtonProps, Popover } from "..";
export interface CopyToClipboardProps
extends HTMLAttributes<HTMLButtonElement> {
export interface CopyToClipboardProps extends Omit<ButtonProps, "children"> {
/**
* Button text
*/
@@ -20,20 +14,31 @@ export interface CopyToClipboardProps
/**
* Text to be copied to clipboard
*/
text: string;
copyText: string;
/**
* Description of text, examples: "personnummer", "navn", "epost" etc.
*/
label: string;
popoverText: string;
/**
* Use a differnet icon to display
* @default "Files" from @navikt/ds-icons
* Allows extending popover properties like "placement"
* @default "right"
*/
icon?: React.ReactElement;
popoverPlacement?: Placement;
}
const CopyToClipboard = forwardRef<HTMLButtonElement, CopyToClipboardProps>(
({ children, text, label, icon, className, ...rest }, ref) => {
(
{
children,
copyText,
popoverText,
className,
size = "medium",
popoverPlacement = "right",
...rest
},
ref
) => {
const buttonRef = useRef<HTMLButtonElement>(null);
const mergedRef = mergeRefs([buttonRef, ref]);
const timeoutRef = useRef<number | null>();
@@ -48,10 +53,10 @@ const CopyToClipboard = forwardRef<HTMLButtonElement, CopyToClipboardProps>(
};
}, [openPopover]);
const title = `Kopier ${label} (${text})`;
const title = `Kopier ${copyText}`;
const handleClick = () => {
copy(text);
copy(copyText);
setOpenPopover(true);
};
@@ -63,17 +68,14 @@ const CopyToClipboard = forwardRef<HTMLButtonElement, CopyToClipboardProps>(
title={title}
className={cl("navds-copy-to-clipboard", className)}
onClick={handleClick}
size={size}
{...rest}
>
{icon ? (
<>{icon}</>
) : (
<Copy
focusable="false"
role="img"
aria-label="Fil ikon for kopiering"
/>
)}
<Copy
focusable="false"
role="img"
aria-label="Fil ikon for kopiering"
/>
{children ? children : <span className="sr-only">{title}</span>}
</Button>
<Popover
@@ -81,11 +83,13 @@ const CopyToClipboard = forwardRef<HTMLButtonElement, CopyToClipboardProps>(
anchorEl={buttonRef.current}
open={openPopover}
onClose={() => setOpenPopover(false)}
placement="right"
placement={popoverPlacement}
arrow={false}
className="navds-copy-to-clipboard__popover"
>
{label}
<BodyShort size={size} as="span">
{popoverText}
</BodyShort>
</Popover>
</div>
);
@@ -1,7 +1,6 @@
import * as React from "react";
import { CopyToClipboard } from "../index";
import { Link } from "@navikt/ds-icons";
export default {
title: "@ds-react/copy-to-clipboard",
@@ -15,24 +14,24 @@ export const All = () => {
return (
<div>
<h2>Fritstående knapp</h2>
<CopyToClipboard label={label} text={text} />
<CopyToClipboard popoverText={label} copyText={text} />
<h2>Sammen med tekst</h2>
<CopyToClipboard label={label} text={text}>
<CopyToClipboard popoverText={label} copyText={text}>
Kopier tekst
</CopyToClipboard>
<h2>Tilpasser seg fontstørrelse</h2>
<CopyToClipboard label={label} text={text} style={{ fontSize: "0.8rem" }}>
<h2>Small size</h2>
<CopyToClipboard popoverText={label} copyText={text} size="small">
Kopier tekst
</CopyToClipboard>
<CopyToClipboard popoverText={label} copyText={text} size="small" />
<h2>Custom icon</h2>
<h2>Endrer placement av popover</h2>
<CopyToClipboard
icon={<Link />}
label={label}
text={text}
style={{ fontSize: "0.8rem" }}
popoverText={label}
copyText={text}
popoverPlacement="bottom-end"
>
Kopier tekst
</CopyToClipboard>
@@ -6,30 +6,40 @@ import { Success } from "@navikt/ds-react";
# 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})`
Innholdet i `copyText` vil bli kopiert til clipboard, mens innholdet i `popoverText`
brukes i popover. Hvis komponenten ikke har noen children (tekst i button) vil da en "sr-only" tekst blie
lagt på knappen med tekst "Kopier copyText"
```jsx
<CopyToClipboard label={"Kopierte PI til clipboard"} text={"3.14"}>
Kopier Pi{" "}
<CopyToClipboard popoverText={"Kopierte adresse"} copyText={"0660 OSLO"}>
Kopier adresse
</CopyToClipboard>
```
<Canvas>
<CopyToClipboard label={"Kopierte PI til clipboard"} text={"3.14"}>
Kopier Pi{" "}
<CopyToClipboard popoverText={"Kopiert adresse"} copyText={"0660 OSLO"}>
Kopier adresse
</CopyToClipboard>
</Canvas>
## Custom ikon
Man kan sette andre ikoner en `Copy` ved `icon`-proppen
## Sizing
```jsx
<CopyToClipboard
icon={<Link />}
label={"Kopierte PI til clipboard"}
text={"3.14"}
/>
popoverText={"Kopierte adressen"}
copyText={"0660 OSLO"}
size="small"
>
Kopier adresse
</CopyToClipboard>
```
<Canvas>
<CopyToClipboard
popoverText={"Kopierte adressen"}
copyText={"0660 OSLO"}
size="small"
>
Kopier adresse
</CopyToClipboard>
</Canvas>
@@ -23,7 +23,7 @@ const ConfirmationPanel = forwardRef<HTMLDivElement, ConfirmationPanelProps>(
<div
ref={ref}
className={cl("navds-confirmation-panel", className, {
"navds-confirmation-panel--s": props.size === "s",
"navds-confirmation-panel--s": props.size === "small",
"navds-confirmation-panel--error": !!props.error,
"navds-confirmation-panel--checked": !!props.checked,
})}
+2 -2
View File
@@ -5,11 +5,11 @@ import { Label } from "..";
const ErrorMessage = (props) => (
<Label
{...props}
component="div"
as="div"
className={cl(
"navds-error-message",
props.className,
`navds-error-message--${props.size ?? "m"}`
`navds-error-message--${props.size ?? "medium"}`
)}
/>
);
@@ -17,7 +17,7 @@ export type FieldsetContextProps = {
/**
* Changes paddings, margins and font-sizes
*/
size: "m" | "s";
size: "medium" | "small";
disabled: boolean;
};
@@ -94,7 +94,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
>
<Label
size={size}
component="legend"
as="legend"
className={cl("navds-fieldset__legend", {
"sr-only": !!hideLegend,
})}
+2 -2
View File
@@ -58,7 +58,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
<Label
htmlFor={inputProps.id}
size={size}
component="label"
as="label"
className={cl("navds-select__label", {
"sr-only": hideLabel,
})}
@@ -85,7 +85,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
className,
"navds-select__input",
"navds-body-short",
`navds-body--${size ?? "m"}`
`navds-body--${size ?? "medium"}`
)}
size={props.htmlSize}
>
+8 -2
View File
@@ -19,6 +19,11 @@ export interface TextFieldProps
* TextField label
*/
label: React.ReactNode;
/**
* Type of form control
* @default "text"
*/
type?: "email" | "number" | "password" | "tel" | "text" | "url";
}
const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
@@ -37,6 +42,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
description,
htmlSize,
hideLabel = false,
type = "text",
...rest
} = props;
@@ -52,7 +58,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
<Label
htmlFor={inputProps.id}
size={size}
component="label"
as="label"
className={cl("navds-text-field__label", { "sr-only": hideLabel })}
>
{label}
@@ -73,7 +79,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
{...omit(rest, ["error", "errorId", "size"])}
{...inputProps}
ref={ref}
type="text"
type={type}
className={cl(
className,
"navds-text-field__input",
+3 -3
View File
@@ -72,7 +72,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
<Label
htmlFor={inputProps.id}
size={size}
component="label"
as="label"
className={cl("navds-textarea__label", {
"sr-only": hideLabel,
})}
@@ -99,7 +99,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
className,
"navds-textarea__input",
"navds-body-short",
`navds-body-${size ?? "m"}`,
`navds-body-${size ?? "medium"}`,
{
"navds-textarea--counter": hasMaxLength,
}
@@ -140,7 +140,7 @@ export const Counter = ({ maxLength, currentLength, size }) => {
className={cl("navds-textarea__counter", {
"navds-textarea__counter--error": difference < 0,
})}
aria-live="polite"
aria-live={difference < 20 ? "polite" : "off"}
size={size}
>
{difference < 0
@@ -0,0 +1,29 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import faker from "faker";
import { Checkbox, CheckboxGroup } from ".";
test("checkbox group chains onChange calls", () => {
const onGroupChange = jest.fn();
const onChange = jest.fn();
const value = faker.datatype.string();
const label = faker.datatype.string();
render(
<CheckboxGroup legend="legend" onChange={onGroupChange}>
<Checkbox onChange={onChange} value={value}>
{label}
</Checkbox>
</CheckboxGroup>
);
userEvent.click(screen.getByLabelText(label));
expect(onGroupChange).toBeCalledTimes(1);
expect(onGroupChange).toBeCalledWith([value]);
expect(onChange).toBeCalledTimes(1);
expect(firstArgumentOfFirstCall(onChange).target.checked).toBe(true);
});
const firstArgumentOfFirstCall = (fn: jest.Mock) => fn.mock.calls[0][0];
@@ -59,7 +59,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
ref={ref}
/>
<BodyShort
component="label"
as="label"
htmlFor={inputProps.id}
size={size}
className="navds-checkbox__label"
@@ -54,7 +54,7 @@ const CheckboxGroup = forwardRef<HTMLFieldSetElement, CheckboxGroupProps>(
className={cl(
className,
"navds-checkbox-group",
`navds-checkbox-group--${rest.size ?? fieldset?.size ?? "m"}`
`navds-checkbox-group--${rest.size ?? fieldset?.size ?? "medium"}`
)}
>
<CheckboxGroupContext.Provider
@@ -95,10 +95,14 @@ Man kan både sette en description på CheckboxGroup og selve checkbox
## Sizing
Checkboxer har default 44px høy klikkflate. Med size="s" blir denne til 24px slik som før
Checkboxer har default 44px høy klikkflate. Med size="small" blir denne til 24px slik som før
```jsx
<CheckboxGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
<Checkbox value="Melon">Melon</Checkbox>
@@ -109,7 +113,7 @@ Checkboxer har default 44px høy klikkflate. Med size="s" blir denne til 24px sl
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
size="small"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange" error="Boksen må være valgt">
@@ -48,7 +48,7 @@ export const All = () => {
<CheckboxGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
size="small"
>
<Checkbox value="Apple">Apple</Checkbox>
<Checkbox value="Orange">Orange</Checkbox>
@@ -1,6 +1,6 @@
import React, { forwardRef, HTMLAttributes } from "react";
import cl from "classnames";
import { Title } from "../..";
import { Heading, BodyShort } from "../..";
export interface ErrorSummaryProps extends HTMLAttributes<HTMLDivElement> {
/**
@@ -9,9 +9,9 @@ export interface ErrorSummaryProps extends HTMLAttributes<HTMLDivElement> {
children: React.ReactNode;
/**
* Changes padding and font-sizes
* @default "m"
* @default "medium"
*/
size?: "m" | "s";
size?: "medium" | "small";
/**
* Heading above links
*/
@@ -25,7 +25,14 @@ export interface ErrorSummaryProps extends HTMLAttributes<HTMLDivElement> {
const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
(
{ children, className, size = "m", headingTag = "h2", heading, ...rest },
{
children,
className,
size = "medium",
headingTag = "h2",
heading,
...rest
},
ref
) => {
return (
@@ -40,24 +47,18 @@ const ErrorSummary = forwardRef<HTMLDivElement, ErrorSummaryProps>(
tabIndex={-1}
role="region"
>
<Title
className="navds-error-summary__title"
component={headingTag}
size="s"
<Heading
className="navds-error-summary__heading"
as={headingTag}
size="small"
>
{heading}
</Title>
<ul
className={cl(
"navds-error-summary__list",
"navds-body-short",
`navds-body--${size}`
)}
>
</Heading>
<BodyShort as="ul" size={size} className="navds-error-summary__list">
{React.Children.map(children, (child) => {
return <li key={child?.toString()}>{child}</li>;
})}
</ul>
</BodyShort>
</div>
);
}
@@ -2,20 +2,20 @@ 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";
export interface ErrorSummaryItemProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
/**
* Link text
*/
children: React.ReactNode;
}
export type ErrorType = OverridableComponent<
ErrorSummaryItemProps,
HTMLAnchorElement
>;
const ErrorSummaryItem: ErrorType = forwardRef(
({ children, component: Component = "a", className, ...rest }, ref) => {
({ children, as: Component = "a", className, ...rest }, ref) => {
return (
<Component
{...rest}
@@ -16,8 +16,8 @@ export const All = () => {
Tekstfeltet må ha en godkjent e-mail
</ErrorSummaryItem>
</ErrorSummary>
<h2>size s</h2>
<ErrorSummary size="s" heading="Feiloppsummering komponent">
<h2>size small</h2>
<ErrorSummary size="small" heading="Feiloppsummering komponent">
<ErrorSummaryItem href="#1">Checkbox må fylles ut</ErrorSummaryItem>
<ErrorSummaryItem href="#2">
Tekstfeltet må ha en godkjent e-mail
+1 -1
View File
@@ -46,7 +46,7 @@ const Radio = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
ref={ref}
/>
<BodyShort
component="label"
as="label"
htmlFor={inputProps.id}
size={size}
className="navds-radio__label"
@@ -67,7 +67,7 @@ const RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(
className={cl(
className,
"navds-radio-group",
`navds-radio-group--${rest.size ?? fieldset?.size ?? "m"}`
`navds-radio-group--${rest.size ?? fieldset?.size ?? "medium"}`
)}
>
<RadioGroupContext.Provider
@@ -95,10 +95,14 @@ Man kan både sette en description på RadioGroup og selve Radio
## Sizing
Radioer har default 44px høy klikkflate. Med size="s" blir denne til 24px slik som før
Radioer har default 44px høy klikkflate. Med size="small" blir denne til 24px slik som før
```jsx
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
<Radio value="Melon">Melon</Radio>
@@ -106,7 +110,11 @@ Radioer har default 44px høy klikkflate. Med size="s" blir denne til 24px slik
```
<Canvas>
<RadioGroup legend="Mollit eiusmod" error="Boks nr 2 må være valgt" size="s">
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="small"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange" error="Boksen må være valgt">
Orange
@@ -45,7 +45,7 @@ export const All = () => {
<RadioGroup
legend="Mollit eiusmod"
error="Boks nr 2 må være valgt"
size="s"
size="small"
>
<Radio value="Apple">Apple</Radio>
<Radio value="Orange">Orange</Radio>
@@ -11,7 +11,7 @@ export interface SearchFieldContextProps {
"aria-describedby"?: string;
disabled?: boolean;
};
size?: "m" | "s";
size?: "medium" | "small";
}
export const SearchFieldContext = React.createContext<SearchFieldContextProps | null>(
@@ -63,7 +63,7 @@ const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
className={cl(
className,
"navds-form-field",
`navds-form-field--${size ?? "m"}`,
`navds-form-field--${size ?? "medium"}`,
"navds-search-field",
{ "navds-search-field--error": hasError }
)}
@@ -71,7 +71,7 @@ const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
<Label
htmlFor={inputProps.id}
size={size}
component="label"
as="label"
className={cl("navds-text-field__label", {
"sr-only": hideLabel,
})}
@@ -11,13 +11,13 @@ export interface SearchFieldButtonProps extends Omit<ButtonProps, "size"> {
children: React.ReactNode;
/**
* Changes design and interactions
* @default "action"
* @default "primary"
*/
variant?: "primary" | "action";
variant?: "primary" | "secondary";
}
const SearchFieldButton = forwardRef<HTMLButtonElement, SearchFieldButtonProps>(
({ className, variant = "action", disabled, ...rest }, ref) => {
({ className, variant = "primary", disabled, ...rest }, ref) => {
const searchField = useContext(SearchFieldContext);
if (searchField === null) {
@@ -11,15 +11,15 @@ export interface SearchFieldClearButtonProps extends Omit<ButtonProps, "size"> {
children: React.ReactNode;
/**
* Changes design and interactions
* @default "primary"
* @default "secondary"
*/
variant?: "primary" | "action";
variant?: "primary" | "secondary";
}
const SearchFieldClearButton = forwardRef<
HTMLButtonElement,
SearchFieldClearButtonProps
>(({ className, variant = "primary", disabled, ...rest }, ref) => {
>(({ className, variant = "secondary", disabled, ...rest }, ref) => {
const searchField = useContext(SearchFieldContext);
if (searchField === null) {
@@ -31,9 +31,9 @@ const SearchFieldClearButton = forwardRef<
return (
<Button
ref={ref}
className={cl(className, "navds-search-field__button")}
{...rest}
ref={ref}
className={cl(className, "navds-search-field__clear-button")}
size={size}
variant={variant}
disabled={disabled ?? inputProps?.disabled}
@@ -20,14 +20,15 @@ const SearchFieldInput = forwardRef<HTMLInputElement, SearchFieldInputProps>(
<input
{...rest}
{...inputProps}
type="search"
role="searchbox"
ref={ref}
type="text"
className={cl(
className,
"navds-search-field__input",
"navds-text-field__input",
"navds-body-short",
`navds-body-${size ?? "m"}`
`navds-body-${size ?? "medium"}`
)}
/>
);
@@ -7,24 +7,23 @@ import {
SearchFieldClearButton,
} from "../index";
export const Example = () => {
export const Example = ({ size = "medium" }: { size: "medium" | "small" }) => {
const [value, setValue] = useState("");
return (
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchField size={size} label="Skriv i søkefeltet for å vise clearbutton">
<SearchFieldInput
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<SearchFieldClearButton onClick={() => setValue("")}>
<Close />
<span>Tøm</span>
</SearchFieldClearButton>
{!!value && (
<SearchFieldClearButton onClick={() => setValue("")}>
<Close />
Tøm
</SearchFieldClearButton>
)}
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
);
@@ -24,7 +24,7 @@ Komponenten er ikke testet eller gått gjennom et design-review, så anbefalses
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
```
@@ -36,7 +36,7 @@ Komponenten er ikke testet eller gått gjennom et design-review, så anbefalses
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
</Canvas>
@@ -54,7 +54,7 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
```
@@ -67,7 +67,7 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
</Canvas>
@@ -79,11 +79,11 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="s"
size="small"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
```
@@ -93,11 +93,11 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
size="s"
size="small"
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
</Canvas>
@@ -113,7 +113,7 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
```
@@ -127,80 +127,35 @@ Vi har satt `label` som required siden man vil bruke den i sammenheng med denne
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
</Canvas>
## Plassering av knapp
## ClearButton
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.
Hvis man bare ønsker at den bare skal vises når bruker har begynt å skrive, anbefaler vi bare å rendre
den når inputvalue ikke er empty.
```jsx
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
hideLabel
>
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
<SearchFieldInput value={value} onChange={(e) => setValue(e.target.value)} />
{!!value && (
<SearchFieldClearButton onClick={() => setValue("")}>
<Close /> Tøm
</SearchFieldClearButton>
)}
<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>
<Search /> Søk
</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>
<Example />
<Example size="small" />
</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>
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import { Meta } from "@storybook/react/types-6-0";
import { Close, Search } from "@navikt/ds-icons";
import {
@@ -14,6 +14,7 @@ export default {
} as Meta;
export const All = () => {
const [show, setShow] = useState(false);
return (
<>
<h1>SearchField</h1>
@@ -23,7 +24,7 @@ export const All = () => {
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
<SearchField
@@ -31,7 +32,7 @@ export const All = () => {
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
@@ -41,9 +42,12 @@ export const All = () => {
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldInput clearSearch />
<SearchFieldButton>
<Search /> <span>Søk</span>
<SearchFieldInput />
<SearchFieldClearButton>
<Close />
</SearchFieldClearButton>
<SearchFieldButton onClick={() => setShow(!show)}>
<Search /> Søk
</SearchFieldButton>
</SearchField>
<SearchField
@@ -51,10 +55,10 @@ export const All = () => {
description="Ea cupidatat eu sunt commodo"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
<SearchFieldClearButton>
<Close /> <span>Tøm</span>
<Close /> Tøm
</SearchFieldClearButton>
<SearchFieldInput />
</SearchField>
@@ -66,7 +70,7 @@ export const All = () => {
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
@@ -75,7 +79,7 @@ export const All = () => {
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="s"
size="small"
>
<SearchFieldButton>
<Search />
@@ -87,7 +91,7 @@ export const All = () => {
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="s"
size="small"
>
<SearchFieldInput />
<SearchFieldButton>
@@ -95,6 +99,35 @@ export const All = () => {
<span className="sr-only">Søk</span>
</SearchFieldButton>
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchFieldButton>
<Search />
<span className="sr-only">Søk</span>
</SearchFieldButton>
<SearchFieldClearButton>
<Close /> Tøm
</SearchFieldClearButton>
<SearchFieldInput />
</SearchField>
<SearchField
label="Mollit eiusmod"
description="Ea cupidatat eu sunt commodo"
size="small"
>
<SearchFieldInput />
<SearchFieldClearButton>
<Close /> Tøm
</SearchFieldClearButton>
<SearchFieldButton>
<Search />
<span className="sr-only">Søk</span>
</SearchFieldButton>
</SearchField>
<h2>SearchField w error</h2>
<SearchField
@@ -104,7 +137,7 @@ export const All = () => {
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
<SearchField
@@ -113,7 +146,7 @@ export const All = () => {
error="Errormsg"
>
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
@@ -128,7 +161,7 @@ export const All = () => {
>
<SearchFieldInput />
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
</SearchField>
<SearchField
@@ -137,7 +170,7 @@ export const All = () => {
hideLabel
>
<SearchFieldButton>
<Search /> <span>Søk</span>
<Search /> Søk
</SearchFieldButton>
<SearchFieldInput />
</SearchField>
@@ -29,7 +29,7 @@ Kommer i størrelsene "m" og "s".
checked={checked}
onChange={() => setChecked(!checked)}
label="Checkbox label text"
size="s"
size="small"
>
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
ut mollit voluptate exercitation nulla mollit.
@@ -37,7 +37,7 @@ Kommer i størrelsene "m" og "s".
```
<Canvas>
<ConfirmationPanelExample size="s" />
<ConfirmationPanelExample size="small" />
</Canvas>
## Errors
@@ -20,12 +20,12 @@ export const All = () => {
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
minim ut mollit voluptate exercitation nulla mollit.
</ConfirmationPanel>
<h2>size s</h2>
<h2>size small</h2>
<ConfirmationPanel
checked={checked}
onChange={() => setChecked(!checked)}
label="Checkbox label text"
size="s"
size="small"
>
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
minim ut mollit voluptate exercitation nulla mollit.
@@ -46,7 +46,7 @@ export const All = () => {
onChange={() => setChecked(!checked)}
label="Checkbox label text"
error="Ex cupidatat do do do"
size="s"
size="small"
>
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
minim ut mollit voluptate exercitation nulla mollit.
Loaded 100 of 208 files, more files were not shown because too many files have changed in this diff. Show more