Compare commits

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

* styles

* flyttet global token til root

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

* add loading prop

* hide content when loading, spinner not centered

* change button loading state with useEffect

* add button component back in

* use a new ref

* add variants for loader buttons

* set loading in state

* add toggle button

* add toggle button

* hide small buttons

* add description for isLoading prop

* move story section to bottom

* destructure imports

* use react-merge-refs

* import useState

* refactor

* refactor

* only set boolean in state

* remove width style when loader removed

* fix slight movement due to rounding width

* adjust loader size to button

* fix button width logic

* useLayoutEffect instead of useEffect for button with handling

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

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

* loading button in story toggles loading

* remove aria-live prop

* rename isLoading to be consistent with Switch

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

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

* move button specific loader style

* stories

* aria-live is back

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

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

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

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

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

* satt opp stepindicator med step

* oppdatert stepindicator api

* påbegynt styling av step-indicator

* lint fix

* oppdatert step-indicator

* refactored css completely

* fikset text-decoration for hover state

* fjernet autoresponsive prop

* mdx story for step-indicator

* implemenetert autoResponsive

* renamet autoRepsonsive -> responsive

* fikset responsive dok

* interaktivt step-indicator story

* flyttet tokens opp til root i css

* syntax fix

* router story and onChange optional

* oopsie

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

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

* [FEATURE] Fix icon names (#1375)

* [ci skip] update readme

* bedre disabled handling, mindre number med samme klikkflate

Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
Co-authored-by: bdahle <bdahle@hey.com>
2022-01-07 11:48:33 +01:00
github-actions[bot] b74f5d6184 Lerna versionbump [ci skip]
- @navikt/ds-css@0.12.7
 - @navikt/ds-icons@0.7.2
 - @navikt/ds-react@0.14.4
 - @navikt/ds-tokens@0.7.1
 - @navikt/ds-react-internal@0.9.4
2022-01-07 08:53:21 +00:00
Andreas Nordahl 0386752686 [fix] small select padding-right bug (#1377) 2022-01-07 09:45:56 +01:00
Ken 0a3fe8a1d9 [ci skip] update readme 2022-01-03 09:36:00 +01:00
Andreas Nordahl 855c2eac9e [FEATURE] Fix icon names (#1375) 2022-01-03 09:34:45 +01:00
KenandAndreas Nordahl ed90d205b6 Opprydding i Repo, flytting av gammel kode til nytt repo (#1372)
Co-authored-by: Andreas Nordahl <andnorda@gmail.com>
2022-01-03 09:33:38 +01:00
Andreas Nordahl d1bd479cf3 check for isChromatic to render icon stories (#1374) 2021-12-30 10:33:44 +01:00
723 changed files with 4407 additions and 52761 deletions

No files matched your search

+1 -59
View File
@@ -1,7 +1,7 @@
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
name: Build, test and maybe publish
name: Build -> Test -> Publish
on:
push:
@@ -39,12 +39,6 @@ jobs:
run: yarn lint
- name: Test
run: yarn test
- name: add access token to .env
run: echo "ACCESS_TOKEN=${{ secrets.VERKTOYKASSE_INNHOLD_TOKEN }}" >> website/.env
- name: add branch token to .env
run: echo "BRANCH=HEAD" >> website/.env
- name: Test gatsby-build (design.nav.no)
run: yarn build:gatsby
publish-npm:
needs: test-build
@@ -100,56 +94,4 @@ jobs:
AUTH_TOKEN: ${{secrets.GIT_REPO}}
- name: Publish to Github registry
run: |
rm lerna.json && cp utilities/lerna.json lerna.json
git add . && git commit -m "tmp"
yarn lerna publish --registry https://npm.pkg.github.com from-package --yes
publish-pages:
needs: test-build
runs-on: ubuntu-latest
if: github.event_name == 'push'
steps:
- uses: actions/checkout@v2
with:
fetch-depth: "0"
token: ${{secrets.GIT_REPO}}
- uses: actions/setup-node@v1
with:
node-version: 14
- name: Node-modules cache
uses: actions/cache@v2
id: node-cache
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: Install deps
if: steps.node-cache.outputs.cache-hit != 'true'
run: yarn install
- name: Gulp-build
run: yarn boot
- name: add access token to .env
run: echo "ACCESS_TOKEN=${{ secrets.VERKTOYKASSE_INNHOLD_TOKEN }}" >> website/.env
- name: add branch token to .env
run: echo "BRANCH=HEAD" >> website/.env
- name: Building Gatsby
run: yarn build:gatsby
- name: Building Storybook
run: yarn build-storybook
- name: Deploy to Design.nav.no 🚀
uses: JamesIves/github-pages-deploy-action@3.6.2
with:
GITHUB_TOKEN: $NAV_DS_TOKEN
BRANCH: gh-pages
FOLDER: website/public
env:
NAV_DS_TOKEN: ${{secrets.GIT_REPO}}
- name: Deploy storybook to designsystem-repo
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{secrets.GIT_REPO}}
external_repository: navikt/designsystemet
publish_dir: ./storybook-static
user_name: "github-actions[bot]"
user_email: "github-actions[bot]@users.noreply.github.com"
-39
View File
@@ -1,39 +0,0 @@
# This workflow will run will build the component library and the storybook, then publish it to https://navikt.github.io/Designsystemet
name: Publish Storybook
on:
workflow_dispatch
jobs:
publish-storybook:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: "0"
token: ${{secrets.GIT_REPO}}
- uses: actions/setup-node@v1
with:
node-version: 14
- name: Node-modules cache
uses: actions/cache@v2
id: node-cache
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: Install deps
if: steps.node-cache.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile
- name: Gulp-build
run: yarn boot
- name: Building Storybook
run: yarn build-storybook
- name: Deploy storybook
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{secrets.GIT_REPO}}
external_repository: navikt/designsystemet
publish_dir: ./storybook-static
user_name: "github-actions[bot]"
user_email: "github-actions[bot]@users.noreply.github.com"
-47
View File
@@ -1,47 +0,0 @@
name: Publish verktøykasse-innhold to dev
on:
push:
branches: verktoykasse-prototype
repository_dispatch:
types: [new-content]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: verktoykasse-prototype
fetch-depth: 0 # Required to retrieve git history
- uses: actions/setup-node@v1
with:
node-version: 14
- name: Node-modules cache
uses: actions/cache@v2
id: node-cache
with:
path: "**/node_modules"
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
- name: Install deps
if: steps.node-cache.outputs.cache-hit != 'true'
run: yarn install
- name: Gulp-build
run: yarn boot
- name: Eslint and Stylelint
run: yarn lint
- name: add access token to .env
run: echo "ACCESS_TOKEN=${{ secrets.VERKTOYKASSE_INNHOLD_TOKEN }}" >> website/.env
- name: add branch token to .env
run: echo "BRANCH=dev" >> website/.env
- name: Gatsby-build
run: yarn build:gatsby
- name: Deploy to dev gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{secrets.GIT_REPO}}
external_repository: navikt/verktoykasse-innhold
publish_dir: website/public
user_name: "github-actions[bot]"
user_email: "github-actions[bot]@users.noreply.github.com"
+10 -5
View File
@@ -1,14 +1,16 @@
const getStories = () => {
return process.env.stories
? [`../@navikt/**/${process.env.stories}.stories.@(js|jsx|ts|tsx|mdx)`]
: ["../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)"];
};
module.exports = {
webpackFinal: async (config, { configType }) => {
config.devServer = { stats: "errors-only" };
return config;
},
devServer: { stats: "errors-only" },
stories: [
"../.storybook/**/*.stories.@(mdx)",
"../packages/**/*.stories.@(js|jsx|ts|tsx|mdx)",
"../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)",
],
stories: () => getStories(),
addons: [
"@storybook/addon-docs",
"@storybook/addon-a11y",
@@ -28,4 +30,7 @@ module.exports = {
},
},
],
core: {
builder: "webpack5",
},
};
-1
View File
@@ -1,4 +1,3 @@
import "nav-frontend-core";
import "@navikt/ds-css/index.css";
import "@navikt/ds-css-internal/index.css";
@@ -1,35 +0,0 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-react/Kom i gang" />
# Ta i bruk `@navikt/ds-react` pakken
## Oppsett
```bash
yarn add @navikt/ds-react @navikt/ds-css
```
Siden stilene ikke importeres direkte i komponentene, så må man selv importere ds-css.
For å legge til all stylingen som trengs må man da bare importere `ds-css`.
```bash
import "@navikt/ds-css"
```
Dette vil også legge css-variabler på :root. For å få dette til å fungere med IE11, kan denne pakken tas i bruk: https://jhildenbiddle.github.io/css-vars-ponyfill/#/
Note: Disse komponentene kan ikke garanteres at fungerer som forventet i IE11 da vi har valgt og ikke unngå styling-valg basert på IE11 støtte eller ikke.
## Bruke styled-components eller emotion
Flere av våre komponenter er implementert med OverridableComponent. Dette vil si at komponenten tar i mot en prop, `as` som lar deg endre hvilken tag som blir satt.
Bruk for dette er eks hvis du ønsker `Heading` stilen, men ikke en heading-tag. Da kan man lett skrive `<Heading as="div">` og man vil få en `div`-tag istedenfor.
Flere css-in-js bibliotek har også denne funksjonaliteten bygd inne, noe som kan komplisere ting når alle bruker samme navn `as` for dette.
### Løsninger
[Styled-components](https://styled-components.com/docs/api#forwardedas-prop)
> TLDR: Bruk `forwardedAs` istendenfor `as` på komponentene, SD fikser resten.
-263
View File
@@ -1,263 +0,0 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-react/Migration" />
# Migreringsguider
## Migrering til ds-css v0.12, ds-tokens v0.7
### Tokens er refaktort og oppdatert
- Vi har nå fått helt nye tokens synket fra 3.0 biblioteket i Figma.
- Dette vi si at de som har brukt tokens for styling i sitt prosjekt må gå gjennom å fikse alle endringene.
- Hvis du bare har brukt react-komponentene rett ut av boken så har denne endringene ikke noe å si for deg.
## Migrering til ds-react v0.11, ds-css v0.10
### ErrorSummary
- ErrorSummaryItem -> ErrorSummary.Item
Må da slette import "ErrorSummaryItem" da denne ikke er eksponert alene lengre
### SearchField
- SearchFieldButton -> SearchField.Button
- SearchFieldClearButton -> SearchField.Clear
- SearchFieldInput -> SearchField.Input
SearchFieldButton, SearchFieldClearButton og SearchFieldInput må da slettes fra imports da de ikke er eksponert lengre.
### CopyToClipBoard
Komponenten er flyttet til pakkene "@navikt/ds-react-internal" og "@navikt/ds-css-internal". API er ikke endret
så fikses med
```bash
yarn install @navikt/ds-react-internal @navikt/ds-css-internal
```
## 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.
-269
View File
@@ -1,269 +0,0 @@
import { Table as DsTable } from "@navikt/ds-react";
import {
SuccessFilled as SuccessIcon,
ErrorFilled as ErrorIcon,
} from "@navikt/ds-icons";
import styled from "styled-components";
const Success = styled(SuccessIcon)`
color: var(--navds-semantic-color-feedback-success-icon);
`;
const Error = styled(ErrorIcon)`
color: var(--navds-semantic-color-feedback-danger-icon);
`;
const Table = styled(DsTable)`
.navds-table__cell > svg,
.navds-table__cell > span {
vertical-align: middle;
margin-left: 50%;
transform: translateX(-50%);
}
`;
type CompT = {
name: string;
status: Partial<[boolean, boolean, boolean]>;
desc?: React.ReactNode;
};
const Components: CompT[] = [
{
name: "Alertstriper",
status: [true, true, true],
desc: "Navn: Alert",
},
{ name: "Chevron", status: [false], desc: "" },
{
name: "Core",
status: [true, true, false],
desc: <code>@navikt/ds-css</code>,
},
{
name: "Ekspanderbartpanel",
status: [true, true, true],
desc: "Navn: Accordion, styling ikke oppdatert til nyeste versjon",
},
{ name: "Etiketter", status: [true, true, false], desc: "Navn: Tag" },
{
name: "Fullbreddeknapp-style",
status: [false],
desc: "",
},
{ name: "Grid", status: [true, true, false], desc: "Navn: Grid" },
{ name: "Hjelpetekst", status: [true, true, true], desc: "Navn: HelpText" },
{
name: "Ikoner-assets",
status: [true, true, true],
desc: <code>@navikt/ds-icons</code>,
},
{
name: "js-utils",
status: [true, true, false],
desc:
"Diverse util-funksjoner blir eksponert gjennom ds-react, men tar for det meste i bruk npm pakker",
},
{ name: "Knapper", status: [true, true, true], desc: "Navn: Button" },
{ name: "Lenkepanel", status: [true, true, true], desc: "Navn: LinkPanel" },
{ name: "Lenker", status: [true, true, true], desc: "Navn: Link" },
{ name: "Lesmerpanel", status: [false], desc: "" },
{ name: "Lukknapp", status: [false], desc: `Bruk Button med "Close"-ikon` },
{ name: "Modal", status: [true, true, true], desc: "Navn: Modal" },
{ name: "Paneler", status: [true, true, true], desc: "Navn: Panel" },
{
name: "Bekrefcheckbokspanel",
status: [true, true, true],
desc: "Navn: ConfirmationPanel",
},
{
name: "Checkbokspanel-gruppe",
status: [false],
desc: "Panel-versjon vil ikke tas videre i nytt system",
},
{
name: "Checkbokspanel",
status: [false],
desc: "Panel-versjon vil ikke tas videre i nytt system",
},
{
name: "Checkbox-gruppe",
status: [true, true, true],
desc: "Navn: CheckboxGroup",
},
{ name: "Checkbox", status: [true, true, true], desc: "Navn: Checkbox" },
{
name: "Feiloppsummering",
status: [true, true, false],
desc: "Navn: ErrorSummary, API vil bli endret for denne",
},
{
name: "Fnr-input",
status: [false],
desc:
"Skjema-elementer med validering vil ikke bli lagt til med det første, men vil diskuteres i fremtiden",
},
{ name: "Input", status: [true, true, true], desc: "Navn: TextField" },
{
name: "Label",
status: [false],
desc: "Skjema-elementer fikser dette selv",
},
{ name: "Radio-Gruppe", status: [true, true, true], desc: "RadioGroup" },
{ name: "Radio", status: [true, true, true], desc: "Navn: Radio" },
{
name: "Radiopanel-gruppe",
status: [false],
desc: "Panel-versjon vil ikke tas videre i nytt system",
},
{
name: "Radio-panel",
status: [false],
desc: "Panel-versjon vil ikke tas videre i nytt system",
},
{ name: "Select", status: [true, true, true], desc: "Navn: Select" },
{ name: "Skjema-gruppe", status: [true, true, true], desc: "Navn: Fieldset" },
{
name: "Skjemaelement-feilemelding",
status: [false],
desc: "",
},
{ name: "Textarea", status: [true, true, true], desc: "Navn: Textarea" },
{ name: "Togglegruppe", status: [true, false, false], desc: "" },
{ name: "ToggleKnapp", status: [true, false, false], desc: "" },
{
name: "Toggle",
status: [true, false, false],
desc: "Vil bli samme komponent som ToggleKnapp",
},
{ name: "Popover", status: [true, true, true], desc: "Navn: Popover" },
{ name: "Snakkeboble", status: [true, true, true], desc: "SpeechBubble" },
{ name: "Spinner", status: [true, true, true], desc: "Navn: Loader" },
{ name: "Stegindikator", status: [true, false, false], desc: "" },
{
name: "Tabell-style",
status: [true, true, false],
desc: "Navn: Table, Er nå publisert som React-component",
},
{ name: "Tabs", status: [true, false, false], desc: "" },
{ name: "Tekstomrade", status: [false], desc: "" },
{
name: "Typografi",
status: [true, true, true],
desc: "Navn: se typography-mappen i storybook",
},
{ name: "veileder", status: [false], desc: "" },
{
name: "Veilederpanel",
status: [true, true, true],
desc: "Navn: GuidePanel",
},
];
const NewComps: CompT[] = [
{
name: "AccordionMenu",
status: [true, true, true],
desc: "",
},
{
name: "SearcField",
status: [true, true, false],
desc: "Denne vil undergå større endringer",
},
{
name: "MicroCard",
status: [true, true, false],
desc: "Vil flyttes over i egen navno pakke for eksterne sider",
},
{
name: "PageHeader",
status: [true, true, false],
desc: "Vil flyttes over i egen navno pakke for eksterne sider",
},
{
name: "CopyToClipboard",
status: [true, true, false],
desc: "Vil flyttes over til @navikt/ds-react-internal pakke",
},
{
name: "Table",
status: [true, true, false],
desc:
"Implementer stylingen til nav-frontend-table-styles, API vil videreutvikles",
},
{
name: "Switch",
status: [true, false, false],
desc: "",
},
{
name: "Tooltip",
status: [true, false, false],
desc: "",
},
{
name: "Timeline",
status: [true, false, false],
desc: "",
},
];
const CompTable = ({ list }) => (
<Table>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Komponent</Table.HeaderCell>
<Table.HeaderCell>Med i nytt system</Table.HeaderCell>
<Table.HeaderCell>Publisert i pakker</Table.HeaderCell>
<Table.HeaderCell>Fullført**</Table.HeaderCell>
<Table.HeaderCell>Info</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{list.map((comp) => {
return (
<Table.Row>
<Table.HeaderCell>{comp.name}</Table.HeaderCell>
<Table.DataCell>
{comp.status?.[0] === undefined ? (
<span>-</span>
) : comp.status?.[0] ? (
<Success />
) : (
<Error />
)}
</Table.DataCell>
<Table.DataCell>
{comp.status?.[1] === undefined ? (
<span>-</span>
) : comp.status?.[1] ? (
<Success />
) : (
<Error />
)}
</Table.DataCell>
<Table.DataCell>
{comp.status?.[2] === undefined ? (
<span>-</span>
) : comp.status?.[1] ? (
<Success />
) : (
<Error />
)}
</Table.DataCell>
<Table.DataCell>{comp.desc ? comp.desc : "-"}</Table.DataCell>
</Table.Row>
);
})}
</Table.Body>
</Table>
);
export const NewCompTable = () => {
return <CompTable list={NewComps} />;
};
export const OldCompTable = () => {
return <CompTable list={Components} />;
};
-64
View File
@@ -1,64 +0,0 @@
import { Meta } from "@storybook/addon-docs";
import { NewCompTable, OldCompTable } from "./roadmap-table.tsx";
<Meta title="ds-react/Roadmap" />
# Roadmap
## Komponenter
\*\* Fullført betyr i denne konteksten at vi føler API-et er ok og da kan forvente mindre breaking changes.
Komponenten kan fortsatt bli utsatt for endringer i selve designet.
### Nye komponenter / wip
<NewCompTable />
### Migrering av gamle komponenter
<OldCompTable />
## Plan videre
Vi jobber kontinuerlig med å finne bedre løsninger for å kunne bygge systemet opp fra bunnen av. Dette innegår da
ny dokumentasjon-side under Verktøykassen, nye byggeblokker helt fra token-nivå og bedre sizing for eksterne/interne sider.
Dette vil la oss bygge mer robuste og fleksible løsninger for fremtiden som skal være bedre tilpasset produktene våre.
(Rekkefølgen representer ikke faktisk tidslinje)
## Tokens
Vi bygger opp `@navikt/ds-tokens` pakken som inneholder alle design-tokensene til designsystemet fra bunnen av.
Dette vil gjøre styling og overriding av komponenter enklere da man kan bruke css-variabler.
## Intern / Ekstern sizing
Komponenter tilpasses og standariseres bedre for skillet mellom interne/eksterne flater.
Eksempel på dette er `size="small" -> 32px, size="medium"-> 48px`.
## Ny dokumentasjon-side
Vi bygger en ny side for å dokumentere systemet, og mer rundt utvikling/design i NAV med "Verktøykassen"
## Migrere komponenter/styling fra nav-frontend-\* -> `@navikt/ds-css / @navikt/ds-react`
Dette arbeidet kommer sakte men sikkert på plass, men tar litt tid da mye må på plass først, da eksempelvis sizing og tokens.
Noen komponenter vil ha oppdatert funksjonalitet, noen bare stilendringer, mens noen kan nesten brukes 1-1 fra nav-frontend-.
Note: Noen pakker vil ikke flyttes over fra nav-frontend og `deprecates` i praksis da. De pakkene som ikka tas over vil ikke bli deprecated på `npm`, slik at man kan fortsette å ta dem i bruk uten en sint terminal hver gang man kjører `yarn install`.
## Theming
Etterhvert når vi har nye react, css og token pakke på plass har vi et ønske om å kunne se på theming for
eks darkmode.
## Vue, svelte, web-components etc...
Dette er noe vi ikke har på planene for tiden, men etterhvert som ting faller på plass så vil dette være
noe vi kunne ta en titt på hvis vi ser at det trengs.
## Versjonering
De nye pakkene under `@navikt`, da `ds-css` og `ds-react` er nå versjonert under to store pakker med alle komponentene. I fremtiden vil vi se på å
ha både samversjonering (alle pakker under en eks ds-react versjon) og induvduell verjsonering da eks ds-react/button har en egen versjon
slik at man kan ha mer finkontroll over komponentbruk på siden sin.
+7 -14
View File
@@ -1,20 +1,13 @@
const path = require("path");
module.exports = (baseConfig) => {
baseConfig.config.module.rules.push(
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
include: [
path.resolve(__dirname, "../node_modules/@navikt/core/css/index.css"),
],
},
{
test: /\.less$/,
loaders: ["style-loader", "css-loader", "less-loader"],
include: path.resolve(__dirname, "../packages/"),
}
);
baseConfig.config.module.rules.push({
test: /\.css$/,
use: ["style-loader", "css-loader"],
include: [
path.resolve(__dirname, "../node_modules/@navikt/core/css/index.css"),
],
});
baseConfig.config.resolve.alias = {
...baseConfig.config.resolve.alias,
"./normalize.css": path.resolve(
-105
View File
@@ -1,105 +0,0 @@
:root {
--navds-accordion-menu-color-text: var(--navds-semantic-color-link);
--navds-accordion-menu-color-text-focus: var(--navds-semantic-color-text);
--navds-accordion-menu-color-background-hover: var(
--navds-global-color-blue-50
);
--navds-accordion-menu-color-text-active: var(--navds-semantic-color-text);
--navds-accordion-menu-outline-focus: var(--navds-semantic-color-focus);
}
.navds-accordion-menu__list {
list-style: none;
margin: 0;
padding: 0;
font-weight: var(--navds-font-weight-bold);
}
.navds-accordion-menu-collapsable__button {
cursor: pointer;
background-color: transparent;
border: none;
font: inherit;
text-align: inherit;
margin: 0;
padding: 0;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: var(--navds-font-weight-bold);
color: var(--navds-accordion-menu-color-text);
text-decoration: underline;
}
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable__button {
display: flex;
padding: var(--navds-spacing-3) var(--navds-spacing-4);
text-decoration: none;
}
.navds-accordion-menu-collapsable__expand-icon {
font-size: 1.5rem;
color: var(--navds-accordion-menu-color);
flex-shrink: 0;
margin-left: var(--navds-spacing-2);
}
.navds-accordion-menu-collapsable--open
> .navds-accordion-menu-collapsable__button
> .navds-accordion-menu-collapsable__expand-icon {
transform: rotate(180deg);
}
.navds-accordion-menu-collapsable .navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-8);
}
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-12);
}
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-item,
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable
.navds-accordion-menu-collapsable__button {
padding-left: var(--navds-spacing-16);
}
.navds-accordion-menu-item:focus,
.navds-accordion-menu-collapsable__button:focus {
outline: 3px solid var(--navds-accordion-menu-outline-focus);
outline-offset: -3px;
color: var(--navds-accordion-menu-color-text-focus);
}
.navds-accordion-menu-collapsable__button:focus
> .navds-accordion-menu-collapsable__expand-icon {
color: var(--navds-accordion-menu-color-focus);
}
.navds-accordion-menu-item:hover,
.navds-accordion-menu-collapsable__button:hover {
background-color: var(--navds-accordion-menu-color-background-hover);
}
.navds-accordion-menu-item--active {
box-shadow: inset 0.5rem 0 var(--navds-semantic-color-link);
color: var(--navds-accordion-menu-color-text-active);
text-decoration: none;
}
+46 -24
View File
@@ -4,11 +4,16 @@
---navds-semantic-color-component-background-light
);
--navds-accordion-color-text-hover: var(--navds-semantic-color-link);
--navds-accordion-color-border: var(--navds-semantic-color-border-muted);
--navds-accordion-color-border-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-accordion-color-border-focus: var(
---navds-semantic-color-component-background-light
--navds-accordion-color-text-open: var(--navds-semantic-color-text);
--navds-accordion-color-text-open-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-accordion-color-background-open: var(
--navds-semantic-color-interaction-primary-hover-subtle
);
}
@@ -20,16 +25,53 @@
background: var(--navds-accordion-color-background);
}
.navds-accordion__header {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--navds-spacing-4);
padding: var(--navds-spacing-4) var(--navds-spacing-3);
margin: 0;
text-align: left;
background: transparent;
cursor: pointer;
border: none;
border-bottom: 2px solid var(--navds-accordion-color-border);
}
.navds-accordion__header:focus {
outline: none;
box-shadow: var(--navds-shadow-focus);
border-color: var(--navds-accordion-color-border-focus);
}
.navds-accordion__header:hover {
color: var(--navds-accordion-color-text-hover);
border-color: var(--navds-accordion-color-border-hover);
text-decoration: underline;
}
.navds-accordion__item--open > .navds-accordion__header {
background-color: var(--navds-accordion-color-background-open);
color: var(--navds-accordion-color-text-open);
border-color: transparent;
}
.navds-accordion__item--open > .navds-accordion__header:hover {
border-color: transparent;
color: var(--navds-accordion-color-text-open-hover);
}
.navds-accordion__content {
color: var(--navds-accordion-color-text);
padding: var(--navds-spacing-5) var(--navds-spacing-3) var(--navds-spacing-10);
border-bottom: 2px solid var(--navds-accordion-color-border);
}
.navds-accordion__item--open
> .navds-accordion__header:hover
+ *
.navds-accordion__content {
border-color: var(--navds-accordion-color-border-hover);
}
.navds-accordion__expand-icon {
@@ -42,26 +84,6 @@
transform: rotateZ(180deg);
}
.navds-accordion__header {
padding: var(--navds-spacing-4) var(--navds-spacing-3);
background: transparent;
text-align: left;
border: none;
width: 100%;
margin: 0;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid #a0a0a0;
gap: var(--navds-spacing-4);
}
.navds-accordion__content {
color: var(--navds-accordion-color-text);
padding: var(--navds-spacing-5) var(--navds-spacing-3) var(--navds-spacing-10);
}
.navds-accordion__expand-icon--filled {
display: none;
}
+17 -2
View File
@@ -74,6 +74,10 @@
--navds-button-color-danger-border-focus: var(
--navds-semantic-color-component-background-light
);
/* Loader */
--navds-loader-color-on-button-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-on-button-foreground: currentColor;
}
.navds-button {
@@ -255,7 +259,18 @@
**************************/
.navds-button:disabled {
opacity: 0.3;
cursor: not-allowed;
transform: none;
}
.navds-button:disabled:not(.navds-button--loading) {
opacity: 0.3;
}
.navds-button .navds-loader .navds-loader__foreground {
stroke: var(--navds-loader-color-on-button-foreground);
}
.navds-button--primary .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
+1 -1
View File
@@ -14,7 +14,7 @@
}
/* Applied when hideLegend is applied to fieldset */
.navds-fieldset > .sr-only + :not(:first-child):not(:empty) {
.navds-fieldset > .navds-sr-only + :not(:first-child):not(:empty) {
margin-top: 0;
}
+2 -2
View File
@@ -4,7 +4,7 @@
}
/* Applied when hideLabel is applied to form-element */
.navds-form-field > .sr-only + :not(:first-child):not(:empty),
.navds-form-field > .sr-only + input:not(:first-child) {
.navds-form-field > .navds-sr-only + :not(:first-child):not(:empty),
.navds-form-field > .navds-sr-only + input:not(:first-child) {
margin-top: 0;
}
+31 -8
View File
@@ -1,6 +1,6 @@
:root {
--navds-radio-checkbox-color-background: var(
--navds-semantic-color-canvas-background-light
--navds-semantic-color-component-background-light
);
--navds-radio-checkbox-color-background-hover: var(
--navds-semantic-color-interaction-primary-hover-subtle
@@ -107,6 +107,29 @@
var(--navds-shadow-focus);
}
.navds-checkbox__input:indeterminate + .navds-checkbox__label::before {
box-shadow: none;
background-color: var(--navds-radio-checkbox-color-background-checked);
}
.navds-checkbox__input:indeterminate + .navds-checkbox__label::after {
content: "";
position: absolute;
top: 50%;
transform: translate(0.375rem, -50%);
background-color: var(--navds-radio-checkbox-color-background);
width: 0.75rem;
height: 0.25rem;
border-radius: 1px;
flex-shrink: 0;
}
.navds-checkbox--small
.navds-checkbox__input:indeterminate
+ .navds-checkbox__label::after {
transform: translate(0.25rem, -50%);
}
.navds-checkbox__input:checked + .navds-checkbox__label::before {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMyAxMCI+ICAgIDxnPiAgICA8cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNCwxMGMtMC40LDAtMC44LTAuMS0xLjEtMC40TDAuNCw3LjFDMC4xLDYuOCwwLDYuNCwwLDZzMC4yLTAuOCwwLjUtMS4xQzEsNC40LDIsNC40LDIuNSw0LjlMNCw2LjRsNi40LTYgICAgQzEwLjgsMC4xLDExLjEsMCwxMS41LDBjMC40LDAsMC44LDAuMiwxLDAuNWMwLjYsMC42LDAuNSwxLjYtMC4xLDIuMXYwTDUsOS42QzQuNyw5LjksNC40LDEwLDQsMTB6IE0xMS44LDEuOUwxMS44LDEuOSAgICBDMTEuOCwxLjksMTEuOCwxLjksMTEuOCwxLjl6IE0xMS4yLDEuMUMxMS4yLDEuMSwxMS4yLDEuMSwxMS4yLDEuMUwxMS4yLDEuMXoiLz4gICAgPC9nPjwvc3ZnPg==);
background-position: 6px center;
@@ -121,7 +144,7 @@
+ .navds-checkbox__label::before {
background-position: 4px center;
}
.navds-checkbox__input:indeterminate:focus + .navds-checkbox__label::before,
.navds-checkbox__input:checked:focus + .navds-checkbox__label::before {
box-shadow: inset 0 0 0 1px white, var(--navds-shadow-focus);
}
@@ -142,28 +165,28 @@
color: var(--navds-radio-checkbox-color-label-hover);
}
.navds-checkbox__input:hover:not(:disabled):not(:checked):not(:focus)
.navds-checkbox__input:hover:not(:disabled):not(:checked):not(:indeterminate):not(:focus)
+ .navds-checkbox__label::before,
.navds-radio__input:hover:not(:disabled):not(:checked):not(:focus)
.navds-radio__input:hover:not(:disabled):not(:checked):not(:indeterminate):not(:focus)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-hover);
background-color: var(--navds-radio-checkbox-color-background-hover);
}
.navds-checkbox--error
> .navds-checkbox__input:not(:hover):not(:disabled):not(:checked)
> .navds-checkbox__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:not(:hover):not(:disabled):not(:checked)
> .navds-radio__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-error);
}
.navds-checkbox--error
> .navds-checkbox__input:focus:not(:hover):not(:disabled):not(:checked)
> .navds-checkbox__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked)
> .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--navds-radio-checkbox-color-shadow-error),
var(--navds-shadow-focus);
+2 -1
View File
@@ -21,7 +21,6 @@
.navds-select__input {
appearance: none;
padding: 0.5rem;
background-color: var(--navds-select-color-background);
border-radius: 4px;
border: 1px solid var(--navds-select-color-border);
@@ -30,6 +29,7 @@
min-height: 48px;
display: inline-block;
position: relative;
padding: 0.5rem;
padding-right: 2.5rem;
}
@@ -59,6 +59,7 @@
.navds-form-field--small .navds-select__input {
min-height: 32px;
padding: 0.25rem;
padding-right: 2rem;
}
/**
+52 -15
View File
@@ -1,14 +1,17 @@
:root {
--navds-switch-color-label: var(--navds-color-text-primary);
--navds-switch-color-label: var(--navds-semantic-color-text);
--navds-switch-color-label-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-switch-color-track-background: var(--navds-semantic-color-text-muted);
--navds-switch-color-track-background-checked: var(
--navds-semantic-color-interaction-primary
--navds-semantic-color-feedback-success-border
);
--navds-switch-color-track-background-hover: var(
--navds-global-color-gray-800
);
--navds-switch-color-track-background-hover-checked: var(
--navds-semantic-color-interaction-primary-hover
--navds-semantic-color-feedback-success-icon
);
--navds-switch-color-track-shadow-inner-focus: var(
--navds-semantic-color-component-background-light
@@ -16,8 +19,12 @@
--navds-switch-color-thumb: var(
--navds-semantic-color-component-background-light
);
--navds-switch-color-thumb-icon: var(--navds-semantic-color-text-muted);
--navds-switch-color-thumb-icon-checked: var(
--navds-semantic-color-feedback-success-border
);
--navds-switch-color-thumb-loader-checked: var(
--navds-semantic-color-interaction-primary
--navds-semantic-color-feedback-success-border
);
}
@@ -27,6 +34,10 @@
width: fit-content;
}
.navds-switch--right {
width: auto;
}
.navds-switch--small {
position: relative;
min-height: 32px;
@@ -61,11 +72,22 @@
padding: 0.75rem 0 0.75rem 3.25rem;
}
.navds-switch--right > .navds-switch__label-wrapper > .navds-switch__content {
padding: 0.75rem 3.25rem 0.75rem 0;
}
.navds-switch--small > .navds-switch__label-wrapper > .navds-switch__content {
padding: calc(var(--navds-spacing-2) - 2px) 0
calc(var(--navds-spacing-2) - 2px) 3.25rem;
}
.navds-switch--right.navds-switch--small
> .navds-switch__label-wrapper
> .navds-switch__content {
padding: calc(var(--navds-spacing-2) - 2px) 3.25rem
calc(var(--navds-spacing-2) - 2px) 0;
}
.navds-switch--with-description,
.navds-switch--small
> .navds-switch__label-wrapper
@@ -73,7 +95,8 @@
padding-bottom: 0;
}
.navds-switch__input:hover ~ .navds-switch__label-wrapper {
.navds-switch__input:hover ~ .navds-switch__label-wrapper,
.navds-switch__label-wrapper:hover {
color: var(--navds-switch-color-label-hover);
}
@@ -89,7 +112,7 @@
position: absolute;
top: var(--navds-spacing-3);
left: 0;
border-radius: var(--navds-spacing-4);
border-radius: 4px;
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -97,10 +120,20 @@
top: var(--navds-spacing-1);
}
.navds-switch--right > .navds-switch__input,
.navds-switch--right > .navds-switch__track {
right: 0;
left: auto;
}
.navds-switch__input:checked ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-checked);
}
.navds-switch__input:hover ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-hover);
}
.navds-switch__input:hover:checked ~ .navds-switch__track {
background-color: var(--navds-switch-color-track-background-hover-checked);
}
@@ -121,7 +154,8 @@
/* Thumb */
.navds-switch__thumb {
background-color: var(--navds-switch-color-thumb);
border-radius: 50%;
color: var(--navds-switch-color-thumb-icon);
border-radius: 2.5px;
width: 20px;
height: 20px;
position: absolute;
@@ -136,16 +170,19 @@
.navds-switch__input:checked ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(20px);
color: var(--navds-switch-color-thumb-icon-checked);
}
.navds-switch__input:hover ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(2px);
}
@media (hover: hover) and (pointer: fine) {
.navds-switch__input:hover ~ .navds-switch__track > .navds-switch__thumb {
transform: translateX(2px);
}
.navds-switch__input:checked:hover
~ .navds-switch__track
> .navds-switch__thumb {
transform: translateX(18px);
.navds-switch__input:checked:hover
~ .navds-switch__track
> .navds-switch__thumb {
transform: translateX(18px);
}
}
.navds-switch__input:disabled:hover
@@ -173,7 +210,7 @@
appearance: none;
}
.navds-switch--disabled {
.navds-switch--disabled:not(.navds-switch--loading) {
opacity: 0.3;
}
+9 -2
View File
@@ -24,13 +24,13 @@
padding: 0.5rem;
background-color: var(--navds-text-field-color-background);
border-radius: 4px;
border: 2px solid var(--navds-text-field-color-border);
border: 1px solid var(--navds-text-field-color-border);
min-height: 48px;
width: 100%;
}
.navds-form-field--small > .navds-text-field__input {
padding: 0 0.15rem;
padding: 0 0.25rem;
min-height: 32px;
}
@@ -52,6 +52,13 @@
*/
.navds-text-field--error > .navds-text-field__input:not(:hover):not(:disabled) {
border-color: var(--navds-text-field-color-border-error);
box-shadow: 0 0 0 1px var(--navds-text-field-color-border-error);
}
.navds-text-field--error
> .navds-text-field__input:focus:not(:hover):not(:disabled) {
box-shadow: 0 0 0 1px var(--navds-text-field-color-border-error),
var(--navds-shadow-focus);
}
/* Disabled handling */
+2 -1
View File
@@ -3,7 +3,6 @@
@import "grid.css";
@import "accordion.css";
@import "accordion-menu.css";
@import "alert.css";
@import "button.css";
@import "content-container.css";
@@ -12,12 +11,14 @@
@import "help-text.css";
@import "link.css";
@import "loader.css";
@import "menu.css";
@import "modal.css";
@import "popover.css";
@import "tag.css";
@import "panel.css";
@import "link-panel.css";
@import "speech-bubble.css";
@import "step-indicator.css";
@import "table.css";
/* Navno spesific packages */
-23
View File
@@ -12,8 +12,6 @@
);
--navds-loader-color-inverted-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-transparent-background: transparent;
--navds-loader-color-on-button-background: rgba(255, 255, 255, 0.3);
--navds-loader-color-on-button-foreground: currentColor;
}
.navds-loader {
@@ -78,27 +76,6 @@
width: 1rem;
}
/*
* Button spesific styling
*/
.navds-button .navds-loader .navds-loader__foreground {
stroke: var(--navds-loader-color-on-button-foreground);
}
.navds-button:hover .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button:active .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
.navds-button--primary .navds-loader .navds-loader__background,
.navds-button--danger .navds-loader .navds-loader__background {
stroke: var(--navds-loader-color-on-button-background);
}
@keyframes loader-rotate {
100% {
transform: rotate(360deg);
+102
View File
@@ -0,0 +1,102 @@
:root {
--navds-menu-color-text: var(--navds-semantic-color-link);
--navds-menu-color-text-hover: var(--navds-semantic-color-text);
--navds-menu-color-text-focus: var(--navds-semantic-color-text);
--navds-menu-color-background-hover: var(--navds-global-color-blue-50);
--navds-menu-color-text-active: var(--navds-semantic-color-text);
--navds-menu-outline-focus: var(--navds-semantic-color-focus);
}
.navds-menu__list {
list-style: none;
margin: 0;
padding: 0;
padding: 0 0.5rem;
}
.navds-menu__list--inner {
padding: 0;
}
.navds-menu-collapse__button {
cursor: pointer;
background-color: transparent;
border: none;
font: inherit;
text-align: inherit;
margin: 0;
width: 100%;
justify-content: space-between;
align-items: center;
font-weight: var(--navds-font-weight-bold);
color: var(--navds-menu-color-text);
}
.navds-menu-item,
.navds-menu-collapse__button {
font-weight: var(--navds-font-weight-bold);
display: flex;
padding: var(--navds-spacing-3) var(--navds-spacing-2);
text-decoration: none;
}
.navds-menu-item:focus,
.navds-menu-collapse__button:focus {
outline: 3px solid var(--navds-menu-outline-focus);
outline-offset: -3px;
color: var(--navds-menu-color-text-focus);
}
.navds-menu-collapse__button:focus > .navds-menu-collapse__expand-icon {
color: var(--navds-menu-color-focus);
}
.navds-menu-item:hover,
.navds-menu-collapse__button:hover {
background-color: var(--navds-menu-color-background-hover);
color: var(--navds-menu-color-text-hover);
}
.navds-menu-item--active {
box-shadow: -0.5rem 0 var(--navds-semantic-color-link);
color: var(--navds-menu-color-text-active);
text-decoration: none;
}
/* Collapse icon */
.navds-menu-collapse__expand-icon {
font-size: 1.5rem;
flex-shrink: 0;
margin-left: var(--navds-spacing-2);
}
.navds-menu-collapse__expand-icon--filled,
.navds-menu-collapse__button:hover > .navds-menu-collapse__expand-icon {
display: none;
}
.navds-menu-collapse__button:hover > .navds-menu-collapse__expand-icon--filled {
display: block;
}
.navds-menu-collapse--open
> .navds-menu-collapse__button
> .navds-menu-collapse__expand-icon {
transform: rotate(180deg);
}
/* Nesting levels */
.navds-menu__list[data-depth="1"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="1"] .navds-menu-item {
padding-left: var(--navds-spacing-6);
}
.navds-menu__list[data-depth="2"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="2"] .navds-menu-item {
padding-left: var(--navds-spacing-10);
}
.navds-menu__list[data-depth="3"] .navds-menu-collapse__button,
.navds-menu__list[data-depth="3"] .navds-menu-item {
padding-left: var(--navds-spacing-14);
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "0.12.6",
"version": "0.14.1",
"private": false,
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
@@ -21,7 +21,7 @@
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^0.7.0",
"@navikt/ds-tokens": "^0.8.0",
"normalize.css": "^8.0.1",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
+202
View File
@@ -0,0 +1,202 @@
:root {
--navds-step-indicator-color-step-line: var(--navds-semantic-color-divider);
--navds-step-indicator-color-step-text: var(--navds-semantic-color-text);
--navds-step-indicator-color-step-label: var(
--navds-semantic-color-interaction-primary
);
--navds-step-indicator-color-step-number-background: var(
--navds-semantic-color-canvas-background-light
);
--navds-step-indicator-color-step-number-background-finished: var(
--navds-semantic-color-canvas-background
);
--navds-step-indicator-color-step-number-shadow: var(
--navds-semantic-color-border
);
--navds-step-indicator-color-step-number-shadow-active: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-step-indicator-color-step-number-shadow-hover: var(
--navds-semantic-color-interaction-primary
);
--navds-step-indicator-color-step-number-background-active: var(
--navds-semantic-color-interaction-primary-selected
);
--navds-step-indicator-color-step-number-text-active: var(
--navds-semantic-color-text-inverted
);
--navds-step-indicator-color-step-number-shadow-inset: var(
--navds-semantic-color-component-background-light
);
}
/* StepIndicator */
.navds-step-indicator {
display: flex;
align-items: flex-start;
padding: 0;
margin: 0;
}
/* Step */
.navds-step-indicator__step-wrapper {
padding: 0 var(--navds-spacing-2);
flex: 1;
position: relative;
list-style: none;
min-width: 10rem;
}
.navds-step-indicator__step-wrapper--hidelabel {
min-width: 5rem;
}
.navds-step-indicator__step {
display: flex;
align-items: center;
flex-direction: column;
padding: 0;
background: none;
border: none;
appearance: none;
width: 100%;
flex-shrink: 1;
color: var(--navds-step-indicator-color-step-text);
text-decoration: none;
cursor: pointer;
}
.navds-step-indicator__step-number {
flex-shrink: 0;
display: flex;
width: 2rem;
height: 2rem;
margin: 0.5rem;
border-radius: 50%;
align-items: center;
justify-content: center;
box-shadow: 0 0 0 1px var(--navds-step-indicator-color-step-number-shadow);
background-color: var(--navds-step-indicator-color-step-number-background);
}
.navds-step-indicator__step-wrapper:first-child
> .navds-step-indicator__step
> .navds-step-indicator__step-number {
padding-right: 0;
}
.navds-step-indicator__step-wrapper:last-child
> .navds-step-indicator__step
> .navds-step-indicator__step-number {
padding-left: 0;
}
.navds-step-indicator__step-label {
width: 100%;
margin-top: var(--navds-spacing-4);
text-align: center;
color: var(--navds-step-indicator-color-step-label);
text-decoration: underline;
}
.navds-step-indicator__step-line {
flex: 1 1 100%;
position: absolute;
top: 1.5rem;
right: calc(50% + 2rem);
left: calc(-50% + 2rem);
display: block;
border-top: 2px solid var(--navds-step-indicator-color-step-line);
border-radius: 4px;
pointer-events: none;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-label {
color: var(--navds-step-indicator-color-step-text);
font-weight: bold;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-number {
background-color: var(
--navds-step-indicator-color-step-number-background-active
);
color: var(--navds-step-indicator-color-step-number-text-active);
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
width: 2.5rem;
height: 2.5rem;
margin: 0.25rem;
}
.navds-step-indicator__step:focus {
outline: none;
}
.navds-step-indicator__step:hover > .navds-step-indicator__step-label {
text-decoration: none;
}
.navds-step-indicator__step.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-label {
text-decoration: underline;
}
.navds-step-indicator__step--active > .navds-step-indicator__step-label,
.navds-step-indicator__step--active.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-label {
text-decoration: none;
}
.navds-step-indicator__step:hover > .navds-step-indicator__step-number {
background: var(--navds-step-indicator-color-step-number-background);
box-shadow: 0 0 0 2px
var(--navds-step-indicator-color-step-number-shadow-hover);
}
.navds-step-indicator__step--active:hover > .navds-step-indicator__step-number {
background-color: var(
--navds-step-indicator-color-step-number-background-active
);
color: var(--navds-step-indicator-color-step-number-text-active);
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
}
.navds-step-indicator__step:focus > .navds-step-indicator__step-number {
box-shadow: var(--navds-shadow-focus);
outline: none;
}
.navds-step-indicator__step--active:focus > .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px inset
var(--navds-step-indicator-color-step-number-shadow-inset),
var(--navds-shadow-focus);
}
.navds-step-indicator__step--disabled:hover
> .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px var(--navds-step-indicator-color-step-number-shadow);
}
.navds-step-indicator__step--disabled.navds-step-indicator__step--active:disabled
> .navds-step-indicator__step-number {
box-shadow: 0 0 0 1px
var(--navds-step-indicator-color-step-number-shadow-active);
}
/* Finished state */
.navds-step-indicator__step--finished > .navds-step-indicator__step-number,
.navds-step-indicator__step--finished.navds-step-indicator__step--disabled
> .navds-step-indicator__step-number {
background: var(--navds-step-indicator-color-step-number-background-finished);
}
/* Disabled */
.navds-step-indicator__step--disabled > .navds-step-indicator__step-number,
.navds-step-indicator__step--disabled > .navds-step-indicator__step-label {
opacity: 0.3;
}
.navds-step-indicator__step--disabled {
cursor: not-allowed;
}
+4 -3
View File
@@ -22,9 +22,10 @@ export const getPublishedIcons = async () => {
throw e;
});
return data?.meta?.components?.filter(
(component: any) => component?.containing_frame?.pageName !== "🔆Pictogram"
);
return data?.meta?.components?.filter((component: any) => {
const page = component?.containing_frame?.pageName;
return page !== "🔆Pictogram" && page !== "🧩Placeholder";
});
};
/**
@@ -1,7 +1,8 @@
import React from "react";
import { storiesOf } from "@storybook/react";
import isChromatic from "chromatic/isChromatic";
import * as Icons from "../src";
import * as Icons from "./src";
export default {
title: "ds-icons/Ikoner",
argTypes: {
@@ -16,7 +17,7 @@ export default {
},
};
if (process.env.STORYBOOK_CHROMATIC === "true") {
if (isChromatic()) {
const iconsStories = storiesOf("ds-icons/Ikoner", module);
Object.entries(Icons).forEach(([name, Icon]) => {
+54 -6
View File
@@ -857,6 +857,18 @@
"created_at": "2021-01-11T13:37:55.491Z",
"pageName": "File"
},
{
"name": "FileError",
"description": "",
"created_at": "2022-01-27T12:48:37.583Z",
"pageName": "File"
},
{
"name": "FileErrorFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.605Z",
"pageName": "File"
},
{
"name": "FileFilled",
"description": "",
@@ -875,6 +887,30 @@
"created_at": "2021-04-26T09:24:37.951Z",
"pageName": "File"
},
{
"name": "FileProgressFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.592Z",
"pageName": "File"
},
{
"name": "Files",
"description": "",
"created_at": "2022-01-27T12:48:37.567Z",
"pageName": "File"
},
{
"name": "FileSuccess",
"description": "",
"created_at": "2022-01-27T12:48:37.575Z",
"pageName": "File"
},
{
"name": "FileSuccessFilled",
"description": "",
"created_at": "2022-01-27T12:48:37.598Z",
"pageName": "File"
},
{
"name": "FillForms",
"description": "",
@@ -893,6 +929,18 @@
"created_at": "2020-07-01T10:37:42.891Z",
"pageName": "Interface"
},
{
"name": "Filter2",
"description": "",
"created_at": "2022-01-14T09:16:08.202Z",
"pageName": "Interface"
},
{
"name": "Filter2Filled",
"description": "",
"created_at": "2022-01-14T09:16:08.197Z",
"pageName": "Interface"
},
{
"name": "FilterFilled",
"description": "",
@@ -1907,6 +1955,12 @@
"created_at": "2021-01-11T13:37:55.582Z",
"pageName": "Interface"
},
{
"name": "SelfService",
"description": "",
"created_at": "2021-04-26T09:24:37.989Z",
"pageName": "Fyrstikkalleen"
},
{
"name": "SelfServiceFilled",
"description": "",
@@ -1925,12 +1979,6 @@
"created_at": "2021-04-26T09:24:37.982Z",
"pageName": "Fyrstikkalleen"
},
{
"name": "SelfServiceStroke",
"description": "",
"created_at": "2021-04-26T09:24:37.989Z",
"pageName": "Fyrstikkalleen"
},
{
"name": "Send",
"description": "",
+6 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "0.7.1",
"version": "0.8.1",
"private": false,
"description": "NAVs egne ikoner i SVG og React format",
"repository": {
@@ -28,10 +28,8 @@
"scripts": {
"create-package-json-pointers-to-esm": "node ../../../utilities/scripts/createPackageJsonsWithESMPointers.js",
"create-icons": "svgr --out-dir src svg",
"convert-icons": "node scripts/pngConverter.mjs",
"clean": "rimraf src cjs esm png NAV-ikonpakke-png.zip NAV-ikonpakke-svg.zip",
"zip-icons": "node scripts/zipIcons.mjs",
"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",
"clean": "rimraf src cjs esm",
"build": "yarn clean && yarn create-icons && tsc && tsc -p tsconfig.esm.json && yarn create-package-json-pointers-to-esm",
"update": "ts-node figma/index.ts dotenv/config"
},
"dependencies": {
@@ -44,7 +42,9 @@
"devDependencies": {
"@svgr/cli": "^5.5.0",
"@types/lodash.startcase": "^4.4.6",
"@types/rimraf": "3.0.2",
"@types/uuid": "^8.3.1",
"axios": "^0.21.3",
"copyfiles": "^2.4.1",
"dotenv": "^10.0.0",
"lodash.kebabcase": "^4.1.1",
@@ -52,7 +52,6 @@
"react": "^16.8.0 || ^17.0.0",
"rimraf": "3.0.2",
"sharp": "0.29.1",
"ts-node": "^10.4.0",
"zip-dir": "^2.0.0"
"ts-node": "^10.4.0"
}
}
@@ -1,41 +0,0 @@
import { existsSync, mkdirSync, readdirSync } from "fs";
import sharp from "sharp";
import rimraf from "rimraf";
import pLimit from "p-limit";
const convertToPng = async () => {
const inputDir = "./svg/";
const outDir = "./png/";
const sizes = [16, 24, 128, 256];
console.log("Converting icons to .png format");
const limit = pLimit(20);
if (existsSync(outDir)) {
rimraf.sync(outDir);
}
mkdirSync(outDir);
sizes.forEach((size) => mkdirSync(outDir + size.toString()));
await Promise.all(
readdirSync(inputDir).map((file) => {
return limit(() =>
sizes.forEach((size) => {
const density = (100 * size) / 16;
sharp(inputDir + file, { density })
.resize(size)
.png()
.toFile(outDir + size.toString() + "/" + file.replace("svg", "png"))
.catch((e) => console.error(e));
})
);
})
);
console.log("Finished converting icons to .png format");
};
try {
convertToPng();
} catch (e) {
console.error(e);
}
-16
View File
@@ -1,16 +0,0 @@
import zipdir from "zip-dir";
const zipDir = async (dir, name) => {
await zipdir(dir, { saveTo: name }, function (err, buffer) {
if (err) {
console.error(err);
}
});
};
try {
zipDir("./png/", "NAV-ikonpakke-png.zip");
zipDir("./svg/", "NAV-ikonpakke-svg.zip");
} catch (e) {
console.error(e);
}
@@ -1,23 +0,0 @@
import { Meta } from "@storybook/addon-docs";
<Meta title="ds-icons/Kom i gang" />
# Ta i bruk ikonpakken `@navikt/ds-icons`
Alle ikoner kan bli funnet her https://design.nav.no/designsystem/resources/icons
## Oppsett
```bash
yarn add @navikt/ds-icons
```
```jsx
Import { Expand } from `@navikt/ds-icons`;
<Expand
title="Åpne meny"
/>
```
Note: Det kan være tilfeller der oppsettet ditt ikke har støtte for SVG, og det må da legges til manuelt i eks en webpack config basert på hva som blir brukt.
+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.4858 7.11515C20.7324 5.94459 20.7324 4.04674 19.4858 2.87619C18.2838 1.74743 16.3616 1.70712 15.1081 2.75525L14.9716 2.87619L3.6862 13.4736L3.52649 13.6301C1.61004 15.5902 1.66328 18.6389 3.6862 20.5385C5.70912 22.4381 8.95584 22.4881 11.0432 20.6885L11.2098 20.5385L22.4953 9.94113L24 11.3541L12.7146 21.9515L12.5304 22.1187C9.61022 24.6816 5.02951 24.6259 2.18147 21.9515C-0.666561 19.2771 -0.725895 14.9757 2.00347 12.2335L2.18147 12.0606L13.4669 1.4632C15.5445 -0.487732 18.913 -0.487732 20.9905 1.4632C23.0135 3.36279 23.0667 6.41157 21.1503 8.37164L20.9905 8.52814L9.7051 19.1255L9.56865 19.2465C8.31517 20.2946 6.39296 20.2543 5.19092 19.1255C3.98889 17.9968 3.94596 16.1918 5.06214 15.0147L5.19092 14.8866L16.4764 4.28917L17.9811 5.70216L6.69565 16.2996L6.61297 16.3867C6.28225 16.7789 6.30981 17.3502 6.69565 17.7126C7.08149 18.0749 7.68993 18.1008 8.10757 17.7902L8.20038 17.7126L19.4858 7.11515Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.8634 1.00122C18.1639 0.974609 19.5426 1.3819 20.5704 2.35845C21.5981 3.33501 22.0267 4.64511 21.9987 5.88083C21.9709 7.10846 21.4908 8.35534 20.5704 9.22999L11.1693 18.163C10.6021 18.7019 9.81338 18.9683 9.05641 18.9838C8.29093 18.9995 7.45868 18.76 6.83035 18.163C6.20202 17.5659 5.95004 16.7751 5.96653 16.0478C5.98283 15.3285 6.26318 14.579 6.83035 14.0401L13.3388 7.85568C13.7382 7.47618 14.3857 7.47618 14.7851 7.85568C15.1845 8.23518 15.1845 8.85048 14.7851 9.22999L8.27667 15.4144C8.13723 15.5469 8.01819 15.7922 8.01145 16.0896C8.0049 16.3789 8.10622 16.6267 8.27667 16.7887C8.44712 16.9506 8.70788 17.0469 9.01237 17.0407C9.32537 17.0343 9.58355 16.9212 9.72299 16.7887L19.1241 7.85568C19.6168 7.38747 19.9355 6.64474 19.9538 5.83898C19.9719 5.0413 19.6939 4.27422 19.1241 3.73276C18.5542 3.19129 17.7469 2.92716 16.9075 2.94433C16.0595 2.96168 15.2778 3.26454 14.7851 3.73276L5.38403 12.6658C4.6945 13.321 4.13449 14.5364 4.05489 15.8977C3.9765 17.2386 4.37172 18.5754 5.38403 19.5373C7.5157 21.5628 10.484 21.5628 12.6156 19.5373L19.1519 13.3265C19.5513 12.947 20.1988 12.947 20.5982 13.3265C20.9976 13.706 20.9976 14.3213 20.5982 14.7008L14.0619 20.9116C11.1315 23.6961 6.86816 23.6961 3.93772 20.9116C2.41897 19.4685 1.91025 17.5412 2.01264 15.7899C2.11384 14.0591 2.81936 12.3541 3.93772 11.2914L13.3388 2.35845C14.2593 1.4838 15.5715 1.02766 16.8634 1.00122Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.4858 7.11888C20.7324 5.94771 20.7324 4.04887 19.4858 2.87769C18.2838 1.74835 16.3616 1.70802 15.1081 2.75669L14.9716 2.87769L3.6862 13.4807L3.52649 13.6372C1.61004 15.5983 1.66328 18.6487 3.6862 20.5493C4.61095 21.4181 5.79143 21.9002 7 21.9956V22H24V24L7 24C5.24586 23.9013 3.52179 23.2223 2.18147 21.963C-0.666561 19.2872 -0.725895 14.9835 2.00347 12.2399L2.18147 12.0669L13.4669 1.46396C15.5445 -0.487988 18.913 -0.487988 20.9905 1.46396C23.0135 3.36455 23.0667 6.41493 21.1503 8.37603L20.9905 8.53261L9.7051 19.1356L9.56865 19.2566C8.31517 20.3053 6.39296 20.2649 5.19092 19.1356C3.98889 18.0062 3.94596 16.2003 5.06214 15.0226L5.19092 14.8944L16.4764 4.29142L17.9811 5.70515L6.69565 16.3081L6.61297 16.3953C6.28225 16.7877 6.30981 17.3593 6.69565 17.7219C7.08149 18.0844 7.68993 18.1103 8.10757 17.7995L8.20038 17.7219L19.4858 7.11888Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.3472 0.00138792C17.7614 -0.0288776 19.2813 0.434034 20.4223 1.56794L19.3387 2.6448L20.4223 1.56794C21.5633 2.70184 22.0291 4.21243 21.9986 5.61786C21.9684 7.01063 21.4486 8.445 20.4223 9.46495L11.0314 18.7978C10.358 19.467 9.43759 19.7854 8.57056 19.8039C7.69079 19.8227 6.71672 19.5352 5.97471 18.7978C5.23271 18.0604 4.94338 17.0923 4.96233 16.218C4.981 15.3563 5.30134 14.4416 5.97472 13.7724L12.4761 7.31122C13.0746 6.71649 14.0448 6.71649 14.6433 7.31122C15.2417 7.90596 15.2417 8.87022 14.6433 9.46495L8.14185 15.9261C8.10938 15.9584 8.03076 16.083 8.02641 16.2836C8.02234 16.4715 8.08594 16.5885 8.14185 16.6441C8.19777 16.6996 8.31553 16.7628 8.50458 16.7588C8.70636 16.7545 8.83176 16.6763 8.86423 16.6441L18.2552 7.31122C18.6406 6.92821 18.9187 6.28392 18.9345 5.55228C18.9501 4.8333 18.71 4.17373 18.2552 3.72167C17.8003 3.26961 17.1366 3.03104 16.4132 3.04652C15.677 3.06227 15.0287 3.33865 14.6433 3.72167L5.25234 13.0545C4.67063 13.6326 4.14756 14.7746 4.07345 16.1004C4.00113 17.3941 4.36759 18.6364 5.25234 19.5157C7.18223 21.4337 9.82386 21.4337 11.7538 19.5157L18.2829 13.0269C18.8814 12.4322 19.8516 12.4322 20.4501 13.0269C21.0485 13.6216 21.0485 14.5859 20.4501 15.1806L13.9209 21.6694C10.7941 24.7769 6.21196 24.7769 3.0852 21.6694C1.44161 20.036 0.9051 17.8683 1.01337 15.9314C1.11986 14.0266 1.86096 12.1174 3.0852 10.9008L12.4761 1.56794C13.5024 0.547983 14.9457 0.0313808 16.3472 0.00138792Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1015 B

After

Width:  |  Height:  |  Size: 1.6 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4142 0H2V22H12V20H4V2H12V7H17V14H19V4.58579L14.4142 0ZM16.5858 5L14 2.41421V5H16.5858ZM18 17.5858L21.2929 14.2929L22.7071 15.7071L19.4142 19L22.7071 22.2929L21.2929 23.7071L18 20.4142L14.7071 23.7071L13.2929 22.2929L16.5858 19L13.2929 15.7071L14.7071 14.2929L18 17.5858Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 445 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0V22H11.5L14.5 19L11 15.5L14.5 12L18 15.5L19 14.5V4.5L14.5 0H2ZM13.5 5V2L16.5 5H13.5ZM13.2929 22.2929L16.5858 19L13.2929 15.7071L14.7071 14.2929L18 17.5858L21.2929 14.2929L22.7071 15.7071L19.4142 19L22.7071 22.2929L21.2929 23.7071L18 20.4142L14.7071 23.7071L13.2929 22.2929Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 448 B

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

After

Width:  |  Height:  |  Size: 645 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 1V6H18" stroke="#262626" stroke-width="2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.4142 0H2V22H11V20H4V2H13.5858L17 5.41421V16H19V4.58579L14.4142 0ZM22.2689 14.3177L16.0317 21.0004L13.7593 18.3492L12.2407 19.6508L15.9683 23.9996L23.7311 15.6823L22.2689 14.3177Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 410 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0V22H12L10 19.5L14 16L16 18L19 15V4.5L14.5 0H2ZM13.5 5V2L16.5 5H13.5ZM22.2689 14.3177L16.0317 21.0004L13.7593 18.3492L12.2407 19.6508L15.9683 23.9996L23.7311 15.6823L22.2689 14.3177Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 356 B

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

After

Width:  |  Height:  |  Size: 645 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.34783 12.9348V12.5015L9.03177 12.2052L1 4.67546L0.316059 5.405L1 4.67546V3.5H23V4.69448L15.4668 12.2277L15.1739 12.5206V12.9348L15.1739 21.5495L9.34783 23.0384V12.9348Z" stroke="#262626" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 321 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3V4.17546C0 4.45187 0.114409 4.71595 0.316059 4.905L8.34783 12.4348V22.5384C8.34783 23.1911 8.96302 23.6689 9.59542 23.5073L15.4215 22.0184C15.8642 21.9052 16.1739 21.5064 16.1739 21.0495V12.4348L23.7071 4.90159C23.8946 4.71405 24 4.4597 24 4.19448V3C24 2.44772 23.5523 2 23 2H1C0.447715 2 0 2.44772 0 3Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 438 B

+1 -1
View File
@@ -4,5 +4,5 @@
"outDir": "./cjs",
"module": "commonjs"
},
"exclude": ["./figma", "./scripts", "**/stories"]
"exclude": ["./figma", "./scripts", "**/*.stories.*"]
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "0.14.3",
"version": "0.15.2",
"private": false,
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
@@ -35,7 +35,7 @@
},
"dependencies": {
"@material-ui/core": "^4.12.3",
"@navikt/ds-icons": "^0.7.1",
"@navikt/ds-icons": "^0.8.1",
"@popperjs/core": "^2.10.1",
"classnames": "^2.2.6",
"react-collapse": "^5.1.0",
@@ -50,12 +50,12 @@
"@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/react-modal": "^3.13.1",
"@types/styled-components": "^5.1.14",
"copyfiles": "^2.4.1",
"faker": "^5.5.3",
"jest": "^27.2.0",
"react-router-dom": "^5.3.0",
"react-router-dom": "^6.1.0",
"rimraf": "3.0.2",
"styled-components": "^5.3.1",
"ts-jest": "^27.0.5"
@@ -1,39 +0,0 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import MenuItems from "./MenuItems";
import Collapsable, {
AccordionMenuCollapsableType,
} from "./AccordionMenuCollapsable";
import Item, { AccordionMenuItemType } from "./AccordionMenuItem";
export interface AccordionMenuProps extends React.HTMLAttributes<HTMLElement> {
children: React.ReactNode;
}
interface AccordionMenuComponent
extends React.ForwardRefExoticComponent<
AccordionMenuProps & React.RefAttributes<HTMLElement>
> {
Collapsable: AccordionMenuCollapsableType;
Item: AccordionMenuItemType;
}
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
({ children, className, ...rest }, ref) => {
return (
<nav
role="navigation"
ref={ref}
className={cl("navds-accordion-menu", className)}
{...rest}
>
<MenuItems>{children}</MenuItems>
</nav>
);
}
) as AccordionMenuComponent;
AccordionMenu.Collapsable = Collapsable;
AccordionMenu.Item = Item;
export default AccordionMenu;
@@ -1,45 +0,0 @@
import React, { forwardRef, HTMLAttributes, useState } from "react";
import cl from "classnames";
import { Expand } from "@navikt/ds-icons";
import MenuItems from "./MenuItems";
export interface AccordionMenuCollapsableProps
extends HTMLAttributes<HTMLDivElement> {
title: string;
defaultOpen?: boolean;
children: React.ReactNode;
}
export type AccordionMenuCollapsableType = React.ForwardRefExoticComponent<
AccordionMenuCollapsableProps & React.RefAttributes<HTMLDivElement>
>;
const Collapsable: AccordionMenuCollapsableType = forwardRef(
({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
return (
<div
ref={ref}
className={cl("navds-accordion-menu-collapsable", className, {
"navds-accordion-menu-collapsable--open": isOpen,
})}
{...rest}
>
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-accordion-menu-collapsable__button"
>
{title}
<Expand
title={isOpen ? "Pil peker opp" : "Pil peker ned"}
className="navds-accordion-menu-collapsable__expand-icon"
/>
</button>
{isOpen && <MenuItems>{children}</MenuItems>}
</div>
);
}
);
export default Collapsable;
@@ -1,13 +0,0 @@
import React from "react";
const MenuItems = ({ children }: { children: React.ReactNode }) => (
<ul className="navds-accordion-menu__list">
{React.Children.toArray(children).map((child, i) => (
<li key={i} className="navds-accordion-menu__list-item">
{child}
</li>
))}
</ul>
);
export default MenuItems;
@@ -1,3 +0,0 @@
export { default as AccordionMenu, AccordionMenuProps } from "./AccordionMenu";
export { AccordionMenuCollapsableProps } from "./AccordionMenuCollapsable";
export { AccordionMenuItemProps } from "./AccordionMenuItem";
@@ -1,66 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { AccordionMenu } from "../../index";
<Meta title="ds-react/accordion-menu/intro" />
# Hvordan ta i bruk Accordion-menu
```jsx
<AccordionMenu>
<AccordionMenu.item href="#leo">Leo</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla" active>
Nulla
</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.item href="#justo" aria-current="page">
Justo
</AccordionMenu.item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.item href="#nulla">Nulla</AccordionMenu.item>
<AccordionMenu.item href="#luctus">Luctus</AccordionMenu.item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
```
<Canvas>
<AccordionMenu>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla">Nulla</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
</AccordionMenu>
</Canvas>
Accordion-menu støtter opp til maks to-nivårer av `AccordionMenu.Collapsable` akkurat nå.
`AccordionMenu.Item` er implementert med `OverridableComponent`, noe som
gjør at man kan ta i bruk eks react-router slik:
```jsx
<AccordionMenu.item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Lenketekst
</AccordionMenu.item>
```
Her er `NavLink` fra `react-router-dom` brukt, og man får da
samtidig bruke alle propsene til denne komponenten som da er `activeClassName` her.
@@ -1,141 +0,0 @@
import * as React from "react";
import { AccordionMenu } from "../index";
import { NavLink, HashRouter as Router } from "react-router-dom";
export default {
title: "ds-react/accordion-menu",
component: { AccordionMenu },
};
export const All = () => (
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<AccordionMenu>
<AccordionMenu.Item href="#leo">Leo</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Accumsan">
<AccordionMenu.Item href="#justo" aria-current="page">
Justo
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur" active aria-current="page">
Pariatur
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Proin">
<AccordionMenu.Item href="#nulla" active>
Nulla
</AccordionMenu.Item>
<AccordionMenu.Item href="#luctus">Luctus</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item href="#justo" active>
Justo
</AccordionMenu.Item>
<AccordionMenu.Item href="#pariatur">Pariatur</AccordionMenu.Item>
</AccordionMenu>
</div>
);
export const ReactRouter = () => (
<AccordionMenu>
<AccordionMenu.Collapsable title="Nivå 1 – 3 rems høy">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/1"
>
Nivå 2 innrykk 2 rems
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/2"
>
Subtitle 3
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Skjema og søknad">
<AccordionMenu.Collapsable title="Satser">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/3"
>
Nivå 3 – 3 rems innrykk Har du rett til dagpenger når du mottar annen
økonomisk støtte fra NAV?
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/4"
>
Subtitle 2
</AccordionMenu.Item>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/5"
>
Subtitle 3
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Collapsable title="Sakbehandlingstider">
<AccordionMenu.Collapsable title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/6"
>
Subtitle 5
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/7"
>
Internasjonalt
</AccordionMenu.Item>
<AccordionMenu.Collapsable title="Meld fra om endringer lang tittel på første nivå">
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/8"
>
Subtitle 6
</AccordionMenu.Item>
</AccordionMenu.Collapsable>
<AccordionMenu.Item
as={NavLink}
activeClassName="navds-accordion-menu-item--active"
to="/9"
>
Nivå 1
</AccordionMenu.Item>
</AccordionMenu>
);
ReactRouter.decorators = [
(Story) => (
<Router>
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<Story />
</div>
</Router>
),
];
@@ -43,6 +43,7 @@ const AccordionHeader: AccordionHeaderType = forwardRef(
return (
<button
{...rest}
ref={ref}
id={context.buttonId}
className={cl(
@@ -52,17 +53,17 @@ const AccordionHeader: AccordionHeaderType = forwardRef(
"navds-heading--small"
)}
onClick={handleClick}
{...rest}
aria-expanded={context.open}
>
{children}
<Expand
title={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
aria-hidden
className={cl("navds-accordion__expand-icon", {
"navds-accordion__expand-icon--flip": context.open,
})}
/>
<ExpandFilled
title={context.open ? "Lukk panel ikon" : "Åpne panel ikon"}
aria-hidden
className={cl(
"navds-accordion__expand-icon",
"navds-accordion__expand-icon--filled",
@@ -0,0 +1,90 @@
import React, { useState } from "react";
import AccordionContent from "./AccordionContent";
import AccordionHeader from "./AccordionHeader";
import AccordionItem from "./AccordionItem";
import { Accordion } from ".";
export default {
title: "ds-react/accordion",
component: Accordion,
subcomponents: {
AccordionItem,
AccordionContent,
AccordionHeader,
},
};
export const All = () => {
const [open, setOpen] = useState(false);
return (
<>
<h1>Accordion</h1>
<h2>Controlled</h2>
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
<h2>Un-controlled</h2>
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum anim
minim eu eiusmod. Veniam in nostrud sunt tempor velit incididunt
sint ex dolor qui velit id eu. Deserunt magna sunt velit in. Est
exercitation id cillum qui do. Minim adipisicing nostrud commodo
proident occaecat aliquip nulla anim proident reprehenderit. Magna
ipsum officia veniam cupidatat duis veniam dolore reprehenderit
mollit velit.Ut consequat commodo minim occaecat id pariatur. Nisi
enim tempor laborum commodo. Tempor sit quis nostrud eu cupidatat
sunt commodo reprehenderit irure deserunt eiusmod ipsum.
Exercitation quis commodo cillum eiusmod eiusmod. Do laborum qui
proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</>
);
};
@@ -1,72 +0,0 @@
import { Meta, Canvas, Props } from "@storybook/addon-docs";
import { Accordion } from "../../index";
<Meta title="ds-react/accordion/intro" />
# Hvordan ta i bruk Accordion
```jsx
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit occaecat nisi
qui nostrud sit.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Aliquip amet irure consectetur occaecat</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do deserunt
amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
<Canvas>
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>
Aliquip amet irure consectetur occaecat
</Accordion.Header>
<Accordion.Content>
Cupidatat aliqua eu ea et anim excepteur. Labore aliquip dolore laborum
consequat. Reprehenderit ad velit quis eiusmod ex sint aliquip do
deserunt amet exercitation velit Lorem.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</Canvas>
## Controlled state
Accordion-komponeten styrer selv open-state, men om man ønsker kan man selv overskrive denne med
`open`-prop + `onClick`-prop slik det er gjort på eksemplet.
```jsx
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={(open) => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
laboris voluptate officia pariatur.Lorem est ex anim velit
</Accordion.Content>
</Accordion.Item>
</Accordion>
```
`renderContentWhenClosed`-prop på `Accordion.Item` bestemmer om innholdet (children) skal beholdes i dom-strukturen mens
Accordion er lukket. Defaulter til `false`.
@@ -1,92 +0,0 @@
import React, { useState } from "react";
import AccordionContent from "../AccordionContent";
import AccordionHeader from "../AccordionHeader";
import AccordionItem from "../AccordionItem";
import { Accordion } from "../index";
export default {
title: "ds-react/accordion",
component: Accordion,
subcomponents: {
AccordionItem,
AccordionContent,
AccordionHeader,
},
};
export const All = () => {
const [open, setOpen] = useState(false);
return (
<>
<div>
<h1>Accordion</h1>
<h2>Controlled</h2>
<Accordion>
<Accordion.Item open={open}>
<Accordion.Header onClick={() => setOpen(!open)}>
Accordion header text
</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
<h2>Un-controlled</h2>
<Accordion>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
<Accordion.Item>
<Accordion.Header>Accordion header text</Accordion.Header>
<Accordion.Content>
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam
officia laboris voluptate officia pariatur.Lorem est ex anim velit
occaecat nisi qui nostrud sit consectetur consectetur officia
nostrud ullamco. Est ex duis proident nostrud elit qui laborum
anim minim eu eiusmod. Veniam in nostrud sunt tempor velit
incididunt sint ex dolor qui velit id eu. Deserunt magna sunt
velit in. Est exercitation id cillum qui do. Minim adipisicing
nostrud commodo proident occaecat aliquip nulla anim proident
reprehenderit. Magna ipsum officia veniam cupidatat duis veniam
dolore reprehenderit mollit velit.Ut consequat commodo minim
occaecat id pariatur. Nisi enim tempor laborum commodo. Tempor sit
quis nostrud eu cupidatat sunt commodo reprehenderit irure
deserunt eiusmod ipsum. Exercitation quis commodo cillum eiusmod
eiusmod. Do laborum qui proident commodo adipisicing eiusmod id.
</Accordion.Content>
</Accordion.Item>
</Accordion>
</div>
</>
);
};
@@ -1,6 +1,6 @@
import React from "react";
import { Alert } from "..";
import { BodyLong, Heading } from "../..";
import { Alert } from ".";
import { BodyLong, Heading } from "..";
export default {
title: "ds-react/alert",
@@ -1,96 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Alert, Heading, BodyLong } from "../../index";
<Meta title="ds-react/alert/intro" />
# Hvordan ta i bruk Alert
```jsx
<Alert variant="info">
Id elit esse enim reprehenderit.Tempor tempor ex exercitation id aute
eu.Laborum nulla nisi irure voluptate mollit fugiat.Est quis culpa nostrud et
reprehenderit ea sint.Eu veniam labore enim labore qui eiusmod Lorem amet ad
esse.
</Alert>
```
<Canvas>
<Alert variant="info">
Id elit esse enim reprehenderit.Tempor tempor ex exercitation id aute
eu.Laborum nulla nisi irure voluptate mollit fugiat.Est quis culpa nostrud
et reprehenderit ea sint.Eu veniam labore enim labore qui eiusmod Lorem amet
ad esse.
</Alert>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`info`, `success`, `warning` og `error`.
<Canvas>
<Alert variant="info">Id elit esse enim reprehenderit.</Alert>
<Alert variant="success">Id elit esse enim reprehenderit.</Alert>
<Alert variant="warning">Id elit esse enim reprehenderit.</Alert>
<Alert variant="error">Id elit esse enim reprehenderit.</Alert>
</Canvas>
## Sizing
Alert har to størrelser: Default 64px height og small 32px height default.
<Canvas>
<Alert size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="success">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="warning">
Id elit esse enim reprehenderit.
</Alert>
<Alert size="small" variant="error">
Id elit esse enim reprehenderit.
</Alert>
</Canvas>
## fullWidth
<Canvas>
<div style={{ margin: 32, display: "grid", gap: 16 }}>
<Alert fullWidth variant="info">
Id elit esse enim reprehenderit.
</Alert>
<Alert fullWidth size="small" variant="info">
Id elit esse enim reprehenderit.
</Alert>
</div>
</Canvas>
## Med heading
```jsx
<Alert variant="info">
<Heading spacing size="small" level="2">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui laboris
ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat sint commodo
consequat eu aute.
</BodyLong>
</Alert>
```
<Canvas>
<Alert variant="info">
<Heading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Heading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui laboris
ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat sint commodo
consequat eu aute.
</BodyLong>
</Alert>
</Canvas>
+55 -18
View File
@@ -1,6 +1,8 @@
import React, { forwardRef } from "react";
import React, { useRef, useState, forwardRef } from "react";
import mergeRefs from "react-merge-refs";
import cl from "classnames";
import { BodyShort, OverridableComponent } from "../";
import { BodyShort, OverridableComponent, Loader } from "../";
import { useClientLayoutEffect } from "../util";
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
@@ -24,6 +26,11 @@ export interface ButtonProps
* @default false
*/
disabled?: boolean;
/**
* Replaces button content with a Loader component, keeps width
* @default false
*/
loading?: boolean;
}
const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
@@ -34,25 +41,55 @@ const Button: OverridableComponent<ButtonProps, HTMLButtonElement> = forwardRef(
className,
children,
size = "medium",
loading = false,
disabled,
...rest
},
ref
) => (
<Component
{...rest}
ref={ref}
className={cl(
className,
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`
)}
>
<BodyShort as="span" className="navds-button__inner" size={size}>
{children}
</BodyShort>
</Component>
)
) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
const mergedRef = mergeRefs([buttonRef, ref]);
const [widthOverride, setWidthOverride] = useState<number>();
useClientLayoutEffect(() => {
if (loading) {
const requestID = window.requestAnimationFrame(() => {
setWidthOverride(buttonRef?.current?.getBoundingClientRect()?.width);
});
return () => {
setWidthOverride(undefined);
cancelAnimationFrame(requestID);
};
}
}, [loading, children]);
return (
<Component
{...rest}
ref={mergedRef}
className={cl(
className,
"navds-button",
`navds-button--${variant}`,
`navds-button--${size}`,
{
"navds-button--loading": widthOverride,
}
)}
style={{ width: widthOverride }}
disabled={disabled ?? widthOverride ? true : undefined}
>
<BodyShort
as="span"
className="navds-button__inner"
size={size}
aria-live="polite"
>
{widthOverride ? <Loader size={size} /> : children}
</BodyShort>
</Component>
);
}
);
export default Button;
@@ -1,5 +1,5 @@
import React from "react";
import { Button } from "../index";
import React, { useState } from "react";
import { Button } from "./index";
import { Success } from "@navikt/ds-icons";
export default {
@@ -37,6 +37,13 @@ const varSwitch = {
};
export const All = () => {
const [loadingState, setLoadingState] = useState(true);
const [content, setContent] = useState<string>("");
const toggleLoading = () => {
setLoadingState(!loadingState);
};
return (
<div style={{ paddingLeft: "1rem" }}>
<h1>Button</h1>
@@ -82,7 +89,7 @@ export const All = () => {
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant}>
<span className="sr-only">Success ikon</span>
<span className="navds-sr-only">Success ikon</span>
<Success />
</Button>
))}
@@ -98,11 +105,42 @@ export const All = () => {
<Section>
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
<span className="sr-only">Success ikon</span>
<span className="navds-sr-only">Success ikon</span>
<Success />
</Button>
))}
</Section>
<h2>Button w/loader</h2>
<Button onClick={toggleLoading}>Toggle loaders</Button>
<Button onClick={() => setContent((content) => `${content} wat`)}>
Change content
</Button>
<Section>
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
loading={loadingState}
onClick={toggleLoading}
>
{content || varSwitch[variant]}
</Button>
))}
</Section>
<h2>Small w/loader</h2>
<Section>
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
size="small"
loading={loadingState}
onClick={toggleLoading}
>
{varSwitch[variant]}
</Button>
))}
</Section>
</div>
);
};
@@ -1,70 +0,0 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Button, Loader } from "../../index";
import { Success } from "@navikt/ds-icons";
<Meta title="ds-react/button/intro" />
# Hvordan ta i bruk Button
```jsx
<Button>Button</Button>
```
<Canvas>
<Button>Button</Button>
</Canvas>
## Varianter
`variants`-prop kan brukes for å endre utseende mellom
`primary`, `secondary`, `tertiary` og `danger`
<Canvas>
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="danger">Danger</Button>
</Canvas>
## Sizing
Button har to størrelser: Default 48px min-height og small 32px min-height
<Canvas>
<Button size="small" variant="primary">
Primary
</Button>
<Button size="small" variant="secondary">
Secondary
</Button>
<Button size="small" variant="tertiary">
Tertiary
</Button>
<Button size="small" variant="danger">
Danger
</Button>
</Canvas>
## Med ikon eller `<Loader />`
Hvis man setter ikoner (svg) eller `<Loader />` rett på button vil størrelsen
bli justert automatisk og sentrert.
<Canvas>
<Button>
<Loader /> Laster... <Loader />
</Button>
<Button size="small">
<Loader />
Laster...
<Loader />
</Button>
<Button>
<Success /> Laster... <Success />
</Button>
<Button size="small">
<Success />
Laster...
<Success />
</Button>
</Canvas>
@@ -96,7 +96,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
size={size}
as="legend"
className={cl("navds-fieldset__legend", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
>
{legend}
@@ -105,7 +105,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
(size === "medium" ? (
<BodyShort
className={cl("navds-fieldset__description", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
id={inputDescriptionId}
size="small"
@@ -116,7 +116,7 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
) : (
<Detail
className={cl("navds-fieldset__description", {
"sr-only": !!hideLegend,
"navds-sr-only": !!hideLegend,
})}
id={inputDescriptionId}
size="small"
+3 -3
View File
@@ -63,7 +63,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
size={size}
as="label"
className={cl("navds-select__label", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
>
{label}
@@ -72,7 +72,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
<BodyShort
as="div"
className={cl("navds-select__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
@@ -94,7 +94,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
>
{children}
</select>
<Expand className="navds-select__chevron" />
<Expand className="navds-select__chevron" aria-hidden />
</div>
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
{showErrorMsg && <ErrorMessage size={size}>{props.error}</ErrorMessage>}
+68 -7
View File
@@ -1,8 +1,35 @@
import cl from "classnames";
import React, { forwardRef, InputHTMLAttributes } from "react";
import React, {
forwardRef,
InputHTMLAttributes,
useEffect,
useState,
} from "react";
import { BodyShort, Detail, Loader, omit } from "..";
import { FormFieldProps, useFormField } from "./useFormField";
const SelectedIcon = () => (
<svg
width="12px"
height="12px"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
role="img"
aria-hidden
aria-label="Deaktiver valg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.01386 8L10.25 2L11 2.75L4.01386 9.5L1 6.5L1.75 5.75L4.01386 8Z"
fill="currentColor"
stroke="currentColor"
/>
</svg>
);
export interface SwitchProps
extends Omit<FormFieldProps, "error" | "errorId">,
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
@@ -18,6 +45,10 @@ export interface SwitchProps
* Toggles loading state with loader-component on switch
*/
loading?: boolean;
/**
* Positions switch on left/right side of label
*/
position?: "left" | "right";
}
const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
@@ -29,34 +60,64 @@ const Switch = forwardRef<HTMLInputElement, SwitchProps>((props, ref) => {
description,
hideLabel = false,
loading,
checked: checkedProp,
defaultChecked,
position = "left",
...rest
} = props;
const Description = size === "medium" ? BodyShort : Detail;
const [checked, setChecked] = useState(
defaultChecked ?? checkedProp ?? false
);
useEffect(() => {
checkedProp !== undefined && setChecked(checkedProp);
}, [checkedProp]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setChecked(e.target.checked);
props.onChange && props.onChange(e);
};
return (
<div
className={cl("navds-switch", props.className, `navds-switch--${size}`, {
"navds-switch--disabled": inputProps.disabled,
})}
className={cl(
"navds-switch",
props.className,
`navds-switch--${size}`,
`navds-switch--${position}`,
{
"navds-switch--loading": loading,
"navds-switch--disabled": inputProps.disabled ?? loading,
}
)}
>
<input
{...omit(rest, ["size"])}
{...omit(inputProps, ["aria-invalid", "aria-describedby"])}
disabled={inputProps.disabled ?? loading}
checked={checkedProp}
defaultChecked={defaultChecked}
ref={ref}
type="checkbox"
onChange={(e) => handleChange(e)}
className={cl(className, "navds-switch__input")}
/>
<span className="navds-switch__track">
<span className="navds-switch__thumb">
{loading && <Loader size="xsmall" />}
{loading ? (
<Loader size="xsmall" aria-live="polite" />
) : checked ? (
<SelectedIcon />
) : null}
</span>
</span>
<label htmlFor={inputProps.id} className="navds-switch__label-wrapper">
<div
className={cl("navds-switch__content", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
"navds-switch--with-description": !!description && !hideLabel,
})}
>
+5 -3
View File
@@ -62,7 +62,9 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
htmlFor={inputProps.id}
size={size}
as="label"
className={cl("navds-text-field__label", { "sr-only": hideLabel })}
className={cl("navds-text-field__label", {
"navds-sr-only": hideLabel,
})}
>
{label}
</Label>
@@ -72,7 +74,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
{size === "medium" ? (
<BodyShort
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size="small"
@@ -83,7 +85,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
) : (
<Detail
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size="small"
+3 -3
View File
@@ -77,7 +77,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
size={size}
as="label"
className={cl("navds-textarea__label", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
>
{label}
@@ -86,7 +86,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
<BodyShort
as="div"
className={cl("navds-textarea__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
@@ -113,7 +113,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
/>
{hasMaxLength && (
<>
<span id={maxLengthId} className="sr-only">
<span id={maxLengthId} className="navds-sr-only">
Tekstområde med plass til {maxLength} tegn., Textarea can have{" "}
{maxLength} signs.
</span>
@@ -24,6 +24,11 @@ export interface CheckboxProps
* The value of the HTML element.
*/
value?: string;
/**
* Specify whether the Checkbox is in an indeterminate state
* @default false
*/
indeterminate?: boolean;
}
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
@@ -52,13 +57,25 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
"hideLabel",
])}
{...inputProps}
type="checkbox"
className="navds-checkbox__input"
ref={ref}
aria-checked={props.indeterminate ? "mixed" : inputProps.checked}
ref={(el) => {
if (el) {
el.indeterminate = props.indeterminate ?? false;
}
if (typeof ref === "function") {
ref(el);
} else if (ref != null) {
ref.current = el;
}
}}
/>
<label htmlFor={inputProps.id} className="navds-checkbox__label">
<div
className={cl("navds-checkbox__content", {
"sr-only": props.hideLabel,
"navds-sr-only": props.hideLabel,
})}
>
<BodyShort as="div" size={size}>
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import { Checkbox, CheckboxGroup } from "../../index";
import { Meta } from "@storybook/react/types-6-0";
export default {
@@ -6,6 +6,36 @@ export default {
component: Checkbox,
} as Meta;
export const Indeterminate = () => {
const [checked, setChecked] = useState([true, false]);
return (
<>
<Checkbox
checked={checked[0] && checked[1]}
indeterminate={checked[0] !== checked[1]}
onChange={(e) => setChecked([e.target.checked, e.target.checked])}
>
Parent
</Checkbox>
<div style={{ paddingLeft: "2rem" }}>
<Checkbox
checked={checked[0]}
onChange={(e) => setChecked([e.target.checked, checked[1]])}
>
Child 1
</Checkbox>
<Checkbox
checked={checked[1]}
onChange={(e) => setChecked([checked[0], e.target.checked])}
>
Child 2
</Checkbox>
</div>
</>
);
};
export const All = () => {
const Checkboxes = (props) => (
<CheckboxGroup
@@ -51,6 +81,13 @@ export const All = () => {
<Checkbox value="Orange" description="Laborum ad" disabled defaultChecked>
Orange
</Checkbox>
<h3>Indeterminate</h3>
<Checkbox value="Apple" indeterminate>
Apple
</Checkbox>
<Checkbox value="Orange" indeterminate size="small">
Orange
</Checkbox>
<h2>Checkbox group</h2>
<Checkboxes />
@@ -32,7 +32,6 @@ const useCheckbox = ({ children, ...props }: CheckboxProps) => {
...rest,
inputProps: {
...inputProps,
type: "checkbox",
checked: checkboxGroup?.value
? checkboxGroup.value.includes(props.value as string)
: props.checked,
@@ -90,7 +90,7 @@ const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
size={size}
as="label"
className={cl("navds-text-field__label", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
>
{label}
@@ -99,7 +99,7 @@ const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
<BodyShort
as="div"
className={cl("navds-text-field__description", {
"sr-only": hideLabel,
"navds-sr-only": hideLabel,
})}
id={inputDescriptionId}
size={size}
@@ -78,7 +78,7 @@ export const All = () => {
>
<SearchField.Button>
<Search />
<span className="sr-only">Søk</span>
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
<SearchField.Input />
</SearchField>
@@ -91,7 +91,7 @@ export const All = () => {
<SearchField.Input />
<SearchField.Button>
<Search />
<span className="sr-only">Søk</span>
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
</SearchField>
<SearchField
@@ -101,7 +101,7 @@ export const All = () => {
>
<SearchField.Button>
<Search />
<span className="sr-only">Søk</span>
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
<SearchField.Clear>
<Close /> Tøm
@@ -120,7 +120,7 @@ export const All = () => {
</SearchField.Clear>
<SearchField.Button>
<Search />
<span className="sr-only">Søk</span>
<span className="navds-sr-only">Søk</span>
</SearchField.Button>
</SearchField>
@@ -6,21 +6,70 @@ import { Switch } from "../index";
# Hvordan ta i bruk Switch
```jsx
<Switch>Slå på feature</Switch>
<Switch>Slå på feature</Switch>
<div>
<Switch position="right">Slå på feature</Switch>
</div>
```
<Canvas>
<Switch>Slå på feature</Switch>
<div>
<Switch position="right">Slå på feature</Switch>
</div>
</Canvas>
## Description
```jsx
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
<div>
<Switch position="right" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
```
<Canvas>
<Switch description="Dette vil gjøre x og y">Slå på feature</Switch>
<div>
<Switch position="right" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
</Canvas>
## Position
Switch kan ha label på høyre eller venstre side. Velges med "Position"-prop "left" | "right". Husk at hvis position
"right" velges, må man selv passe på at den har en definert bredde slik at elementet ikke vises over hele skjermen.
```jsx
<div>
<div>
<h3>Feil</h3>
<Switch position="right">Slå på feature</Switch>
<h3>Riktig</h3>
<div style={{ width: 200 }}>
<Switch position="right">Slå på feature 1</Switch>
<Switch position="right">Slå på feature 2</Switch>
<Switch position="right">Slå på feature 3</Switch>
</div>
</div>
</div>
```
<Canvas>
<div>
<h3>Feil</h3>
<Switch position="right">Slå på feature</Switch>
<h3>Riktig</h3>
<div style={{ width: 300 }}>
<Switch position="right">Slå på feature 1</Switch>
<Switch position="right">Slå på feature 2</Switch>
<Switch position="right">Slå på feature 3</Switch>
</div>
</div>
</Canvas>
## Sizing
@@ -30,6 +79,9 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
```jsx
<Switch size="small" >Slå på feature</Switch>
<Switch size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
<Switch position="right" size="small" >Slå på feature</Switch>
<Switch position="right" size="small" description="Dette vil gjøre x og y">Slå på feature</Switch>
```
<Canvas>
@@ -39,6 +91,14 @@ Switch har default 48px høy klikkflate. Med size="small" blir klikkflaten 32px
Slå på feature
</Switch>
</div>
<div>
<Switch position="right" size="small">
Slå på feature
</Switch>
<Switch position="right" size="small" description="Dette vil gjøre x og y">
Slå på feature
</Switch>
</div>
</Canvas>
## defaultChecked
@@ -58,11 +118,21 @@ Switch er en stylet checkbox, så både `checked` og `defaultChecked` fungerer
Ved bruk av `hideLegend` på Switch kan man gjøre slik at legend/description bare vises for skjermlesere
```jsx
<Switch hideLabel>Slå på feature</Switch>
<div style={{ width: 300 }}>
<Switch hideLabel>Slå på feature</Switch>
<Switch hideLabel position="right">
Slå på feature
</Switch>
</div>
```
<Canvas>
<Switch hideLabel>Slå på feature</Switch>
<div style={{ width: 300 }}>
<Switch hideLabel>Slå på feature</Switch>
<Switch hideLabel position="right">
Slå på feature
</Switch>
</div>
</Canvas>
## Disabled
@@ -9,16 +9,24 @@ export default {
export const All = () => {
const [checked, setChecked] = useState(false);
const [loadingState, setLoadingState] = useState(false);
return (
<div>
<div style={{ width: "fit-content" }}>
<h1>Switch</h1>
<Switch>Label text</Switch>
<Switch position="right">Label text</Switch>
<h2>Switch w/Description</h2>
<Switch>Label text</Switch>
<Switch description="Switch description">Label text</Switch>
<Switch>Label text</Switch>
<Switch position="right">Label text</Switch>
<Switch position="right" description="Switch description">
Label text
</Switch>
<Switch position="right">Label text</Switch>
<h2>hidelabel</h2>
<Switch description="Switch description" hideLabel>
Label text
@@ -29,6 +37,15 @@ export const All = () => {
<Switch hideLabel size="small">
Label text small
</Switch>
<Switch position="right" description="Switch description" hideLabel>
Label text
</Switch>
<Switch position="right" description="Switch description" hideLabel>
Label text
</Switch>
<Switch position="right" hideLabel size="small">
Label text small
</Switch>
<h2>Switch small</h2>
<Switch size="small">Label text</Switch>
@@ -37,6 +54,16 @@ export const All = () => {
</Switch>
<Switch size="small">Label text</Switch>
<Switch position="right" size="small">
Label text
</Switch>
<Switch position="right" description="Switch description" size="small">
Label text
</Switch>
<Switch position="right" size="small">
Label text
</Switch>
<h2>Controlled</h2>
<Switch checked={checked} onChange={() => setChecked(!checked)}>
Label text
@@ -65,6 +92,13 @@ export const All = () => {
<Switch disabled loading>
Label text
</Switch>
<Switch checked loading>
Label text
</Switch>
<button onClick={() => setLoadingState(!loadingState)}>
Toggle loading
</button>
<Switch loading={loadingState}>Label text</Switch>
</div>
);
};
+12 -9
View File
@@ -1,26 +1,28 @@
import { Helptext as HelpTextIcon } from "@navikt/ds-icons";
import { Placement } from "@popperjs/core";
import cl from "classnames";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import mergeRefs from "react-merge-refs";
import { Popover } from "..";
import { Popover, PopoverProps } from "..";
export interface HelpTextProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
Pick<PopoverProps, "strategy" | "placement"> {
/**
* Component content
*/
children: React.ReactNode;
/**
* Placement of popover
* @default "top"
*/
placement?: Placement;
}
const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
(
{ className, children, placement = "top", title = "hjelp", ...rest },
{
className,
children,
placement = "top",
strategy = "absolute",
title = "hjelp",
...rest
},
ref
) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
@@ -64,6 +66,7 @@ const HelpText = forwardRef<HTMLButtonElement, HelpTextProps>(
role="tooltip"
anchorEl={buttonRef.current}
placement={placement}
strategy={strategy}
>
<Popover.Content>{children}</Popover.Content>
</Popover>
+2 -1
View File
@@ -1,5 +1,4 @@
export * from "./accordion";
export * from "./accordion-menu";
export * from "./alert";
export * from "./button";
export * from "./form";
@@ -9,10 +8,12 @@ export * from "./guide-panel";
export * from "./link";
export * from "./link-panel";
export * from "./loader";
export * from "./menu";
export * from "./modal";
export * from "./panel";
export * from "./popover";
export * from "./speech-bubble";
export * from "./step-indicator";
export * from "./tag";
export * from "./table";
export * from "./typography";
@@ -40,10 +40,7 @@ const LinkPanelComponent: OverridableComponent<
className={cl("navds-link-panel", className)}
>
<div className="navds-link-panel__content">{children}</div>
<Next
className="navds-link-panel__chevron"
aria-label="arrow-icon pointing right"
/>
<Next className="navds-link-panel__chevron" aria-hidden />
</Panel>
);
}
@@ -63,25 +63,3 @@ Bakgrunnen kan settes til transparent med `transparent={true}`
<Canvas>
<Loader size="2xlarge" transparent />
</Canvas>
## Bruk av loader i knapper
Husk her å gi brukeren nok informasjon om hvorfor knappen har en Loader. Dette kan gjøres ved å ha god tekst på siden,
i knappen og i `title`-proppen for `Loader`. Unngå også bruk av `Loader` uten noen tekst som hinter til hva som foregår.
Stylingen er overstyrt for knapper, slik at `transparent` ikke fungerer by-default ved bruk i knapper.
Størrelsen justeres også automatisk, slik at alt man trenger er å sette Loaderen rett inn i knappen.
```jsx
<Button>
Laster inn nytt innhold...
<Loader />
</Button>
```
<Canvas>
<Button>
Laster inn nytt innhold...
<Loader />
</Button>
</Canvas>
+36
View File
@@ -0,0 +1,36 @@
import React, { forwardRef } from "react";
import cl from "classnames";
import MenuItems from "./MenuItems";
import Item, { MenuItemType } from "./MenuItem";
import Collapse, { MenuCollapseType } from "./MenuCollapse";
export interface MenuProps extends React.HTMLAttributes<HTMLElement> {
children: React.ReactNode;
}
interface MenuComponent
extends React.ForwardRefExoticComponent<
MenuProps & React.RefAttributes<HTMLElement>
> {
Collapse: MenuCollapseType;
Item: MenuItemType;
}
const Menu = forwardRef<HTMLElement, MenuProps>(
({ children, className, ...rest }, ref) => (
<nav
{...rest}
role="navigation"
ref={ref}
className={cl("navds-menu", className)}
>
<MenuItems>{children}</MenuItems>
</nav>
)
) as MenuComponent;
Menu.Collapse = Collapse;
Menu.Item = Item;
export default Menu;
@@ -0,0 +1,80 @@
import React, {
createContext,
forwardRef,
HTMLAttributes,
useContext,
useState,
} from "react";
import cl from "classnames";
import { Expand, ExpandFilled } from "@navikt/ds-icons";
import MenuItems from "./MenuItems";
export const NestingContext = createContext<{ depth: number }>({ depth: 1 });
const NestingProvider = ({ children }) => {
const context = useContext(NestingContext);
return (
<NestingContext.Provider
value={{
depth: context.depth + 1,
}}
>
{children}
</NestingContext.Provider>
);
};
export interface MenuCollapseProps extends HTMLAttributes<HTMLDivElement> {
title: string;
defaultOpen?: boolean;
children: React.ReactNode;
}
export type MenuCollapseType = React.ForwardRefExoticComponent<
MenuCollapseProps & React.RefAttributes<HTMLDivElement>
>;
const Collapse: MenuCollapseType = forwardRef(
({ children, defaultOpen = false, title, className, ...rest }, ref) => {
const [isOpen, setIsOpen] = useState(defaultOpen);
const context = useContext(NestingContext);
return (
<div
{...rest}
ref={ref}
className={cl("navds-menu-collapse", className, {
"navds-menu-collapse--open": isOpen,
})}
>
<button
onClick={() => setIsOpen(!isOpen)}
className="navds-menu-collapse__button"
>
{title}
<Expand
title={isOpen ? "lukk navigasjons-skuff" : "åpne navigason-skuff"}
className="navds-menu-collapse__expand-icon"
/>
<ExpandFilled
title={isOpen ? "lukk navigasjons-skuff" : "åpne navigason-skuff"}
className="navds-menu-collapse__expand-icon navds-menu-collapse__expand-icon--filled"
/>
</button>
<NestingProvider>
{isOpen && (
<MenuItems
data-depth={context.depth}
className="navds-menu__list--inner"
>
{children}
</MenuItems>
)}
</NestingProvider>
</div>
);
}
);
export default Collapse;
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
import { OverridableComponent } from "..";
import cl from "classnames";
export interface AccordionMenuItemProps
export interface MenuItemProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
children: React.ReactNode;
/**
@@ -12,12 +12,12 @@ export interface AccordionMenuItemProps
active?: boolean;
}
export type AccordionMenuItemType = OverridableComponent<
AccordionMenuItemProps,
export type MenuItemType = OverridableComponent<
MenuItemProps,
HTMLAnchorElement
>;
const Item: AccordionMenuItemType = forwardRef(
const Item: MenuItemType = forwardRef(
(
{ children, as: Component = "a", active = false, className, ...rest },
ref
@@ -25,8 +25,8 @@ const Item: AccordionMenuItemType = forwardRef(
return (
<Component
ref={ref}
className={cl("navds-accordion-menu-item", className, {
"navds-accordion-menu-item--active": active,
className={cl("navds-menu-item", className, {
"navds-menu-item--active": active,
})}
{...rest}
>
+21
View File
@@ -0,0 +1,21 @@
import cl from "classnames";
import React from "react";
const MenuItems = ({
children,
className,
...rest
}: {
children: React.ReactNode;
className?: string;
}) => (
<ul {...rest} className={cl("navds-menu__list", className)}>
{React.Children.toArray(children).map((child, i) => (
<li key={i} className="navds-menu__list-item">
{child}
</li>
))}
</ul>
);
export default MenuItems;
+3
View File
@@ -0,0 +1,3 @@
export { default as Menu, MenuProps } from "./Menu";
export { MenuCollapseProps } from "./MenuCollapse";
export { MenuItemProps } from "./MenuItem";
@@ -0,0 +1,93 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { Menu } from "../../index";
<Meta title="ds-react/menu/intro" />
# Hvordan ta i bruk Menu
```jsx
<Menu>
<Menu.Item href="#leo">Leo</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
<Menu.Collapse title="Accumsan">
<Menu.Item href="#justo" aria-current="page">
Justo
</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla">Nulla</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
</Menu.Collapse>
</Menu>
```
<Canvas>
<Menu>
<Menu.Item href="#leo">Leo</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
<Menu.Collapse title="Accumsan">
<Menu.Item href="#justo">Justo</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla">Nulla</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
</Menu.Collapse>
</Menu>
</Canvas>
## Elementer i menyen
Menyen har to typer elementer man kan bruke: `Collapse` for nesting og `Item` for navigasjonslenker på siden.
<Canvas>
<div>
<h2>Item</h2>
<Menu>
<Menu.Item href="#leo">Lenke</Menu.Item>
<Menu.Item href="#leo">Lenke</Menu.Item>
<Menu.Item href="#leo">Lenke</Menu.Item>
<Menu.Item href="#leo">Lenke</Menu.Item>
<Menu.Item href="#leo">Lenke</Menu.Item>
</Menu>
<h2>Collapses + Item</h2>
<Menu>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
<Menu.Collapse title="Accumsan">
<Menu.Item href="#justo">Justo</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla">Nulla</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
</Menu.Collapse>
<Menu.Item href="#leo">Lenke</Menu.Item>
<Menu.Item href="#leo">Lenke</Menu.Item>
</Menu>
</div>
</Canvas>
`Menu.Item` er implementert med `OverridableComponent`, noe som
gjør at man kan ta i bruk eks react-router slik:
```jsx
<Menu.Item as={NavLink} activeClassName="navds-menu-item--active" to="/1">
Lenketekst
</Menu.Item>
```
Her er `NavLink` fra `react-router-dom` brukt, og man får da
samtidig bruke alle propsene til denne komponenten som da er `activeClassName` her.
@@ -0,0 +1,139 @@
import * as React from "react";
import cl from "classnames";
import { Menu } from "../index";
import { NavLink, HashRouter as Router } from "react-router-dom";
import { MenuItemProps } from "../MenuItem";
export default {
title: "ds-react/menu",
component: { Menu },
};
export const All = () => (
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<h2>Only Menu.Items</h2>
<Menu>
<Menu.Item href="#leo">Leo</Menu.Item>
<Menu.Item href="#justo">Justo</Menu.Item>
<Menu.Item href="#pariatur" active aria-current="page">
Pariatur
</Menu.Item>
<Menu.Item href="#nulla">Nulla</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
<Menu.Item href="#justo">Justo</Menu.Item>
<Menu.Item href="#pariatur">Pariatur</Menu.Item>
</Menu>
<h2>With Collapse</h2>
<Menu>
<Menu.Item href="#leo">Leo</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
<Menu.Collapse title="Accumsan">
<Menu.Item href="#justo" aria-current="page">
Justo
</Menu.Item>
<Menu.Item href="#pariatur" active aria-current="page">
Pariatur
</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Collapse title="Proin">
<Menu.Item href="#nulla" active>
Nulla
</Menu.Item>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
<Menu.Item href="#luctus">Luctus</Menu.Item>
</Menu.Collapse>
</Menu.Collapse>
<Menu.Item href="#justo" active>
Justo
</Menu.Item>
<Menu.Item href="#pariatur">Pariatur</Menu.Item>
</Menu>
</div>
);
export const ReactRouter = () => {
const MenuItemLink = (props: MenuItemProps & { to: string }) => {
const { to } = props;
const CustomLink = React.useMemo(
() => (props: MenuItemProps) => (
<NavLink
{...props}
to={to}
className={({ isActive }) =>
cl(props.className, {
"navds-menu-item--active": isActive,
})
}
/>
),
[to]
);
return (
<Menu.Item {...props} as={CustomLink}>
Nivå 2 innrykk 2 rems
</Menu.Item>
);
};
return (
<Menu>
<Menu.Collapse title="Nivå 1 - 3 rems høy">
<MenuItemLink to="/1">Nivå 2 innrykk 2 rems</MenuItemLink>
<MenuItemLink to="/2">Subtitle 3</MenuItemLink>
</Menu.Collapse>
<Menu.Collapse title="Skjema og søknad">
<Menu.Collapse title="Satser">
<MenuItemLink to="/3">
Nivå 3 - 3 rems innrykk Har du rett til dagpenger når du mottar
annen økonomisk støtte fra NAV?
</MenuItemLink>
</Menu.Collapse>
<MenuItemLink to="/4">Subtitle 2</MenuItemLink>
<MenuItemLink to="/5">Subtitle 3</MenuItemLink>
</Menu.Collapse>
<Menu.Collapse title="Sakbehandlingstider">
<Menu.Collapse title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
<MenuItemLink to="/6">Subtitle 5</MenuItemLink>
</Menu.Collapse>
</Menu.Collapse>
<MenuItemLink to="/7">Internasjonalt</MenuItemLink>
<Menu.Collapse title="Meld fra om endringer lang tittel på første nivå">
<MenuItemLink to="/8">Subtitle 6</MenuItemLink>
</Menu.Collapse>
<MenuItemLink to="/9">Nivå 1</MenuItemLink>
</Menu>
);
};
ReactRouter.decorators = [
(Story) => (
<Router>
<div
style={{
background: "white",
maxWidth: 288,
}}
>
<Story />
</div>
</Router>
),
];
+19 -12
View File
@@ -28,6 +28,11 @@ export interface ModalProps {
* User defined classname for modal
*/
className?: string;
/**
* Toggles addition of a X-button on modal
* @default true
*/
closeButton?: boolean;
}
interface ModalComponent
@@ -50,6 +55,7 @@ const Modal = forwardRef<ReactModal, ModalProps>(
onClose,
className,
shouldCloseOnOverlayClick = true,
closeButton = true,
...rest
},
ref
@@ -77,18 +83,19 @@ const Modal = forwardRef<ReactModal, ModalProps>(
onRequestClose={(e) => onModalCloseRequest(e)}
>
{children}
<Button
className={cl("navds-modal__button", {
"navds-modal__button--shake": shouldCloseOnOverlayClick,
})}
size="small"
variant="secondary"
ref={buttonRef}
aria-label="lukk modalvindu"
onClick={onClose}
>
<Close title="X-ikon for å lukke modal" />
</Button>
{closeButton && (
<Button
className={cl("navds-modal__button", {
"navds-modal__button--shake": shouldCloseOnOverlayClick,
})}
size="small"
variant="tertiary"
ref={buttonRef}
onClick={onClose}
>
<Close title="Lukk modalvindu" />
</Button>
)}
</ReactModal>
);
}
@@ -11,6 +11,7 @@ Modal.setAppElement("#root");
export const All = () => {
const [open, setOpen] = useState(true);
const [openTwo, setOpenTwo] = useState(false);
const [openThree, setOpenThree] = useState(false);
return (
<>
@@ -46,6 +47,21 @@ export const All = () => {
</p>
</Modal.Content>
</Modal>
<button onClick={() => setOpenThree(true)}>
Open modal without x-button
</button>
<Modal
open={openThree}
closeButton={false}
onClose={() => setOpenThree(false)}
>
<Modal.Content>
<h1>Header</h1>
<h2>subheader</h2>
<p>Cupidatat irure ipsum veniam ad in esse.</p>
<p>Cillum tempor pariatur amet ut laborum Lorem enim enim.</p>
</Modal.Content>
</Modal>
</>
);
};
@@ -44,6 +44,12 @@ export interface PopoverProps extends HTMLAttributes<HTMLDivElement> {
* @default 16 w/arrow, 4 w/no-arrow
*/
offset?: number;
/**
* Changes what CSS position property to use
* You want to use "fixed" if reference element is inside a fixed container, but popover is not
* @default "absolute"
*/
strategy?: "absolute" | "fixed";
}
const useEventLister = (event: string, callback) =>
@@ -72,6 +78,7 @@ const Popover = forwardRef<HTMLDivElement, PopoverProps>(
onClose,
placement = "right",
offset,
strategy = "absolute",
...rest
},
ref
@@ -137,6 +144,7 @@ const Popover = forwardRef<HTMLDivElement, PopoverProps>(
},
},
],
strategy,
}
);
@@ -0,0 +1,79 @@
import React, { forwardRef, useContext } from "react";
import cl from "classnames";
import { StepContext } from ".";
import { BodyShort, Label, OverridableComponent } from "..";
export interface StepIndicatorStepProps
extends React.HTMLAttributes<HTMLButtonElement> {
/**
* Text content under indicator
*/
children: React.ReactNode;
/**
* Disables interaction with element
*/
disabled?: boolean;
/**
* Handled by StepIndicator
*/
index?: number;
}
export interface StepIndicatorStepType
extends OverridableComponent<StepIndicatorStepProps, HTMLButtonElement> {}
const StepComponent: OverridableComponent<
StepIndicatorStepProps,
HTMLButtonElement
> = forwardRef(
(
{ className, children, as: Component = "button", disabled, index, ...rest },
ref
) => {
const context = useContext(StepContext);
if (context === null) {
console.error(
"<StepIndicator.Step> has to be used within an <StepIndicator>"
);
return null;
}
const safeIndex = index ?? 0;
const Number = context.activeStep === safeIndex ? Label : BodyShort;
return (
<Component
{...rest}
disabled={disabled}
ref={ref}
className={cl("navds-step-indicator__step", className, {
"navds-step-indicator__step--disabled": disabled,
"navds-step-indicator__step--active":
context.activeStep === safeIndex,
"navds-step-indicator__step--finished":
context.activeStep > safeIndex,
})}
onClick={(e) => {
context.onStepChange(safeIndex);
rest.onClick && rest.onClick(e);
}}
>
<Number className="navds-step-indicator__step-number">
{safeIndex + 1}
</Number>
<div className={cl("navds-step-indicator__step-label")}>
{!context.hideLabels && children}
</div>
{safeIndex !== 0 && (
<span aria-hidden className="navds-step-indicator__step-line" />
)}
</Component>
);
}
);
const Step = StepComponent as StepIndicatorStepType;
export default Step;
@@ -0,0 +1,145 @@
import cl from "classnames";
import React, {
createContext,
forwardRef,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import mergeRefs from "react-merge-refs";
import Step, { StepIndicatorStepProps, StepIndicatorStepType } from "./Step";
export interface StepIndicatorProps
extends React.HTMLAttributes<HTMLOListElement> {
/**
* <StepIndicator.Step /> elements
*/
children: React.ReactNode;
/**
* Adds classname to wrapper
*/
className?: string;
/**
* Current active step index
*/
activeStep: number;
/**
* Callback for clicked step index
*/
onStepChange?: (step: number) => void;
/**
* Hides labels for each step if true
* @default false
*/
hideLabels?: boolean;
/**
* enables `hideLabels` internally when steps start to overflow.
* @note declaring `hideLabels` overwrites this functionality
*/
responsive?: boolean;
}
interface StepIndicatorComponent
extends React.ForwardRefExoticComponent<
StepIndicatorProps & React.RefAttributes<HTMLOListElement>
> {
Step: StepIndicatorStepType;
}
interface StepContextProps {
activeStep: number;
onStepChange: (step: number) => void;
hideLabels: boolean;
}
export const StepContext = createContext<StepContextProps | null>(null);
const StepIndicator: StepIndicatorComponent = forwardRef<
HTMLOListElement,
StepIndicatorProps
>(
(
{
children,
className,
activeStep,
hideLabels,
onStepChange = () => {},
responsive,
...rest
},
ref
) => {
const wrapperRef = useRef<HTMLOListElement | null>(null);
const mergedRef = mergeRefs([wrapperRef, ref]);
const [showLabels, setShowLabels] = useState(true);
const removeLabels = hideLabels ?? (!!responsive && !showLabels);
const stepsWithIndex = React.Children.map(children, (step, index) => {
return React.isValidElement<StepIndicatorStepProps>(step) ? (
<li
className={cl("navds-step-indicator__step-wrapper", {
"navds-step-indicator__step-wrapper--hidelabel": removeLabels,
})}
key={index}
aria-current={index === activeStep && "step"}
>
{React.cloneElement(step, {
...step.props,
index,
})}
</li>
) : (
step
);
});
const canShowLabels = useCallback(() => {
const remSize = parseFloat(
String(getComputedStyle(document.documentElement).fontSize)
);
const childrenLength = React.Children.toArray(children).filter((child) =>
React.isValidElement(child)
).length;
wrapperRef.current &&
setShowLabels(
wrapperRef.current?.getBoundingClientRect().width >=
remSize * 10 * childrenLength
);
}, [children]);
useEffect(() => {
window.addEventListener("resize", canShowLabels);
canShowLabels();
return () => {
window.removeEventListener("resize", canShowLabels);
};
}, [canShowLabels]);
return (
<ol
ref={mergedRef}
className={cl(`navds-step-indicator`, className)}
{...rest}
>
<StepContext.Provider
value={{
activeStep,
onStepChange,
hideLabels: removeLabels,
}}
>
{stepsWithIndex}
</StepContext.Provider>
</ol>
);
}
) as StepIndicatorComponent;
StepIndicator.Step = Step;
export default StepIndicator;
@@ -0,0 +1,2 @@
export { default as StepIndicator } from "./StepIndicator";
export * from "./StepIndicator";
@@ -0,0 +1,23 @@
import React, { useState } from "react";
import { StepIndicator } from "..";
export const Example = ({ ...props }) => {
const [active, setactive] = useState(1);
const { disabled, ...rest } = props;
return (
<StepIndicator {...rest} activeStep={active} onStepChange={setactive}>
<StepIndicator.Step>Start</StepIndicator.Step>
<StepIndicator.Step>
Sunt deserunt qui sit sunt culpa nisi
</StepIndicator.Step>
<StepIndicator.Step disabled={disabled}>
Nulla nisi pariatur nulla cupidatat elit.
</StepIndicator.Step>
<StepIndicator.Step>
Nulla laborum proident consequat laborum elit et dolore ut sunt.
</StepIndicator.Step>
</StepIndicator>
);
};
@@ -0,0 +1,122 @@
import { Meta, Canvas } from "@storybook/addon-docs";
import { StepIndicator } from "..";
import { Example } from "./Example";
<Meta title="ds-react/step-indicator/intro" />
# Hvordan ta i bruk StepIndicator
Vi flytter over Stegindikator til `ds-react` uten noen veldig store endringer i design.
Du må nå selv styre state med `activeStep` og `onStepChange`.
```jsx
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
<StepIndicator.Step>Start</StepIndicator.Step>
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
<StepIndicator.Step>
Nulla nisi pariatur nulla cupidatat elit.
</StepIndicator.Step>
<StepIndicator.Step>
Nulla laborum proident consequat laborum elit et dolore ut sunt.
</StepIndicator.Step>
</StepIndicator>
```
<Canvas>
<Example />
</Canvas>
## responsive
Bruk `responsive`-prop for å skjule labels med en gang StepIndicator begynner å overlfowe.
```jsx
<StepIndicator
responsive
activeStep={activeStep}
onStepChange={(x) => setActiveStep(x)}
>
<StepIndicator.Step>Start</StepIndicator.Step>
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
<StepIndicator.Step>
Nulla nisi pariatur nulla cupidatat elit.
</StepIndicator.Step>
<StepIndicator.Step>
Nulla laborum proident consequat laborum elit et dolore ut sunt.
</StepIndicator.Step>
</StepIndicator>
```
<Canvas>
<Example responsive />
</Canvas>
## hideLabels
Du kan gjemme labels fra hvert steg med `hideLabels`-prop
```jsx
<StepIndicator
hideLabels
activeStep={activeStep}
onStepChange={(x) => setActiveStep(x)}
>
<StepIndicator.Step>Start</StepIndicator.Step>
<StepIndicator.Step>Sunt deserunt qui sit sunt culpa nisi</StepIndicator.Step>
<StepIndicator.Step>
Nulla nisi pariatur nulla cupidatat elit.
</StepIndicator.Step>
<StepIndicator.Step>
Nulla laborum proident consequat laborum elit et dolore ut sunt.
</StepIndicator.Step>
</StepIndicator>
```
<Canvas>
<Example hideLabels />
</Canvas>
## disabled
```jsx
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
<StepIndicator.Step>Start</StepIndicator.Step>
<StepIndicator.Step disabled>
Sunt deserunt qui sit sunt culpa nisi
</StepIndicator.Step>
<StepIndicator.Step disabled>
Nulla nisi pariatur nulla cupidatat elit.
</StepIndicator.Step>
<StepIndicator.Step>
Nulla laborum proident consequat laborum elit et dolore ut sunt.
</StepIndicator.Step>
</StepIndicator>
```
<Canvas>
<Example disabled />
</Canvas>
## Override tags
`StepIndicator.Step` er implementert med Overridable-component noe som gjør at du kan endre taggen til
det du selv ønsker ved å bruke `as`-prop
```jsx
<StepIndicator activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
{/* Dette er default */}
<StepIndicator.Step as="button">Start</StepIndicator.Step>
<StepIndicator.Step as="a" href="#">
Sunt deserunt qui sit sunt culpa nisi
</StepIndicator.Step>
</StepIndicator>
```
<Canvas>
<StepIndicator activeStep={1} onStepChange={console.log}>
<StepIndicator.Step as="button">{`<button>`}</StepIndicator.Step>
<StepIndicator.Step as="a" href="#">
{`<a>`}
</StepIndicator.Step>
</StepIndicator>
</Canvas>
@@ -0,0 +1,104 @@
import React, { useState } from "react";
import StepIndicator from "../StepIndicator";
import { Meta } from "@storybook/react/types-6-0";
import { Link, HashRouter as Router, useLocation } from "react-router-dom";
export default {
title: "ds-react/step-indicator",
component: StepIndicator,
} as Meta;
export const All = () => {
const [activeStep, setActiveStep] = useState(1);
return (
<div>
<StepIndicator activeStep={1} onStepChange={console.log}>
<StepIndicator.Step>Steg nr 1</StepIndicator.Step>
<StepIndicator.Step>Laborum velit eu magna esse</StepIndicator.Step>
<StepIndicator.Step>test</StepIndicator.Step>
</StepIndicator>
<br />
<StepIndicator activeStep={1} onStepChange={console.log}>
<StepIndicator.Step href="#" as="a">
1
</StepIndicator.Step>
<StepIndicator.Step href="#" as="a">
2
</StepIndicator.Step>
<StepIndicator.Step href="#" as="a">
3
</StepIndicator.Step>
</StepIndicator>
<br />
<StepIndicator activeStep={activeStep} onStepChange={setActiveStep}>
<StepIndicator.Step disabled>
Pariatur pariatur adipisicing reprehenderit ad occaecat reprehenderit
ut dolore.
</StepIndicator.Step>
<StepIndicator.Step>Laborum velit eu magna esse</StepIndicator.Step>
<StepIndicator.Step disabled>
Cupidatat Lorem do nostrud ut eu.
</StepIndicator.Step>
<StepIndicator.Step>test</StepIndicator.Step>
<StepIndicator.Step>
Voluptate pariatur ut est voluptate elit officia excepteur laborum.
</StepIndicator.Step>
</StepIndicator>
<br />
<StepIndicator
activeStep={activeStep}
onStepChange={setActiveStep}
hideLabels
>
<StepIndicator.Step>
Pariatur pariatur adipisicing reprehenderit ad occaecat reprehenderit
ut dolore.
</StepIndicator.Step>
<StepIndicator.Step>Laborum velit eu magna esse</StepIndicator.Step>
<StepIndicator.Step disabled>
Cupidatat Lorem do nostrud ut eu.
</StepIndicator.Step>
<StepIndicator.Step>test</StepIndicator.Step>
<StepIndicator.Step>
Voluptate pariatur ut est voluptate elit officia excepteur laborum.
</StepIndicator.Step>
</StepIndicator>
</div>
);
};
export const ReactRouter = () => {
const { pathname } = useLocation();
return (
<StepIndicator
activeStep={
{
"/": 0,
"/first": 0,
"/second": 1,
"/third": 2,
}[pathname]
}
>
<StepIndicator.Step as={Link} to="/first">
Steg nr 1
</StepIndicator.Step>
<StepIndicator.Step as={Link} to="/second">
Laborum velit eu magna esse
</StepIndicator.Step>
<StepIndicator.Step as={Link} to="/third">
test
</StepIndicator.Step>
</StepIndicator>
);
};
ReactRouter.decorators = [
(Story) => (
<Router>
<Story />
</Router>
),
];
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "0.7.0",
"version": "0.8.0",
"private": false,
"description": "Auto-generated design-tokens for NAV design-systems framework",
"author": "NAV Designsystem team",
@@ -30,6 +30,7 @@
},
"devDependencies": {
"@types/jest": "^27.0.1",
"axios": "^0.21.3",
"dotenv": "^10.0.0",
"figma-api": "^1.7.0",
"jest": "^27.2.0",
+13 -4
View File
@@ -74,16 +74,25 @@
"value": "rgba(241, 241, 241, 1)"
},
"200": {
"value": "rgba(201, 201, 201, 1)"
"value": "rgba(229, 229, 229, 1)"
},
"300": {
"value": "rgba(207, 207, 207, 1)"
},
"400": {
"value": "rgba(160, 160, 160, 1)"
"value": "rgba(176, 176, 176, 1)"
},
"500": {
"value": "rgba(143, 143, 143, 1)"
},
"600": {
"value": "rgba(106, 106, 106, 1)"
"value": "rgba(112, 112, 112, 1)"
},
"700": {
"value": "rgba(89, 89, 89, 1)"
},
"800": {
"value": "rgba(79, 79, 79, 1)"
"value": "rgba(64, 64, 64, 1)"
},
"900": {
"value": "rgba(38, 38, 38, 1)"
+6
View File
@@ -66,3 +66,9 @@
outline: none;
box-shadow: inset 0 0 0 2px var(--navds-dropdown-item-color-focus);
}
.navdsi-dropdown__item:disabled {
opacity: 0.3;
background: transparent;
cursor: not-allowed;
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "0.7.0",
"version": "0.7.1",
"private": false,
"description": "Css for NAV internal Designsystem components",
"author": "NAV Designsystem team",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "0.9.3",
"version": "0.10.2",
"private": false,
"description": "NAV internal designsystem react components",
"author": "NAV Designsystem team",
@@ -33,8 +33,8 @@
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^0.7.1",
"@navikt/ds-react": "^0.14.3",
"@navikt/ds-icons": "^0.8.1",
"@navikt/ds-react": "^0.15.2",
"@popperjs/core": "^2.10.1",
"classnames": "^2.3.1",
"copy-to-clipboard": "^3.3.1",
@@ -7,7 +7,7 @@ import { Success } from "@navikt/ds-react";
# Hvordan ta i bruk CopyToClipboard
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
brukes i popover. Hvis komponenten ikke har noen children (tekst i button) vil da en "navds-sr-only" tekst bli
lagt på knappen med tekst "Kopier copyText"
```jsx
@@ -27,6 +27,7 @@ export const All = () => (
<Dropdown.Menu.List>
<Dropdown.Menu.List.Item>Gosys</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item>Psys</Dropdown.Menu.List.Item>
<Dropdown.Menu.List.Item disabled>Infotrygd</Dropdown.Menu.List.Item>
</Dropdown.Menu.List>
</Dropdown.Menu>
</Dropdown>
Loaded 100 of 723 files, more files were not shown because too many files have changed in this diff. Show more