mirror of
https://github.com/navikt/aksel.git
synced 2026-10-15 18:22:02 +00:00
Compare commits
67
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
041c662737 | ||
|
|
f8c59d7bc1 | ||
|
|
f0dccb0a83 | ||
|
|
11f23ef579 | ||
|
|
ebb7be678f | ||
|
|
588d485841 | ||
|
|
f4ec864c5d | ||
|
|
c91131c29c | ||
|
|
d8e18812ff | ||
|
|
d40f624edb | ||
|
|
1cfd79fdb8 | ||
|
|
9dabc6386d | ||
|
|
ac6215408d | ||
|
|
6e4e0bde93 | ||
|
|
dcf0ecc9a6 | ||
|
|
2b1cc85517 | ||
|
|
1053ca7dca | ||
|
|
25c186473b | ||
|
|
7ea6c9c0f1 | ||
|
|
a6014bb409 | ||
|
|
f60ff3a8c9 | ||
|
|
8d8425acfb | ||
|
|
ce086d890f | ||
|
|
5e9ef5fbd3 | ||
|
|
21958012a2 | ||
|
|
fa0307ec15 | ||
|
|
69c32e4036 | ||
|
|
9a9e265831 | ||
|
|
fb37c6135f | ||
|
|
09259ef960 | ||
|
|
2b0753e4a6 | ||
|
|
471e9b19ee | ||
|
|
86b7b8e406 | ||
|
|
563942947d | ||
|
|
c9adb83158 | ||
|
|
bf079796f3 | ||
|
|
a1f4f0fe28 | ||
|
|
f146c0c57c | ||
|
|
fd397b03e5 | ||
|
|
2a66f1ec6e | ||
|
|
2853e5cd94 | ||
|
|
8a068e787d | ||
|
|
f8fbf6c3a8 | ||
|
|
6da78d13a3 | ||
|
|
bc7ff31a29 | ||
|
|
b82afbe806 | ||
|
|
92425cdb5b | ||
|
|
12cca3e352 | ||
|
|
396bcfbb8a | ||
|
|
0a364b989a | ||
|
|
233cf0cb31 | ||
|
|
b3d1c8429a | ||
|
|
1b66630b08 | ||
|
|
a3640b4ad1 | ||
|
|
c9092c951e | ||
|
|
5761ee7213 | ||
|
|
6239d40d9c | ||
|
|
4081131e1a | ||
|
|
a0797cbf70 | ||
|
|
8f0c6948c3 | ||
|
|
9dd22c2201 | ||
|
|
47f174edee | ||
|
|
00ccebf826 | ||
|
|
ca3d011b54 | ||
|
|
da11faf790 | ||
|
|
41022fb3ab | ||
|
|
81a79de789 |
No files matched your search
@@ -11,7 +11,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test-build:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -27,10 +27,10 @@ jobs:
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Install deps
|
||||
- name: install
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
run: yarn install
|
||||
- name: Gulp-build
|
||||
- name: Boot
|
||||
run: yarn boot
|
||||
- name: Eslint and Stylelint
|
||||
run: yarn lint
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
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
|
||||
- name: Test gatsby-build (design.nav.no)
|
||||
run: yarn build:gatsby
|
||||
- name: Test chromatic
|
||||
uses: chromaui/action@v1
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
exitZeroOnChanges: true
|
||||
|
||||
publish-npm:
|
||||
needs: build
|
||||
needs: test-build
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
steps:
|
||||
@@ -66,20 +66,42 @@ jobs:
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Install deps
|
||||
- name: install
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Gulp-build
|
||||
- name: Boot
|
||||
run: yarn boot
|
||||
- run: git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
- run: git config --global user.name "github-actions[bot]"
|
||||
- run: git remote set-url origin https://github-actions[bot]:$NAV_DS_TOKEN@github.com/$GITHUB_REPOSITORY.git
|
||||
- name: Setup github connection for auth
|
||||
run: |
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git remote set-url origin https://github-actions[bot]:$NAV_DS_TOKEN@github.com/$GITHUB_REPOSITORY.git
|
||||
env:
|
||||
NAV_DS_TOKEN: ${{secrets.GIT_REPO}}
|
||||
- run: yarn lerna version patch --include-merged-tags --yes
|
||||
- run: yarn lerna publish from-package --yes
|
||||
- name: Update all package-versions with patch
|
||||
run: yarn lerna version patch --include-merged-tags --yes
|
||||
|
||||
- name: Create a .npmrc file for NPM
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
|
||||
npm whoami
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTOMATION}}
|
||||
NPM_TOKEN: ${{secrets.NPM_AUTOMATION}}
|
||||
- name: Publish to NPM registry
|
||||
run: |
|
||||
yarn lerna publish from-package --yes
|
||||
rm .npmrc
|
||||
- name: Create a .npmrc file for the github package repository
|
||||
uses: FerLuisxd/create-npmrc@3
|
||||
with:
|
||||
org_name: navikt
|
||||
env:
|
||||
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: publish-npm
|
||||
@@ -122,7 +144,7 @@ jobs:
|
||||
env:
|
||||
NAV_DS_TOKEN: ${{secrets.GIT_REPO}}
|
||||
|
||||
- name: Deploy storybook
|
||||
- name: Deploy storybook to designsystem-repo
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
personal_token: ${{secrets.GIT_REPO}}
|
||||
|
||||
@@ -41,6 +41,7 @@ typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
.npmrc
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
@@ -10,7 +10,6 @@ module.exports = {
|
||||
"../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)",
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-docs",
|
||||
{
|
||||
name: "@storybook/addon-storysource",
|
||||
@@ -27,6 +26,5 @@ module.exports = {
|
||||
controls: { hideNoControlsWarning: true },
|
||||
},
|
||||
},
|
||||
"@whitespace/storybook-addon-html",
|
||||
],
|
||||
};
|
||||
@@ -11,7 +11,7 @@ yarn add @navikt/ds-react @navikt/ds-css
|
||||
```
|
||||
|
||||
Siden stilene ikke importeres direkte i komponentene, så må man selv importere ds-css.
|
||||
Dette gjøres for å la komponetene brukes i Nextjs prosjekter.
|
||||
For å legge til all stylingen som trengs må man da bare importere `ds-css`.
|
||||
|
||||
```bash
|
||||
import "@navikt/ds-css"
|
||||
@@ -19,15 +19,4 @@ import "@navikt/ds-css"
|
||||
|
||||
Dette vil også legge css-variabler på :root. For å få dette til å fungere med IE11, kan denne pakken tas i bruk: https://jhildenbiddle.github.io/css-vars-ponyfill/#/
|
||||
|
||||
## Testing
|
||||
|
||||
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
|
||||
|
||||
```bash
|
||||
"moduleNameMapper": {
|
||||
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
|
||||
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
|
||||
}
|
||||
```
|
||||
|
||||
Dette vil remappe komponentene (og ikonpakken) til å bruke CommonJs versjonen for testing
|
||||
Note: Disse komponentene kan ikke garanteres at fungerer som forventet i IE11 da vi har valgt og ikke unngå styling-valg basert på IE11 støtte eller ikke.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Designsystem v2
|
||||
|
||||
Storybook: https://navikt.github.io/Designsystemet/
|
||||
@@ -1,8 +0,0 @@
|
||||
.navds-accordion-anchor-menu {
|
||||
padding: var(--navds-spacing-4) 0;
|
||||
}
|
||||
|
||||
.navds-accordion-anchor-menu__title {
|
||||
margin-left: var(--navds-spacing-4);
|
||||
margin-right: var(--navds-spacing-4);
|
||||
}
|
||||
@@ -83,7 +83,7 @@
|
||||
}
|
||||
|
||||
.navds-checkbox__input:checked + .navds-checkbox__label::before {
|
||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMyAxMCI+ICAgIDxnPiAgICA8cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNNCwxMGMtMC40LDAtMC44LTAuMS0xLjEtMC40TDAuNCw3LjFDMC4xLDYuOCwwLDYuNCwwLDZzMC4yLTAuOCwwLjUtMS4xQzEsNC40LDIsNC40LDIuNSw0LjlMNCw2LjRsNi40LTYgICAgQzEwLjgsMC4xLDExLjEsMCwxMS41LDBjMC40LDAsMC44LDAuMiwxLDAuNWMwLjYsMC42LDAuNSwxLjYtMC4xLDIuMXYwTDUsOS42QzQuNyw5LjksNC40LDEwLDQsMTB6IE0xMS44LDEuOUwxMS44LDEuOSAgICBDMTEuOCwxLjksMTEuOCwxLjksMTEuOCwxLjl6IE0xMS4yLDEuMUMxMS4yLDEuMSwxMS4yLDEuMSwxMS4yLDEuMUwxMS4yLDEuMXoiLz4gICAgPC9nPjwvc3ZnPg==);
|
||||
background-image: var(--navds-checkmark-image-white);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 75%;
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
.navds-checkbox__input:checked:focus + .navds-checkbox__label::before {
|
||||
background-color: white;
|
||||
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMyAxMCI+ICAgIDxnPiAgICA8cGF0aCBmaWxsPSIjMDA2N0M1IiBkPSJNNCwxMGMtMC40LDAtMC44LTAuMS0xLjEtMC40TDAuNCw3LjFDMC4xLDYuOCwwLDYuNCwwLDZzMC4yLTAuOCwwLjUtMS4xQzEsNC40LDIsNC40LDIuNSw0LjlMNCw2LjRsNi40LTYgICAgQzEwLjgsMC4xLDExLjEsMCwxMS41LDBjMC40LDAsMC44LDAuMiwxLDAuNWMwLjYsMC42LDAuNSwxLjYtMC4xLDIuMXYwTDUsOS42QzQuNyw5LjksNC40LDEwLDQsMTB6IE0xMS44LDEuOUwxMS44LDEuOSAgICBDMTEuOCwxLjksMTEuOCwxLjksMTEuOCwxLjl6IE0xMS4yLDEuMUMxMS4yLDEuMSwxMS4yLDEuMSwxMS4yLDEuMUwxMS4yLDEuMXoiLz4gICAgPC9nPjwvc3ZnPg==);
|
||||
background-image: var(--navds-checkmark-image-blue);
|
||||
}
|
||||
|
||||
.navds-checkbox--error
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
.navds-confirmation-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--navds-spacing-4);
|
||||
padding: var(--navds-spacing-4);
|
||||
border-radius: 4px;
|
||||
background-color: #ffeccc;
|
||||
transition: background-color linear 100ms;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel__content {
|
||||
max-width: 80ch;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--s {
|
||||
padding: var(--navds-spacing-3);
|
||||
gap: var(--navds-spacing-2);
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked {
|
||||
background-color: #ccf1d6;
|
||||
border-color: #ccf1d6;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--error {
|
||||
background-color: var(--navds-color-error-background);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel
|
||||
.navds-checkbox__input:hover
|
||||
+ .navds-checkbox__label {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked
|
||||
.navds-checkbox__input:hover
|
||||
+ .navds-checkbox__label {
|
||||
color: var(--navds-color-darkgray);
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked
|
||||
.navds-checkbox__input
|
||||
+ .navds-checkbox__label::before {
|
||||
transition: none;
|
||||
background-color: var(--navds-color-green-50);
|
||||
border-color: var(--navds-color-green-50);
|
||||
background-image: var(--navds-checkmark-image-white);
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked
|
||||
.navds-checkbox__input:hover
|
||||
+ .navds-checkbox__label::before {
|
||||
background-color: var(--navds-color-green-70);
|
||||
border-color: var(--navds-color-green-70);
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked
|
||||
.navds-checkbox__input:focus:hover
|
||||
+ .navds-checkbox__label::before {
|
||||
background-image: var(--navds-checkmark-image-white);
|
||||
}
|
||||
@@ -12,3 +12,8 @@
|
||||
.navds-fieldset--s > :not(:first-child):not(:empty) {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Applied when hideLegend is applied to fieldset */
|
||||
.navds-fieldset > .sr-only + :not(:first-child):not(:empty) {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -7,3 +7,9 @@
|
||||
.navds-form-field--s > input:not(:first-child) {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Applied when hideLabel is applied to form-element */
|
||||
.navds-form-field > .sr-only + :not(:first-child):not(:empty),
|
||||
.navds-form-field > .sr-only + input:not(:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -6,9 +6,11 @@
|
||||
@import "error-summary.css";
|
||||
@import "checkbox.css";
|
||||
@import "checkbox-group.css";
|
||||
@import "confirmation-panel.css";
|
||||
@import "error-message.css";
|
||||
@import "radio.css";
|
||||
@import "radio-group.css";
|
||||
@import "select.css";
|
||||
@import "text-field.css";
|
||||
@import "textarea.css";
|
||||
@import "search-field.css";
|
||||
@@ -0,0 +1,32 @@
|
||||
.navds-search-field__input-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.navds-form-field--s .navds-search-field__input {
|
||||
padding: 0.25rem;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.navds-search-field__input-wrapper > *:not(:first-child):not(:last-child) {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.navds-search-field__input-wrapper > :first-child {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.navds-search-field__input-wrapper > :last-child {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.navds-search-field__input-wrapper :focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.navds-search-field--error
|
||||
.navds-search-field__input:not(:hover):not(:focus):not(:disabled) {
|
||||
box-shadow: 0 0 0 1px var(--navds-color-red-50) inset;
|
||||
border-color: var(--navds-color-red-50);
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
@import "baseline/baseline.css";
|
||||
@import "typography.css";
|
||||
@import "grid.css";
|
||||
@import "layouts.css";
|
||||
|
||||
@import "accordion.css";
|
||||
@import "accordion-anchor-menu.css";
|
||||
@import "accordion-menu.css";
|
||||
@import "alert.css";
|
||||
@import "button.css";
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
/*****************
|
||||
* .navds-layout *
|
||||
*****************/
|
||||
|
||||
.navds-layout__container {
|
||||
display: grid;
|
||||
grid-gap: var(--navds-grid-gutter-small);
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns,
|
||||
.navds-layout__container--2-columns {
|
||||
max-width: 60rem;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns {
|
||||
max-width: 79.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section--white > * {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.navds-layout__section--padding > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__section > *:not(:last-child) {
|
||||
margin-bottom: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__section--left,
|
||||
.navds-layout__section--main,
|
||||
.navds-layout__section--right {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section > *:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--left > *,
|
||||
.navds-layout__section--padding.navds-layout__section--main > *,
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns > .navds-layout__section--left.navds-layout__section--sticky {
|
||||
/* TEMP Solution until dekratøren has updated */
|
||||
--navds-sidebar-sticky-offset: var(--decorator-sticky-offset);
|
||||
|
||||
top: calc(
|
||||
var(--navds-grid-gutter-small) + var(--navds-sidebar-sticky-offset)
|
||||
);
|
||||
position: sticky;
|
||||
max-height: calc(
|
||||
100vh - var(--navds-grid-gutter-small) * 2 -
|
||||
var(--navds-sidebar-sticky-offset)
|
||||
);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns > .navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 10;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--left,
|
||||
.navds-layout__container--2-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 2;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-column: span 4;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left.navds-layout__section--sticky {
|
||||
/* TEMP Solution until dekratøren has updated */
|
||||
--navds-sidebar-sticky-offset: var(--decorator-sticky-offset);
|
||||
|
||||
top: calc(
|
||||
var(--navds-grid-gutter-small) + var(--navds-sidebar-sticky-offset)
|
||||
);
|
||||
position: sticky;
|
||||
max-height: calc(
|
||||
100vh - var(--navds-grid-gutter-small) * 2 -
|
||||
var(--navds-sidebar-sticky-offset)
|
||||
);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 6;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__header *
|
||||
************************/
|
||||
|
||||
.navds-layout__header {
|
||||
background: var(--navds-layout-background-white);
|
||||
}
|
||||
|
||||
.navds-layout__header-content {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
.navds-layout__header-title {
|
||||
margin: var(--navds-spacing-1) var(--navds-spacing-3);
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__header-title {
|
||||
margin: var(--navds-spacing-1) 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__body *
|
||||
************************/
|
||||
|
||||
.navds-layout__body {
|
||||
background: var(--navds-layout-background-gray);
|
||||
scroll-margin-block: 2rem;
|
||||
}
|
||||
|
||||
.navds-layout__body--white {
|
||||
background: var(--navds-layout-background-white);
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
.navds-layout__body--2-columns.navds-layout__body--padding {
|
||||
padding-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navds-layout__body--3-columns.navds-layout__body--padding {
|
||||
padding-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__panel *
|
||||
************************/
|
||||
|
||||
.navds-layout__panel {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: var(--navds-layout-padding-small);
|
||||
background: white;
|
||||
padding-top: 2.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel--icon-margin {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-small);
|
||||
}
|
||||
|
||||
.navds-layout__panel--highlight {
|
||||
box-shadow: rgb(102, 164, 220) 0 0 0 0.15rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-content {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-icon {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
top: -2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel-icon svg,
|
||||
.navds-layout__panel-icon img {
|
||||
background: #c7dbed;
|
||||
border-radius: 2rem;
|
||||
padding: 1rem;
|
||||
height: 4rem;
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-title {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy + .navds-copy-to-clipboard__popover {
|
||||
background-color: var(--navds-color-gray-90);
|
||||
color: var(--navds-color-white);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.navds-layout__panel-popover-content {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy-anchor:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.navds-layout__panel-anchor {
|
||||
position: relative;
|
||||
top: -2.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-anchor--child {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.navds-layout__panel-anchor--child--icon {
|
||||
position: absolute;
|
||||
margin-top: -2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__panel {
|
||||
padding: var(--navds-layout-padding-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__panel:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 448px) and (max-width: 959px) {
|
||||
.navds-layout__section .navds-accordion-anchor-menu__title {
|
||||
margin-left: 2.5rem;
|
||||
margin-right: 2.5rem;
|
||||
}
|
||||
.navds-layout__section .navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 3.5rem;
|
||||
padding-right: 3.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 4.5rem;
|
||||
padding-right: 4.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns .navds-layout__panel--icon-margin:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--3-columns .navds-layout__panel--icon-margin:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel--icon-margin:not(:first-child) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,12 @@
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.navds-alert--error .navds-link,
|
||||
.navds-alert--info .navds-link,
|
||||
.navds-confirmation-panel--error .navds-link {
|
||||
color: var(--navds-color-text-primary);
|
||||
}
|
||||
|
||||
.navds-link:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
|
||||
.navds-modal {
|
||||
background-color: var(--navds-color-background);
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: var(--navds-spacing-4);
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
max-height: 100%;
|
||||
z-index: var(--navds-z-index-modal-content);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.navds-modal:focus,
|
||||
@@ -30,6 +28,9 @@
|
||||
right: 0;
|
||||
background-color: var(--navds-color-modal-overlay);
|
||||
padding: var(--navds-spacing-4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.navds-modal__button--shake {
|
||||
@@ -44,7 +45,7 @@
|
||||
}
|
||||
|
||||
.navds-modal__button {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
top: var(--navds-spacing-4);
|
||||
right: var(--navds-spacing-4);
|
||||
display: flex;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "0.6.17",
|
||||
"version": "0.7.3",
|
||||
"private": false,
|
||||
"description": "Css for NAV Designsystem components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -21,7 +21,7 @@
|
||||
"watch-css": "postcss -w --use postcss-import -o dist/index.css index.css"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^0.4.3",
|
||||
"@navikt/ds-tokens": "^0.4.4",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.2.7",
|
||||
"postcss-cli": "^8.3.1",
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"main": "index.js",
|
||||
"typings": "../esm/index.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -11,7 +11,7 @@
|
||||
"name": "AddCircle",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.784Z",
|
||||
"updated_at": "2021-04-09T13:32:16.308Z",
|
||||
"updated_at": "2021-08-12T11:15:52.168Z",
|
||||
"pageName": "Interface",
|
||||
"visible": true
|
||||
},
|
||||
@@ -32,18 +32,18 @@
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "AddPeople",
|
||||
"name": "AddPerson",
|
||||
"description": "",
|
||||
"created_at": "2021-06-15T15:06:55.651Z",
|
||||
"updated_at": "2021-06-15T15:06:55.651Z",
|
||||
"updated_at": "2021-08-13T06:33:04.695Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "AddPeopleFilled",
|
||||
"name": "AddPersonFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-06-15T15:06:55.654Z",
|
||||
"updated_at": "2021-06-15T15:06:55.654Z",
|
||||
"updated_at": "2021-08-13T06:33:04.683Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
@@ -107,7 +107,7 @@
|
||||
"name": "Back",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.840Z",
|
||||
"updated_at": "2021-04-09T13:32:23.607Z",
|
||||
"updated_at": "2021-08-12T14:51:21.441Z",
|
||||
"pageName": "Chevron",
|
||||
"visible": true
|
||||
},
|
||||
@@ -123,7 +123,7 @@
|
||||
"name": "Bag",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.673Z",
|
||||
"updated_at": "2021-06-14T07:21:59.055Z",
|
||||
"updated_at": "2021-08-13T09:47:23.613Z",
|
||||
"pageName": "Jobs",
|
||||
"visible": true
|
||||
},
|
||||
@@ -203,7 +203,7 @@
|
||||
"name": "Bookmark",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.877Z",
|
||||
"updated_at": "2021-04-09T13:32:23.611Z",
|
||||
"updated_at": "2021-08-12T12:32:34.047Z",
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
@@ -251,7 +251,7 @@
|
||||
"name": "Calculator",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.917Z",
|
||||
"updated_at": "2021-06-14T07:21:59.043Z",
|
||||
"updated_at": "2021-08-12T12:31:15.652Z",
|
||||
"pageName": "Money",
|
||||
"visible": true
|
||||
},
|
||||
@@ -395,7 +395,7 @@
|
||||
"name": "Clock",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.647Z",
|
||||
"updated_at": "2021-04-09T13:32:23.334Z",
|
||||
"updated_at": "2021-08-13T07:30:12.128Z",
|
||||
"pageName": "Time",
|
||||
"visible": true
|
||||
},
|
||||
@@ -411,7 +411,7 @@
|
||||
"name": "Close",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.827Z",
|
||||
"updated_at": "2021-04-09T13:32:16.911Z",
|
||||
"updated_at": "2021-08-12T13:19:34.922Z",
|
||||
"pageName": "Interface",
|
||||
"visible": true
|
||||
},
|
||||
@@ -419,7 +419,7 @@
|
||||
"name": "CloseFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.364Z",
|
||||
"updated_at": "2021-04-09T13:32:16.624Z",
|
||||
"updated_at": "2021-08-12T10:54:40.891Z",
|
||||
"pageName": "Interface",
|
||||
"visible": true
|
||||
},
|
||||
@@ -427,7 +427,7 @@
|
||||
"name": "CoApplicant",
|
||||
"description": "",
|
||||
"created_at": "2021-04-30T10:55:32.823Z",
|
||||
"updated_at": "2021-04-30T10:55:32.823Z",
|
||||
"updated_at": "2021-08-13T09:47:48.809Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
@@ -507,7 +507,7 @@
|
||||
"name": "Copy",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.619Z",
|
||||
"updated_at": "2021-05-05T12:44:31.388Z",
|
||||
"updated_at": "2021-08-12T12:36:11.164Z",
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
@@ -567,6 +567,14 @@
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "Decision",
|
||||
"description": "",
|
||||
"created_at": "2021-08-13T06:33:04.661Z",
|
||||
"updated_at": "2021-08-13T06:33:04.661Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "DecisionCheck",
|
||||
"description": "",
|
||||
@@ -591,6 +599,14 @@
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "DecisionFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-08-13T06:33:04.665Z",
|
||||
"updated_at": "2021-08-13T06:33:04.665Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "Delete",
|
||||
"description": "",
|
||||
@@ -619,7 +635,7 @@
|
||||
"name": "DialogDots",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.133Z",
|
||||
"updated_at": "2021-04-09T13:32:23.486Z",
|
||||
"updated_at": "2021-08-12T11:19:13.127Z",
|
||||
"pageName": "Communication",
|
||||
"visible": true
|
||||
},
|
||||
@@ -875,7 +891,7 @@
|
||||
"name": "EmployerFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-22T13:40:32.293Z",
|
||||
"updated_at": "2021-04-22T08:46:31.424Z",
|
||||
"updated_at": "2021-08-13T06:33:04.692Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
@@ -931,7 +947,7 @@
|
||||
"name": "Eye",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.895Z",
|
||||
"updated_at": "2021-04-09T13:32:23.514Z",
|
||||
"updated_at": "2021-08-12T09:55:24.102Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -939,7 +955,7 @@
|
||||
"name": "EyeFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.321Z",
|
||||
"updated_at": "2021-04-09T13:32:16.996Z",
|
||||
"updated_at": "2021-08-12T09:55:25.386Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -947,7 +963,7 @@
|
||||
"name": "EyeScreened",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.956Z",
|
||||
"updated_at": "2021-04-09T13:32:23.351Z",
|
||||
"updated_at": "2021-08-12T09:56:29.536Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -955,7 +971,7 @@
|
||||
"name": "EyeScreenedFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.578Z",
|
||||
"updated_at": "2021-04-09T13:32:23.419Z",
|
||||
"updated_at": "2021-08-12T09:55:47.137Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1107,7 +1123,7 @@
|
||||
"name": "Findout",
|
||||
"description": "",
|
||||
"created_at": "2021-05-05T13:04:25.502Z",
|
||||
"updated_at": "2021-05-05T13:04:25.502Z",
|
||||
"updated_at": "2021-08-12T12:32:46.082Z",
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1139,7 +1155,7 @@
|
||||
"name": "Folder",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.682Z",
|
||||
"updated_at": "2021-04-09T13:32:23.439Z",
|
||||
"updated_at": "2021-08-13T07:30:12.108Z",
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1267,7 +1283,7 @@
|
||||
"name": "HandBandage",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.711Z",
|
||||
"updated_at": "2021-04-09T13:32:16.442Z",
|
||||
"updated_at": "2021-08-13T09:48:45.392Z",
|
||||
"pageName": "Health",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1379,7 +1395,7 @@
|
||||
"name": "Helmet",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.793Z",
|
||||
"updated_at": "2021-04-09T13:32:23.412Z",
|
||||
"updated_at": "2021-08-13T09:49:01.868Z",
|
||||
"pageName": "Jobs",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1491,7 +1507,7 @@
|
||||
"name": "Information",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.005Z",
|
||||
"updated_at": "2021-04-09T13:32:16.578Z",
|
||||
"updated_at": "2021-08-12T12:35:33.631Z",
|
||||
"pageName": "Status",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1499,7 +1515,7 @@
|
||||
"name": "InformationFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.736Z",
|
||||
"updated_at": "2021-04-09T13:32:16.132Z",
|
||||
"updated_at": "2021-08-12T11:36:44.756Z",
|
||||
"pageName": "Status",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1531,7 +1547,7 @@
|
||||
"name": "LawFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.330Z",
|
||||
"updated_at": "2021-04-09T13:32:16.725Z",
|
||||
"updated_at": "2021-08-13T09:50:59.913Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1539,7 +1555,7 @@
|
||||
"name": "Left",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.797Z",
|
||||
"updated_at": "2021-04-09T13:32:23.354Z",
|
||||
"updated_at": "2021-08-13T06:33:04.688Z",
|
||||
"pageName": "Arrow",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1619,7 +1635,7 @@
|
||||
"name": "Locked",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.027Z",
|
||||
"updated_at": "2021-04-09T13:32:23.385Z",
|
||||
"updated_at": "2021-08-12T09:56:54.295Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1715,7 +1731,7 @@
|
||||
"name": "MinusCircleFilled",
|
||||
"description": "",
|
||||
"created_at": "2021-01-11T13:37:55.721Z",
|
||||
"updated_at": "2021-04-09T13:32:16.246Z",
|
||||
"updated_at": "2021-08-12T10:26:25.789Z",
|
||||
"pageName": "Interface",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1731,7 +1747,7 @@
|
||||
"name": "Mobile",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.010Z",
|
||||
"updated_at": "2021-04-09T13:32:16.508Z",
|
||||
"updated_at": "2021-08-12T11:19:05.339Z",
|
||||
"pageName": "Device",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1747,7 +1763,7 @@
|
||||
"name": "Money",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.741Z",
|
||||
"updated_at": "2021-04-09T13:32:23.388Z",
|
||||
"updated_at": "2021-08-12T12:31:01.092Z",
|
||||
"pageName": "Money",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1891,7 +1907,7 @@
|
||||
"name": "Office1",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.720Z",
|
||||
"updated_at": "2021-04-09T13:32:23.456Z",
|
||||
"updated_at": "2021-08-12T12:56:17.625Z",
|
||||
"pageName": "Building",
|
||||
"visible": true
|
||||
},
|
||||
@@ -1987,7 +2003,7 @@
|
||||
"name": "People",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.850Z",
|
||||
"updated_at": "2021-04-09T13:32:23.661Z",
|
||||
"updated_at": "2021-08-12T11:17:04.979Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2115,7 +2131,7 @@
|
||||
"name": "Profile",
|
||||
"description": "",
|
||||
"created_at": "2021-04-26T09:24:38.029Z",
|
||||
"updated_at": "2021-04-30T10:55:32.846Z",
|
||||
"updated_at": "2021-08-12T12:32:56.285Z",
|
||||
"pageName": "File",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2147,7 +2163,7 @@
|
||||
"name": "Receipt",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.904Z",
|
||||
"updated_at": "2021-04-09T13:32:23.649Z",
|
||||
"updated_at": "2021-08-12T12:29:47.091Z",
|
||||
"pageName": "Money",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2227,7 +2243,7 @@
|
||||
"name": "Right",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.642Z",
|
||||
"updated_at": "2021-04-09T13:32:23.409Z",
|
||||
"updated_at": "2021-08-12T07:14:26.093Z",
|
||||
"pageName": "Arrow",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2259,7 +2275,7 @@
|
||||
"name": "Sandglass",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.117Z",
|
||||
"updated_at": "2021-04-09T13:32:23.313Z",
|
||||
"updated_at": "2021-08-12T08:18:12.598Z",
|
||||
"pageName": "Time",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2323,7 +2339,7 @@
|
||||
"name": "Search",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.983Z",
|
||||
"updated_at": "2021-04-09T13:32:16.382Z",
|
||||
"updated_at": "2021-08-12T12:37:22.919Z",
|
||||
"pageName": "Interface",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2387,7 +2403,7 @@
|
||||
"name": "Send",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.101Z",
|
||||
"updated_at": "2021-04-09T13:32:23.596Z",
|
||||
"updated_at": "2021-08-13T07:30:12.151Z",
|
||||
"pageName": "Communication",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2403,7 +2419,7 @@
|
||||
"name": "Service",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.707Z",
|
||||
"updated_at": "2021-06-14T07:21:59.047Z",
|
||||
"updated_at": "2021-08-12T11:15:52.145Z",
|
||||
"pageName": "People",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2675,7 +2691,7 @@
|
||||
"name": "SuccessStroke",
|
||||
"description": "",
|
||||
"created_at": "2021-04-15T07:12:49.753Z",
|
||||
"updated_at": "2021-04-15T07:12:49.753Z",
|
||||
"updated_at": "2021-08-12T11:30:36.177Z",
|
||||
"pageName": "Status",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2755,7 +2771,7 @@
|
||||
"name": "ThermometerStroke",
|
||||
"description": "",
|
||||
"created_at": "2021-04-07T12:13:28.179Z",
|
||||
"updated_at": "2021-04-09T13:32:16.814Z",
|
||||
"updated_at": "2021-08-12T12:34:12.825Z",
|
||||
"pageName": "Health",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2811,7 +2827,7 @@
|
||||
"name": "Unlocked",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:42.823Z",
|
||||
"updated_at": "2021-04-09T13:32:16.901Z",
|
||||
"updated_at": "2021-08-12T09:56:56.564Z",
|
||||
"pageName": "Privacy",
|
||||
"visible": true
|
||||
},
|
||||
@@ -2843,7 +2859,7 @@
|
||||
"name": "Upload",
|
||||
"description": "",
|
||||
"created_at": "2020-07-01T10:37:43.046Z",
|
||||
"updated_at": "2021-04-09T13:32:23.685Z",
|
||||
"updated_at": "2021-08-13T07:41:40.719Z",
|
||||
"pageName": "Attachment",
|
||||
"visible": true
|
||||
},
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-icons",
|
||||
"version": "0.3.3",
|
||||
"version": "0.5.2",
|
||||
"private": false,
|
||||
"description": "NAVs egne ikoner i SVG og React format",
|
||||
"repository": {
|
||||
@@ -14,11 +14,10 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "NAV",
|
||||
"main": "esm/index.js",
|
||||
"module": "esm/index.js",
|
||||
"typings": "esm/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"main": "./cjs/index.js",
|
||||
"module": "./esm/index.js",
|
||||
"typings": "./esm/index.d.ts",
|
||||
"files": [
|
||||
"/cjs",
|
||||
"/esm",
|
||||
@@ -26,12 +25,13 @@
|
||||
"/svg"
|
||||
],
|
||||
"scripts": {
|
||||
"cjs-package": "copyfiles -f config/package.json cjs",
|
||||
"dl-icons": "FILE_KEY=UmEVH3pZ71uJPsSz9ilP3Y node --experimental-modules --es-module-specifier-resolution=node -r dotenv/config figma-api/index.js dotenv_config_path=figma-api/.env",
|
||||
"create-package-json-pointers-to-esm": "node ../../utilities/scripts/createPackageJsonsWithESMPointers.js",
|
||||
"dl-icons": "FILE_KEY=UmEVH3pZ71uJPsSz9ilP3Y node --experimental-modules --es-module-specifier-resolution=node -r dotenv/config figma-api/index.mjs dotenv_config_path=figma-api/.env",
|
||||
"create-icons": "svgr --silent --typescript --ref --icon --title-prop --replace-attr-values \"#262626=currentColor\" -d src svg",
|
||||
"convert-icons": "node figma-api/pngConverter.js",
|
||||
"clean": "rm -rf src && rm -rf esm && rm -rf cjs && rm -rf png && rm -rf NAV-ikonpakke-png.zip && rm -rf NAV-ikonpakke-svg.zip",
|
||||
"build": "npm run clean && npm run create-icons && tsc && tsc -p tsconfig-esm.json && yarn cjs-package && npm run convert-icons && node figma-api/zipIcons.js"
|
||||
"convert-icons": "node figma-api/pngConverter.mjs",
|
||||
"clean": "rimraf src esm cjs png NAV-ikonpakke-png.zip NAV-ikonpakke-svg.zip",
|
||||
"zip-icons": "node figma-api/zipIcons.mjs",
|
||||
"build": "npm run clean && npm run create-icons && tsc && tsc -p tsconfig-esm.json && yarn create-package-json-pointers-to-esm && npm run convert-icons && yarn zip-icons"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Meta } from "@storybook/addon-docs";
|
||||
|
||||
# Ta i bruk ikonpakken `@navikt/ds-icons`
|
||||
|
||||
Alle ikoner kan bli funnet her https://design.nav.no/resources/icons
|
||||
Alle ikoner kan bli funnet her https://design.nav.no/designsystem/resources/icons
|
||||
|
||||
## Oppsett
|
||||
|
||||
@@ -12,7 +12,7 @@ Alle ikoner kan bli funnet her https://design.nav.no/resources/icons
|
||||
yarn add @navikt/ds-icons
|
||||
```
|
||||
|
||||
```bash
|
||||
```jsx
|
||||
Import { Expand } from `@navikt/ds-icons`;
|
||||
|
||||
<Expand
|
||||
@@ -22,15 +22,4 @@ Import { Expand } from `@navikt/ds-icons`;
|
||||
/>
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
|
||||
|
||||
```bash
|
||||
"moduleNameMapper": {
|
||||
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
|
||||
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
|
||||
}
|
||||
```
|
||||
|
||||
Dette vil remappe Ikonpakken (og komponentpakken) til å bruke CommonJs versjonen for testing
|
||||
Note: Det kan være tilfeller der oppsettet ditt ikke har støtte for SVG, og det må da legges til manuelt i eks en webpack config basert på hva som blir brukt.
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.9565 8C12.6134 8 13.9565 6.65685 13.9565 5C13.9565 3.34315 12.6134 2 10.9565 2C9.29969 2 7.95654 3.34315 7.95654 5C7.95654 6.65685 9.29969 8 10.9565 8ZM10.9565 10C13.718 10 15.9565 7.76142 15.9565 5C15.9565 2.23858 13.718 0 10.9565 0C8.19512 0 5.95654 2.23858 5.95654 5C5.95654 7.76142 8.19512 10 10.9565 10Z" fill="#262626"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.0569 11.5858C19.2758 10.8047 18.0095 10.8047 17.2285 11.5858L15.8143 13C15.0332 13.781 15.0332 15.0474 15.8143 15.8284L16.6856 16.6997L12.1071 21.2782L11.4 21.9853L12.8142 23.3995L13.5213 22.6924L18.0998 18.114L19.0496 19.0637C19.8306 19.8448 21.0969 19.8448 21.878 19.0637L23.2922 17.6495C24.0733 16.8685 24.0733 15.6021 23.2922 14.8211L20.0569 11.5858ZM18.6427 13L21.878 16.2353L20.4638 17.6495L17.2285 14.4142L18.6427 13Z" fill="#262626"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1594 11.7521C13.2095 11.2709 12.1352 11 11 11C7.13401 11 4 14.134 4 18H6C6 15.2386 8.23858 13 11 13C11.5609 13 12.0993 13.092 12.6014 13.2617L14.1594 11.7521Z" fill="#262626"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 5C16 7.76142 13.7614 10 11 10C8.23858 10 6 7.76142 6 5C6 2.23858 8.23858 0 11 0C13.7614 0 16 2.23858 16 5ZM4 18C4 14.134 7.13401 11 11 11C12.3956 11 13.6959 11.4084 14.7877 12.1123L8.7108 18H4Z" fill="#262626"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.2782 12.2854C18.8876 11.9049 18.2545 11.9049 17.8639 12.2854L15.3891 14.6973C14.9985 15.0778 14.9985 15.6949 15.3891 16.0754L16.8033 17.4536L11.5 22.6218L12.9142 24L18.2175 18.8318L19.8085 20.3823C20.199 20.7628 20.8322 20.7628 21.2227 20.3823L23.6976 17.9704C24.0881 17.5899 24.0881 16.9728 23.6976 16.5923L19.2782 12.2854Z" fill="#262626"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 764 B |
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"main": "index.js",
|
||||
"typings": "../esm/index.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "0.6.13",
|
||||
"version": "0.7.5",
|
||||
"private": false,
|
||||
"description": "NAV designsystem react components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -14,11 +14,10 @@
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler/tree/master/%40navikt/ds-react"
|
||||
},
|
||||
"main": "esm/index.js",
|
||||
"module": "esm/index.js",
|
||||
"typings": "esm/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"main": "./cjs/index.js",
|
||||
"module": "./esm/index.js",
|
||||
"typings": "./esm/index.d.ts",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
@@ -28,14 +27,14 @@
|
||||
"/src"
|
||||
],
|
||||
"scripts": {
|
||||
"cjs-package": "copyfiles -f config/package.json cjs",
|
||||
"clean": "rm -rf cjs esm",
|
||||
"build": "yarn run clean && tsc && tsc -p tsconfig-esm.json && yarn cjs-package",
|
||||
"create-package-json-pointers-to-esm": "node ../../utilities/scripts/createPackageJsonsWithESMPointers.js",
|
||||
"clean": "rimraf cjs esm",
|
||||
"build": "yarn run clean && tsc && tsc -p tsconfig-esm.json && yarn create-package-json-pointers-to-esm",
|
||||
"watch": "tsc --watch -p tsconfig-esm.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@navikt/ds-icons": "^0.3.3",
|
||||
"@navikt/ds-icons": "^0.5.2",
|
||||
"@popperjs/core": "^2.5.4",
|
||||
"classnames": "^2.2.6",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
@@ -43,12 +42,12 @@
|
||||
"react-merge-refs": "^1.1.0",
|
||||
"react-modal": "3.12.1",
|
||||
"react-popper": "^2.2.4",
|
||||
"short-uuid": "^4.2.0",
|
||||
"uuid": "^8.3.2"
|
||||
"short-uuid": "^4.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copyfiles": "^2.4.1",
|
||||
"react-router-dom": "^5.2.0"
|
||||
"react-router-dom": "^5.2.0",
|
||||
"rimraf": "3.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import { AccordionMenu as BaseAccordionMenu } from "../accordion-menu";
|
||||
import { Title } from "../index";
|
||||
import { ActiveAnchorProvider } from "./ActiveAnchorStore";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface AccordionAnchorMenuProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionAnchorMenu = forwardRef<
|
||||
HTMLDivElement,
|
||||
AccordionAnchorMenuProps
|
||||
>(({ children, title, className, ...rest }, ref) => (
|
||||
<div
|
||||
className={cl("navds-accordion-anchor-menu", className)}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
{title && (
|
||||
<Title level={2} size="m" className="navds-accordion-anchor-menu__title">
|
||||
{title}
|
||||
</Title>
|
||||
)}
|
||||
<ActiveAnchorProvider>
|
||||
<BaseAccordionMenu aria-label={title || "Meny"}>
|
||||
{children}
|
||||
</BaseAccordionMenu>
|
||||
</ActiveAnchorProvider>
|
||||
</div>
|
||||
));
|
||||
|
||||
export default AccordionAnchorMenu;
|
||||
@@ -1 +0,0 @@
|
||||
export { AccordionMenuCollapsable as AccordionAnchorMenuCollapsable } from "../accordion-menu";
|
||||
@@ -1,39 +0,0 @@
|
||||
import React, { forwardRef, useEffect } from "react";
|
||||
import { AccordionMenuItem, AccordionMenuItemType } from "../accordion-menu";
|
||||
import { useStore } from "./ActiveAnchorStore";
|
||||
|
||||
const AccordionAnchorMenuItem: AccordionMenuItemType = forwardRef(
|
||||
(props, ref) => {
|
||||
const isAnchorActive = useIsAnchorActive(
|
||||
props.href && props.href.split("#")[1]
|
||||
);
|
||||
|
||||
return (
|
||||
<AccordionMenuItem
|
||||
{...props}
|
||||
ref={ref}
|
||||
active={props.active || isAnchorActive}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const useIsAnchorActive = (anchor: string | undefined) => {
|
||||
const { activeAnchor, registerAnchor, unregisterAnchor } = useStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (anchor) {
|
||||
const target = document.getElementById(anchor);
|
||||
if (target) {
|
||||
registerAnchor(anchor);
|
||||
return () => {
|
||||
unregisterAnchor(anchor);
|
||||
};
|
||||
}
|
||||
}
|
||||
}, [anchor, registerAnchor, unregisterAnchor]);
|
||||
|
||||
return (anchor && activeAnchor === anchor) || false;
|
||||
};
|
||||
|
||||
export default AccordionAnchorMenuItem;
|
||||
@@ -1,73 +0,0 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
} from "react";
|
||||
|
||||
export interface ActiveAnchorStore {
|
||||
activeAnchor?: string;
|
||||
registerAnchor: (anchor: string) => void;
|
||||
unregisterAnchor: (anchor: string) => void;
|
||||
}
|
||||
|
||||
export const ActiveAnchorContext = createContext({} as ActiveAnchorStore);
|
||||
export const ActiveAnchorProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const [anchors, setAnchors] = useState<string[]>([]);
|
||||
const [activeAnchor, setActiveAnchor] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
const scrollListener = () => {
|
||||
const offset = 100;
|
||||
const lastPassedAnchor = anchors
|
||||
.map((anchor) => document.getElementById(anchor) as HTMLElement)
|
||||
.map((element: HTMLElement) => ({
|
||||
id: element.id,
|
||||
top: element.getBoundingClientRect().top - offset,
|
||||
scrolledToBottom:
|
||||
window.innerHeight + window.pageYOffset >=
|
||||
document.body.offsetHeight,
|
||||
}))
|
||||
.filter((element) => element.scrolledToBottom || element.top <= 0)
|
||||
.sort((a, b) => (a.top < b.top ? -1 : 1))
|
||||
.map((anchor) => anchor.id)
|
||||
.pop();
|
||||
|
||||
// Set active anchor and related url hash
|
||||
if (lastPassedAnchor && activeAnchor !== lastPassedAnchor) {
|
||||
const { href, hash } = window.location;
|
||||
const urlWithoutHash = href.replace(hash, "");
|
||||
const urlWithAnchor = `${urlWithoutHash}#${lastPassedAnchor}`;
|
||||
const title = document.title;
|
||||
window.history.replaceState(window.history.state, title, urlWithAnchor);
|
||||
setActiveAnchor(lastPassedAnchor);
|
||||
}
|
||||
};
|
||||
window.addEventListener("scroll", scrollListener);
|
||||
return () => {
|
||||
window.removeEventListener("scroll", scrollListener);
|
||||
};
|
||||
}, [anchors, activeAnchor]);
|
||||
|
||||
return (
|
||||
<ActiveAnchorContext.Provider
|
||||
value={{
|
||||
activeAnchor,
|
||||
registerAnchor: useCallback((anchor) => {
|
||||
setAnchors((anchors) => [...anchors, anchor]);
|
||||
}, []),
|
||||
unregisterAnchor: useCallback((anchor) => {
|
||||
setAnchors((anchors) => anchors.filter((a) => a !== anchor));
|
||||
}, []),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ActiveAnchorContext.Provider>
|
||||
);
|
||||
};
|
||||
export const useStore = () => useContext(ActiveAnchorContext);
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as AccordionAnchorMenu } from "./AccordionAnchorMenu";
|
||||
export { AccordionAnchorMenuCollapsable } from "./AccordionAnchorMenuCollapsable";
|
||||
export { default as AccordionAnchorMenuItem } from "./AccordionAnchorMenuItem";
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Meta, Canvas } from "@storybook/addon-docs";
|
||||
import { AccordionAnchorMenu } from "../../index";
|
||||
import { Success } from "@navikt/ds-react";
|
||||
|
||||
<Meta title="ds-react/accordion-anchor-menu/intro" />
|
||||
|
||||
# AccordionAnchorMenu
|
||||
|
||||
NOTE: Komponenten er ikke oppdatert og er veldig buggy. Ville ungått bruk av denne om mulig og bare brukt
|
||||
vanlig `AccordionMenu`. Hvorvidt vi kommer til å oppdatere denne og ta den med i 1.0 er usikkert.
|
||||
|
||||
`AccordionAnchorMenu` er en meny-komponent som implementerer `AccordionMenu` med context
|
||||
for lytting på aktiv anchor/heading. Dette vil si at active-state settes automatisk.
|
||||
når man scroller forbi den relevante linken på siden.
|
||||
@@ -1,125 +0,0 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
AccordionAnchorMenu as Menu,
|
||||
AccordionAnchorMenuCollapsable as Collapsable,
|
||||
AccordionAnchorMenuItem as Item,
|
||||
} from "../index";
|
||||
import {
|
||||
ProductPageLayout as Layout,
|
||||
ProductPageSection as Section,
|
||||
ProductPagePanel as Panel,
|
||||
} from "../../index";
|
||||
import { Right } from "../../layouts/stories/components/sections/Right";
|
||||
import { LightBulb, Telephone } from "@navikt/ds-icons";
|
||||
import { MainOne } from "../../layouts/stories/components/sections/Main";
|
||||
import { MainTwo } from "../../layouts/stories/components/sections/Main";
|
||||
import { MainThree } from "../../layouts/stories/components/sections/Main";
|
||||
import { Link, HashRouter as Router } from "react-router-dom";
|
||||
|
||||
export default {
|
||||
title: "ds-react/accordion-anchor-menu",
|
||||
component: { Menu },
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
};
|
||||
|
||||
export const All = () => (
|
||||
<Layout title={"Nunc et lorem"}>
|
||||
<Section left sticky withPadding={false}>
|
||||
<Menu title={"Minima"}>
|
||||
<Item href={"#leo-quis"}>Leo quis</Item>
|
||||
<Collapsable title={"Proin accumsan"}>
|
||||
<Item href={"#nulla-pariatur"}>Nulla pariatur</Item>
|
||||
<Item href={"#luctus-justo"}>Luctus justo</Item>
|
||||
</Collapsable>
|
||||
<Item href={"#maecenas-in-pretium"}>Maecenas in pretium</Item>
|
||||
</Menu>
|
||||
</Section>
|
||||
<Section whiteBackground={false} withPadding={false}>
|
||||
<Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</Panel>
|
||||
<Panel title={"Proin accumsan"} anchor={"proin-accumsan"}>
|
||||
<MainTwo title={false} />
|
||||
</Panel>
|
||||
<Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</Panel>
|
||||
</Section>
|
||||
<Section right sticky>
|
||||
<Right />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export const ReactRouter = () => (
|
||||
<Layout title={"Nunc et lorem"}>
|
||||
<Section left sticky withPadding={false}>
|
||||
<Menu>
|
||||
<Item component={Link} to="/link1">
|
||||
Leo quis
|
||||
</Item>
|
||||
<Collapsable title={"Proin accumsan"}>
|
||||
<Item component={Link} to="/link2">
|
||||
Nulla pariatur
|
||||
</Item>
|
||||
<Item component={Link} to="/link3">
|
||||
Luctus justo
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Collapsable title={"Sint cupidatat"}>
|
||||
<Item component={Link} to="/link4">
|
||||
Nulla pariatur
|
||||
</Item>
|
||||
<Item component={Link} to="/link5">
|
||||
Luctus justo
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Item component={Link} to="/link6">
|
||||
Maecenas in pretium
|
||||
</Item>
|
||||
</Menu>
|
||||
</Section>
|
||||
<Section whiteBackground={false} withPadding={false}>
|
||||
<Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</Panel>
|
||||
<Panel title={"Proin accumsan"} anchor={"proin-accumsan"}>
|
||||
<MainTwo title={false} />
|
||||
</Panel>
|
||||
<Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</Panel>
|
||||
</Section>
|
||||
<Section right sticky>
|
||||
<Right />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
ReactRouter.decorators = [
|
||||
(Story) => (
|
||||
<Router>
|
||||
<Story />
|
||||
</Router>
|
||||
),
|
||||
];
|
||||
@@ -4,7 +4,6 @@ import MenuItems from "./MenuItems";
|
||||
|
||||
export interface AccordionMenuProps extends HTMLAttributes<HTMLElement> {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
|
||||
|
||||
@@ -8,7 +8,6 @@ export interface AccordionMenuCollapsableProps
|
||||
title: string;
|
||||
defaultOpen?: boolean;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionMenuCollapsable = forwardRef<
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import React from "react";
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
const MenuItems = ({ children }: { children: React.ReactNode }) => (
|
||||
<ul className="navds-accordion-menu__list">
|
||||
{React.Children.toArray(children).map((child, i) => (
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { forwardRef, useEffect, useState } from "react";
|
||||
import cl from "classnames";
|
||||
import { UnmountClosed, Collapse } from "react-collapse";
|
||||
import { Expand, ExpandFilled } from "@navikt/ds-icons";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useId } from "..";
|
||||
|
||||
export interface AccordionProps
|
||||
extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
@@ -10,10 +10,6 @@ export interface AccordionProps
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Content on interactive surface of component
|
||||
*/
|
||||
@@ -26,8 +22,6 @@ export interface AccordionProps
|
||||
open?: boolean;
|
||||
/**
|
||||
* Callback for when user interacts with component
|
||||
*
|
||||
* @param {object} event
|
||||
*/
|
||||
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||
/**
|
||||
@@ -46,19 +40,15 @@ const Accordion = forwardRef<HTMLButtonElement, AccordionProps>(
|
||||
className,
|
||||
renderContentWhenClosed = false,
|
||||
onClick,
|
||||
id,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [contentId, setContentId] = useState("");
|
||||
const [buttonId, setButtonId] = useState("");
|
||||
const [internalOpen, setInternalOpen] = useState<boolean>(open);
|
||||
|
||||
// Forsøk på å fikse Nextjs SSR server/client clock problem
|
||||
useEffect(() => {
|
||||
setContentId(() => uuidv4());
|
||||
setButtonId(() => uuidv4());
|
||||
}, []);
|
||||
const buttonId = useId(id);
|
||||
const contentId = useId();
|
||||
|
||||
useEffect(() => {
|
||||
setInternalOpen(open);
|
||||
|
||||
@@ -12,17 +12,10 @@ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
* Decides what design the alert will have
|
||||
*/
|
||||
variant: "error" | "warning" | "info" | "success";
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Reduces padding on component
|
||||
* @default "medium"
|
||||
* Changes padding and font-sizes
|
||||
* @default "m"
|
||||
*/
|
||||
size?: "m" | "s";
|
||||
}
|
||||
|
||||
@@ -1,27 +1,25 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Decides component design and interactions
|
||||
* Changes design and interactions
|
||||
* @default "primary"
|
||||
*/
|
||||
variant?: "primary" | "secondary" | "action" | "danger";
|
||||
/**
|
||||
* Reduces internal padding for component
|
||||
* @default "medium"
|
||||
* Changes padding, height and font-size
|
||||
* @default "m"
|
||||
*/
|
||||
size?: "m" | "s";
|
||||
/**
|
||||
* Prevent the user from interacting with the button: it cannot be pressed or focused.
|
||||
* @note Avoid using if possible for accessibility purposes
|
||||
* @default false
|
||||
*/
|
||||
disabled?: boolean;
|
||||
|
||||
@@ -29,6 +29,13 @@ const variants: Array<"primary" | "secondary" | "action" | "danger"> = [
|
||||
"danger",
|
||||
];
|
||||
|
||||
const varSwitch = {
|
||||
primary: "Primary",
|
||||
secondary: "Secondary",
|
||||
action: "Action",
|
||||
danger: "Danger",
|
||||
};
|
||||
|
||||
export const All = () => {
|
||||
return (
|
||||
<>
|
||||
@@ -36,7 +43,7 @@ export const All = () => {
|
||||
<Section>
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant}>
|
||||
{variant}
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
@@ -44,7 +51,7 @@ export const All = () => {
|
||||
<Section>
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} disabled>
|
||||
{variant}
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
@@ -56,7 +63,7 @@ export const All = () => {
|
||||
className={`navds-button navds-button--${variant} navds-body-short`}
|
||||
href="the-link"
|
||||
>
|
||||
{variant}
|
||||
{varSwitch[variant]}
|
||||
</a>
|
||||
))}
|
||||
</Section>
|
||||
@@ -64,7 +71,7 @@ export const All = () => {
|
||||
<Section>
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} size="s">
|
||||
{variant}
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
@@ -72,7 +79,7 @@ export const All = () => {
|
||||
<Section>
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant}>
|
||||
<span>{variant}</span> <Success />
|
||||
<span>{varSwitch[variant]}</span> <Success />
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
@@ -80,7 +87,7 @@ export const All = () => {
|
||||
<Section>
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} size="s">
|
||||
<Success /> <span>{variant}</span>
|
||||
<Success /> <span>{varSwitch[variant]}</span>
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
|
||||
@@ -5,10 +5,6 @@ import { OverridableComponent } from "../util";
|
||||
export interface MicroCardProps {
|
||||
props: {
|
||||
children: string;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
} & React.HTMLAttributes<HTMLAnchorElement>;
|
||||
defaultComponent: "a";
|
||||
}
|
||||
|
||||
@@ -2,10 +2,6 @@ import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface ContentContainerProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
classNames?: string;
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
|
||||
@@ -9,10 +9,14 @@ import React, {
|
||||
useState,
|
||||
} from "react";
|
||||
import mergeRefs from "react-merge-refs";
|
||||
import { Popover, Button } from "../index";
|
||||
import { Popover, Button } from "..";
|
||||
|
||||
export interface CopyToClipboardProps
|
||||
extends HTMLAttributes<HTMLButtonElement> {
|
||||
/**
|
||||
* Button text
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* Text to be copied to clipboard
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import { BodyLong, Checkbox, CheckboxProps } from "..";
|
||||
|
||||
export interface ConfirmationPanelProps extends Partial<CheckboxProps> {
|
||||
/**
|
||||
* Additional information on panel
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* Checkbox label
|
||||
*/
|
||||
label: string;
|
||||
/**
|
||||
* Checked state for checkbox
|
||||
*/
|
||||
checked: boolean;
|
||||
}
|
||||
|
||||
const ConfirmationPanel = forwardRef<HTMLDivElement, ConfirmationPanelProps>(
|
||||
({ className, children, label, ...props }, ref) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cl("navds-confirmation-panel", className, {
|
||||
"navds-confirmation-panel--s": props.size === "s",
|
||||
"navds-confirmation-panel--error": !!props.error,
|
||||
"navds-confirmation-panel--checked": !!props.checked,
|
||||
})}
|
||||
>
|
||||
{children && (
|
||||
<BodyLong
|
||||
size={props.size}
|
||||
className="navds-confirmation-panel__content"
|
||||
>
|
||||
{children}
|
||||
</BodyLong>
|
||||
)}
|
||||
<Checkbox {...props}>{label}</Checkbox>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ConfirmationPanel;
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import cl from "classnames";
|
||||
import { Label } from "../index";
|
||||
import { Label } from "..";
|
||||
|
||||
const ErrorMessage = (props) => (
|
||||
<Label
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
import cl from "classnames";
|
||||
import React, { FieldsetHTMLAttributes, forwardRef, useContext } from "react";
|
||||
import { BodyShort, Label } from "../../index";
|
||||
import { BodyShort, Label, omit } from "../..";
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import { FormFieldProps } from "../useFormField";
|
||||
import { useFieldset } from "./useFieldset";
|
||||
|
||||
export type FieldsetContextProps = {
|
||||
/**
|
||||
* Error message applied to element
|
||||
*/
|
||||
error?: React.ReactNode;
|
||||
/**
|
||||
* Overrides internal errorId
|
||||
*/
|
||||
errorId: string;
|
||||
/**
|
||||
* Changes paddings, margins and font-sizes
|
||||
*/
|
||||
size: "m" | "s";
|
||||
disabled: boolean;
|
||||
errorDescribedBy?: string;
|
||||
};
|
||||
|
||||
export const FieldsetContext = React.createContext<FieldsetContextProps | null>(
|
||||
@@ -23,7 +31,6 @@ export interface FieldsetProps
|
||||
* FormFields in Fieldset
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
/**
|
||||
* Fieldset legend
|
||||
*/
|
||||
@@ -48,7 +55,6 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
|
||||
hasError,
|
||||
size,
|
||||
inputDescriptionId,
|
||||
errorDescribedBy,
|
||||
} = useFieldset(props);
|
||||
|
||||
const fieldset = useContext(FieldsetContext);
|
||||
@@ -67,14 +73,16 @@ const Fieldset = forwardRef<HTMLFieldSetElement, FieldsetProps>(
|
||||
<FieldsetContext.Provider
|
||||
value={{
|
||||
error: errorPropagation ? props.error ?? fieldset?.error : undefined,
|
||||
errorId: props.error ? errorId : fieldset?.errorId ?? errorId,
|
||||
errorId: cl({
|
||||
[errorId]: showErrorMsg,
|
||||
[fieldset?.errorId ?? ""]: !!fieldset?.error,
|
||||
}),
|
||||
size,
|
||||
disabled: props.disabled ?? false,
|
||||
errorDescribedBy,
|
||||
}}
|
||||
>
|
||||
<fieldset
|
||||
{...rest}
|
||||
{...omit(rest, ["errorId", "error", "size"])}
|
||||
{...inputProps}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
import cl from "classnames";
|
||||
import { useContext } from "react";
|
||||
import { FieldsetContext } from "./index";
|
||||
import { useFormField } from "../useFormField";
|
||||
|
||||
/**
|
||||
@@ -8,19 +5,13 @@ import { useFormField } from "../useFormField";
|
||||
*/
|
||||
export const useFieldset = (props) => {
|
||||
const formField = useFormField(props, "fieldset");
|
||||
const { errorId, inputProps, showErrorMsg } = formField;
|
||||
const fieldset = useContext(FieldsetContext);
|
||||
|
||||
const errorDescribedBy: string = cl(fieldset?.errorDescribedBy, {
|
||||
[errorId]: showErrorMsg,
|
||||
});
|
||||
const { inputProps } = formField;
|
||||
|
||||
return {
|
||||
...formField,
|
||||
errorDescribedBy,
|
||||
inputProps: {
|
||||
"aria-invalid": inputProps["aria-invalid"],
|
||||
"aria-describedby": cl(inputProps["aria-describedby"], errorDescribedBy),
|
||||
"aria-describedby": inputProps["aria-describedby"],
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,13 +1,17 @@
|
||||
import React, { forwardRef, SelectHTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import { BodyShort, Label } from "../index";
|
||||
import { BodyShort, Label, omit } from "..";
|
||||
import ErrorMessage from "./ErrorMessage";
|
||||
import { FormFieldProps, useFormField } from "./useFormField";
|
||||
|
||||
export interface SelectProps
|
||||
extends FormFieldProps,
|
||||
Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> {
|
||||
/**
|
||||
* Collection of <option>-elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Expose the HTML size attribute
|
||||
*/
|
||||
@@ -74,7 +78,7 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>((props, ref) => {
|
||||
)}
|
||||
<div className="navds-select__container">
|
||||
<select
|
||||
{...rest}
|
||||
{...omit(rest, ["error", "errorId", "size"])}
|
||||
{...inputProps}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import React, { forwardRef, InputHTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import { BodyShort, Label } from "../index";
|
||||
import { BodyShort, Label, omit } from "..";
|
||||
import ErrorMessage from "./ErrorMessage";
|
||||
import { FormFieldProps, useFormField } from "./useFormField";
|
||||
|
||||
export interface TextFieldProps
|
||||
extends FormFieldProps,
|
||||
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Expose the HTML size attribute
|
||||
*/
|
||||
@@ -74,7 +70,7 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>((props, ref) => {
|
||||
</BodyShort>
|
||||
)}
|
||||
<input
|
||||
{...rest}
|
||||
{...omit(rest, ["error", "errorId", "size"])}
|
||||
{...inputProps}
|
||||
ref={ref}
|
||||
type="text"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import TextareaAutosize from "@material-ui/core/TextareaAutosize";
|
||||
import { BodyShort, Label } from "../index";
|
||||
import { BodyShort, Label, omit } from "..";
|
||||
import ErrorMessage from "./ErrorMessage";
|
||||
import { FormFieldProps, useFormField } from "./useFormField";
|
||||
import useId from "./useId";
|
||||
import { useId } from "..";
|
||||
|
||||
/**
|
||||
* TODO: Mulighet for lokalisering av sr-only/counter text
|
||||
@@ -57,7 +57,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const maxLengthId = useId({ prefix: "TextareaMaxLength" });
|
||||
const maxLengthId = `TextareaMaxLength-${useId()}`;
|
||||
const hasMaxLength = maxLength !== undefined && maxLength > 0;
|
||||
|
||||
return (
|
||||
@@ -92,7 +92,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
)}
|
||||
<div className="navds-textarea__wrapper">
|
||||
<TextareaAutosize
|
||||
{...rest}
|
||||
{...omit(rest, ["error", "errorId", "size"])}
|
||||
{...inputProps}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
|
||||
@@ -3,17 +3,23 @@ import cl from "classnames";
|
||||
import useCheckbox from "./useCheckbox";
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import { FormFieldProps } from "../useFormField";
|
||||
import { BodyShort } from "../../index";
|
||||
import { omit } from "../../index";
|
||||
import { BodyShort, omit } from "../..";
|
||||
|
||||
export interface CheckboxProps
|
||||
extends FormFieldProps,
|
||||
Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
|
||||
className?: string;
|
||||
/**
|
||||
* Label for checkbox
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Hides label and makes it viewable for screen-readers only.
|
||||
*/
|
||||
hideLabel?: boolean;
|
||||
/**
|
||||
* The value of the HTML element.
|
||||
*/
|
||||
value?: string;
|
||||
}
|
||||
|
||||
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
||||
@@ -46,6 +52,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
||||
"error",
|
||||
"errorId",
|
||||
"description",
|
||||
"hideLabel",
|
||||
])}
|
||||
{...inputProps}
|
||||
className="navds-checkbox__input"
|
||||
@@ -57,7 +64,11 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
|
||||
size={size}
|
||||
className="navds-checkbox__label"
|
||||
>
|
||||
{props.children}
|
||||
{props.hideLabel ? (
|
||||
<span className="sr-only">{props.children}</span>
|
||||
) : (
|
||||
props.children
|
||||
)}
|
||||
</BodyShort>
|
||||
{props.description && (
|
||||
<BodyShort
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { createContext, forwardRef, useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { Fieldset, FieldsetProps, FieldsetContext } from "../index";
|
||||
import { Fieldset, FieldsetProps, FieldsetContext } from "..";
|
||||
|
||||
export interface CheckboxGroupState {
|
||||
readonly defaultValue: readonly string[];
|
||||
@@ -13,6 +13,10 @@ export const CheckboxGroupContext = createContext<CheckboxGroupState | null>(
|
||||
);
|
||||
|
||||
export interface CheckboxGroupProps extends Omit<FieldsetProps, "onChange"> {
|
||||
/**
|
||||
* Checkboxes
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Controlled state for group
|
||||
*/
|
||||
|
||||
@@ -157,6 +157,38 @@ Ved bruk av `hideLegend` på CheckboxGroup kan man gjøre slik at legend/descrip
|
||||
</CheckboxGroup>
|
||||
</Canvas>
|
||||
|
||||
## hideLabel
|
||||
|
||||
Ved bruk av `hideLabel` kan man lettere ta i bruk checkbox internt i eks tabeller.
|
||||
|
||||
```jsx
|
||||
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
|
||||
<Checkbox value="Apple" hideLabel>
|
||||
Apple
|
||||
</Checkbox>
|
||||
<Checkbox value="Orange" hideLabel>
|
||||
Orange
|
||||
</Checkbox>
|
||||
<Checkbox value="Melon" hideLabel>
|
||||
Melon
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<CheckboxGroup legend="Mollit eiusmod" hideLegend>
|
||||
<Checkbox value="Apple" hideLabel>
|
||||
Apple
|
||||
</Checkbox>
|
||||
<Checkbox value="Orange" hideLabel>
|
||||
Orange
|
||||
</Checkbox>
|
||||
<Checkbox value="Melon" hideLabel>
|
||||
Melon
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
</Canvas>
|
||||
|
||||
## Disabled
|
||||
|
||||
Ved bruk av `disabled` kan man både disabled enkelte checkboxer eller checkboxgruppen.
|
||||
|
||||
@@ -66,6 +66,18 @@ export const All = () => {
|
||||
<Checkbox value="Orange">Orange</Checkbox>
|
||||
<Checkbox value="Melon">Melon</Checkbox>
|
||||
</CheckboxGroup>
|
||||
<h2>hideLabel</h2>
|
||||
<CheckboxGroup legend="Mollit eiusmod">
|
||||
<Checkbox value="Apple" hideLabel>
|
||||
Apple
|
||||
</Checkbox>
|
||||
<Checkbox value="Orange" hideLabel>
|
||||
Orange
|
||||
</Checkbox>
|
||||
<Checkbox value="Melon" hideLabel>
|
||||
Melon
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
<h2>Disabled</h2>
|
||||
<CheckboxGroup legend="Mollit eiusmod" disabled>
|
||||
<Checkbox value="Apple">Apple</Checkbox>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useContext } from "react";
|
||||
import { CheckboxProps } from "../../index";
|
||||
import { CheckboxProps } from "../..";
|
||||
import { useFormField } from "../useFormField";
|
||||
import { CheckboxGroupContext } from "./CheckboxGroup";
|
||||
|
||||
@@ -17,7 +17,7 @@ const useCheckbox = ({ children, ...props }: CheckboxProps) => {
|
||||
"`checked` is unsupported on <Checkbox> elements within a <CheckboxGroup>. Please set a `value` or `defaultValue` on <CheckboxGroup> instead."
|
||||
);
|
||||
}
|
||||
if (props.value === null) {
|
||||
if (props.value === undefined) {
|
||||
console.warn(
|
||||
"A <Checkbox> element within a <CheckboxGroup> requires a `value` property."
|
||||
);
|
||||
|
||||
@@ -3,13 +3,17 @@ import cl from "classnames";
|
||||
import { Title } from "../..";
|
||||
|
||||
export interface ErrorSummaryProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* ErrorSummaryItems
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes padding and font-sizes
|
||||
* @default "m"
|
||||
*/
|
||||
size?: "m" | "s";
|
||||
/**
|
||||
* ErrorSummary heading above links
|
||||
* Heading above links
|
||||
*/
|
||||
heading?: React.ReactNode;
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import { OverridableComponent } from "../../index";
|
||||
import { OverridableComponent } from "../..";
|
||||
|
||||
export type ErrorType = OverridableComponent<ErrorSummaryItemProps>;
|
||||
|
||||
export interface ErrorSummaryItemProps {
|
||||
props: {
|
||||
/**
|
||||
* Link text
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
} & React.HTMLAttributes<HTMLAnchorElement>;
|
||||
defaultComponent: "a";
|
||||
|
||||
@@ -10,6 +10,12 @@ export {
|
||||
FieldsetProps,
|
||||
} from "./Fieldset";
|
||||
export { Radio, RadioGroup, RadioGroupProps, RadioProps } from "./radio";
|
||||
export {
|
||||
SearchField,
|
||||
SearchFieldProps,
|
||||
SearchFieldInput,
|
||||
SearchFieldInputProps,
|
||||
} from "./search-field";
|
||||
export { default as Select, SelectProps } from "./Select";
|
||||
export {
|
||||
ErrorSummary,
|
||||
@@ -19,3 +25,7 @@ export {
|
||||
} from "./error-summary";
|
||||
export { Counter, default as Textarea, TextareaProps } from "./Textarea";
|
||||
export { default as TextField, TextFieldProps } from "./TextField";
|
||||
export {
|
||||
default as ConfirmationPanel,
|
||||
ConfirmationPanelProps,
|
||||
} from "./ConfirmationPanel";
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { forwardRef, InputHTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import { BodyShort, omit } from "../../index";
|
||||
import { BodyShort, omit } from "../..";
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import { FormFieldProps } from "../useFormField";
|
||||
import { useRadio } from "./useRadio";
|
||||
@@ -12,7 +12,6 @@ export interface RadioProps
|
||||
* Label for radio
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { Fieldset, FieldsetContext, FieldsetProps } from "../index";
|
||||
import useId from "../useId";
|
||||
import { Fieldset, FieldsetContext, FieldsetProps } from "..";
|
||||
import { useId } from "../..";
|
||||
|
||||
export interface RadioGroupContextProps {
|
||||
name: string;
|
||||
@@ -16,6 +16,13 @@ export const RadioGroupContext = React.createContext<RadioGroupContextProps | nu
|
||||
);
|
||||
|
||||
export interface RadioGroupProps extends Omit<FieldsetProps, "onChange"> {
|
||||
/**
|
||||
* Collection of <Radio>-elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Override internal name
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Default checked radiobutton
|
||||
@@ -51,6 +58,8 @@ const RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(
|
||||
) => {
|
||||
const fieldset = useContext(FieldsetContext);
|
||||
|
||||
const nameId = useId();
|
||||
|
||||
return (
|
||||
<Fieldset
|
||||
{...rest}
|
||||
@@ -63,7 +72,7 @@ const RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(
|
||||
>
|
||||
<RadioGroupContext.Provider
|
||||
value={{
|
||||
name: useId({ id: name, prefix: "RadioGroupName" }),
|
||||
name: name ?? `radioGroupName-${nameId}`,
|
||||
defaultValue,
|
||||
value,
|
||||
onChange,
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import cl from "classnames";
|
||||
import React, { forwardRef } from "react";
|
||||
import { BodyShort, Label, omit } from "../..";
|
||||
import ErrorMessage from "../ErrorMessage";
|
||||
import { FormFieldProps, useFormField } from "../useFormField";
|
||||
|
||||
export interface SearchFieldContextProps {
|
||||
inputProps: {
|
||||
id: string;
|
||||
"aria-invalid": boolean;
|
||||
"aria-describedby"?: string;
|
||||
disabled?: boolean;
|
||||
};
|
||||
size?: "m" | "s";
|
||||
}
|
||||
|
||||
export const SearchFieldContext = React.createContext<SearchFieldContextProps | null>(
|
||||
null
|
||||
);
|
||||
|
||||
export interface SearchFieldProps
|
||||
extends FormFieldProps,
|
||||
React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* SearchFieldInput & SearchFieldButton
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* If enabled shows the label and description for screenreaders only
|
||||
*/
|
||||
hideLabel?: boolean;
|
||||
/**
|
||||
* SearchField label
|
||||
*/
|
||||
label: React.ReactNode;
|
||||
}
|
||||
|
||||
const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
inputProps,
|
||||
errorId,
|
||||
showErrorMsg,
|
||||
hasError,
|
||||
size,
|
||||
inputDescriptionId,
|
||||
} = useFormField(props, "searchfield");
|
||||
|
||||
const {
|
||||
className,
|
||||
hideLabel,
|
||||
children,
|
||||
label,
|
||||
description,
|
||||
error,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
{...omit(rest, ["id", "error", "errorId", "size", "disabled"])}
|
||||
className={cl(
|
||||
className,
|
||||
"navds-form-field",
|
||||
`navds-form-field--${size ?? "m"}`,
|
||||
"navds-search-field",
|
||||
{ "navds-search-field--error": hasError }
|
||||
)}
|
||||
>
|
||||
<Label
|
||||
htmlFor={inputProps.id}
|
||||
size={size}
|
||||
component="label"
|
||||
className={cl("navds-text-field__label", {
|
||||
"sr-only": hideLabel,
|
||||
})}
|
||||
>
|
||||
{label}
|
||||
</Label>
|
||||
{!!description && (
|
||||
<BodyShort
|
||||
className={cl("navds-text-field__description", {
|
||||
"sr-only": hideLabel,
|
||||
})}
|
||||
id={inputDescriptionId}
|
||||
size={size}
|
||||
>
|
||||
{description}
|
||||
</BodyShort>
|
||||
)}
|
||||
<div className="navds-search-field__input-wrapper">
|
||||
<SearchFieldContext.Provider
|
||||
value={{
|
||||
inputProps,
|
||||
size,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</SearchFieldContext.Provider>
|
||||
</div>
|
||||
<div id={errorId} aria-relevant="additions removals" aria-live="polite">
|
||||
{showErrorMsg && <ErrorMessage size={size}>{error}</ErrorMessage>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default SearchField;
|
||||
@@ -0,0 +1,43 @@
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { SearchFieldContext } from "./SearchField";
|
||||
import { Button, ButtonProps } from "../..";
|
||||
|
||||
export interface SearchFieldButtonProps extends Omit<ButtonProps, "size"> {
|
||||
/**
|
||||
* Button text
|
||||
* @example <Search /> <span>Søk</span>
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes design and interactions
|
||||
* @default "action"
|
||||
*/
|
||||
variant?: "primary" | "action";
|
||||
}
|
||||
|
||||
const SearchFieldButton = forwardRef<HTMLButtonElement, SearchFieldButtonProps>(
|
||||
({ className, variant = "action", disabled, ...rest }, ref) => {
|
||||
const searchField = useContext(SearchFieldContext);
|
||||
|
||||
if (searchField === null) {
|
||||
console.warn("SearchFieldButton has to be wrapped in <SearchField />");
|
||||
return null;
|
||||
}
|
||||
|
||||
const { size, inputProps } = searchField;
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
className={cl(className, "navds-search-field__button")}
|
||||
{...rest}
|
||||
size={size}
|
||||
variant={variant}
|
||||
disabled={disabled ?? inputProps?.disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default SearchFieldButton;
|
||||
@@ -0,0 +1,44 @@
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { SearchFieldContext } from "./SearchField";
|
||||
import { Button, ButtonProps } from "../..";
|
||||
|
||||
export interface SearchFieldClearButtonProps extends Omit<ButtonProps, "size"> {
|
||||
/**
|
||||
* Button text
|
||||
* @example <Close /> <span>Søk</span>
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes design and interactions
|
||||
* @default "primary"
|
||||
*/
|
||||
variant?: "primary" | "action";
|
||||
}
|
||||
|
||||
const SearchFieldClearButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
SearchFieldClearButtonProps
|
||||
>(({ className, variant = "primary", disabled, ...rest }, ref) => {
|
||||
const searchField = useContext(SearchFieldContext);
|
||||
|
||||
if (searchField === null) {
|
||||
console.warn("SearchFieldClearButton has to be wrapped in <SearchField />");
|
||||
return null;
|
||||
}
|
||||
|
||||
const { size, inputProps } = searchField;
|
||||
|
||||
return (
|
||||
<Button
|
||||
ref={ref}
|
||||
className={cl(className, "navds-search-field__button")}
|
||||
{...rest}
|
||||
size={size}
|
||||
variant={variant}
|
||||
disabled={disabled ?? inputProps?.disabled}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export default SearchFieldClearButton;
|
||||
@@ -0,0 +1,37 @@
|
||||
import React, { forwardRef, InputHTMLAttributes, useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { SearchFieldContext } from "./SearchField";
|
||||
|
||||
export interface SearchFieldInputProps
|
||||
extends InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
const SearchFieldInput = forwardRef<HTMLInputElement, SearchFieldInputProps>(
|
||||
({ className, ...rest }, ref) => {
|
||||
const searchField = useContext(SearchFieldContext);
|
||||
|
||||
if (searchField === null) {
|
||||
console.warn("SearchFieldInput has to be wrapped in <SearchField />");
|
||||
return null;
|
||||
}
|
||||
|
||||
const { size, inputProps } = searchField;
|
||||
|
||||
return (
|
||||
<input
|
||||
{...rest}
|
||||
{...inputProps}
|
||||
ref={ref}
|
||||
type="text"
|
||||
className={cl(
|
||||
className,
|
||||
"navds-search-field__input",
|
||||
"navds-text-field__input",
|
||||
"navds-body-short",
|
||||
`navds-body-${size ?? "m"}`
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default SearchFieldInput;
|
||||
@@ -0,0 +1,13 @@
|
||||
export { default as SearchField, SearchFieldProps } from "./SearchField";
|
||||
export {
|
||||
default as SearchFieldInput,
|
||||
SearchFieldInputProps,
|
||||
} from "./SearchFieldInput";
|
||||
export {
|
||||
default as SearchFieldButton,
|
||||
SearchFieldButtonProps,
|
||||
} from "./SearchFieldButton";
|
||||
export {
|
||||
default as SearchFieldClearButton,
|
||||
SearchFieldClearButtonProps,
|
||||
} from "./SearchFieldClearButton";
|
||||
@@ -0,0 +1,31 @@
|
||||
import React, { useState } from "react";
|
||||
import { Close, Search } from "@navikt/ds-icons";
|
||||
import {
|
||||
SearchField,
|
||||
SearchFieldInput,
|
||||
SearchFieldButton,
|
||||
SearchFieldClearButton,
|
||||
} from "../index";
|
||||
|
||||
export const Example = () => {
|
||||
const [value, setValue] = useState("");
|
||||
|
||||
return (
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldInput
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
/>
|
||||
<SearchFieldClearButton onClick={() => setValue("")}>
|
||||
<Close />
|
||||
<span>Tøm</span>
|
||||
</SearchFieldClearButton>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,206 @@
|
||||
import { Meta, Canvas } from "@storybook/addon-docs";
|
||||
import {
|
||||
SearchField,
|
||||
SearchFieldInput,
|
||||
SearchFieldButton,
|
||||
SearchFieldClearButton,
|
||||
} from "../index";
|
||||
|
||||
import { Example } from "./search-field-example.tsx";
|
||||
|
||||
import { Search } from "@navikt/ds-icons";
|
||||
|
||||
<Meta title="ds-react/form/search-field/intro" />
|
||||
|
||||
# Hvordan ta i bruk SearchField
|
||||
|
||||
## Viktig
|
||||
|
||||
Komponenten er ikke testet eller gått gjennom et design-review, så anbefalses og vente med å ta den i bruk.
|
||||
|
||||
## Bruk
|
||||
|
||||
```jsx
|
||||
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
</Canvas>
|
||||
|
||||
## hideLabel
|
||||
|
||||
`hideLabel` proppen kan brukes for å vise label + description for bare skjermlesere.
|
||||
Vi har satt `label` som required siden man vil bruke den i sammenheng med denne proppen for bedre UU.
|
||||
|
||||
```jsx
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
</Canvas>
|
||||
|
||||
## Sizing
|
||||
|
||||
```jsx
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
size="s"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
size="s"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
</Canvas>
|
||||
|
||||
## Errors
|
||||
|
||||
```jsx
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
error="Error message"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
error="Error message"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
</Canvas>
|
||||
|
||||
## Plassering av knapp
|
||||
|
||||
```jsx
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<div>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
<br />
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
</div>
|
||||
</Canvas>
|
||||
|
||||
<h2>ClearButton</h2>
|
||||
|
||||
Man kan bruke `SearchFieldClearButton` for å håndtere clearing av value i `<input />`. For å bruke denne
|
||||
kreves det da at `SearchFieldInput` er controlled slik at man styrer state selv slik som eksemplet under.
|
||||
|
||||
```jsx
|
||||
<SearchField label="Mollit eiusmod" description="Ea cupidatat eu sunt commodo">
|
||||
<SearchFieldInput value={value} onChange={(e) => setValue(e.target.value)} />
|
||||
<SearchFieldClearButton onClick={() => setValue("")}>
|
||||
<Close />
|
||||
<span>Tøm</span>
|
||||
</SearchFieldClearButton>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<Example />
|
||||
</Canvas>
|
||||
@@ -0,0 +1,147 @@
|
||||
import React from "react";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import { Close, Search } from "@navikt/ds-icons";
|
||||
import {
|
||||
SearchField,
|
||||
SearchFieldInput,
|
||||
SearchFieldButton,
|
||||
SearchFieldClearButton,
|
||||
} from "../index";
|
||||
import { Fieldset } from "../..";
|
||||
export default {
|
||||
title: "ds-react/form/search-field",
|
||||
component: SearchField,
|
||||
} as Meta;
|
||||
|
||||
export const All = () => {
|
||||
return (
|
||||
<>
|
||||
<h1>SearchField</h1>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
|
||||
<h1>SearchField w clearsearch</h1>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldInput clearSearch />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldClearButton>
|
||||
<Close /> <span>Tøm</span>
|
||||
</SearchFieldClearButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
|
||||
<h2>Hidelabel</h2>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
|
||||
<h2>SearchField small</h2>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
size="s"
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search />
|
||||
<span className="sr-only">Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
size="s"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search />
|
||||
<span className="sr-only">Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
|
||||
<h2>SearchField w error</h2>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
error="Errormsg"
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
error="Errormsg"
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
|
||||
<h2>SearchField in Fieldset</h2>
|
||||
<Fieldset legend="Filter" error="Fieldset-error-msg">
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
error="Errormsg"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldInput />
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
</SearchField>
|
||||
<SearchField
|
||||
label="Mollit eiusmod"
|
||||
description="Ea cupidatat eu sunt commodo"
|
||||
hideLabel
|
||||
>
|
||||
<SearchFieldButton>
|
||||
<Search /> <span>Søk</span>
|
||||
</SearchFieldButton>
|
||||
<SearchFieldInput />
|
||||
</SearchField>
|
||||
</Fieldset>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import { Meta, Canvas } from "@storybook/addon-docs";
|
||||
import { ConfirmationPanelExample } from "./live-examples";
|
||||
|
||||
<Meta title="ds-react/form/confirmation-panel/intro" />
|
||||
|
||||
# Hvordan ta i bruk ConfirmationPanel
|
||||
|
||||
```jsx
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
|
||||
ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<ConfirmationPanelExample />
|
||||
</Canvas>
|
||||
|
||||
## Størrelser
|
||||
|
||||
Kommer i størrelsene "m" og "s".
|
||||
|
||||
```jsx
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
size="s"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
|
||||
ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<ConfirmationPanelExample size="s" />
|
||||
</Canvas>
|
||||
|
||||
## Errors
|
||||
|
||||
```jsx
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
error="Laborum enim esse quis"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia minim
|
||||
ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<ConfirmationPanelExample error="Laborum enim esse quis" />
|
||||
</Canvas>
|
||||
@@ -0,0 +1,62 @@
|
||||
import React, { useState } from "react";
|
||||
import { ConfirmationPanel } from "../index";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import { Link } from "../..";
|
||||
export default {
|
||||
title: "ds-react/form/confirmation-panel",
|
||||
component: ConfirmationPanel,
|
||||
} as Meta;
|
||||
|
||||
export const All = () => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
return (
|
||||
<div>
|
||||
<h1>ConfirmationPanel</h1>
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
|
||||
minim ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
<h2>size s</h2>
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
size="s"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
|
||||
minim ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
<h3>error</h3>
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
error="Ex cupidatat do do do"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
|
||||
minim ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
<h3>error small</h3>
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
error="Ex cupidatat do do do"
|
||||
size="s"
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">testlink</Link> anim officia
|
||||
minim ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
<h2>Empty</h2>
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
></ConfirmationPanel>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import React, { useState } from "react";
|
||||
import { Fieldset } from "../index";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import { Button, Checkbox, CheckboxGroup } from "../../index";
|
||||
export default {
|
||||
title: "ds-react/form/uu-demo",
|
||||
component: Fieldset,
|
||||
} as Meta;
|
||||
|
||||
export const Demo1 = () => {
|
||||
const [error, setError] = useState(undefined);
|
||||
const [fieldsetError, setFieldsetError] = useState(undefined);
|
||||
const [groupError, setGroupError] = useState(undefined);
|
||||
const [propagation, setPropagation] = useState(true);
|
||||
return (
|
||||
<div>
|
||||
<h1>Nested-erros + aria-describedby</h1>
|
||||
<div>
|
||||
<Button
|
||||
style={{ marginBottom: "2rem" }}
|
||||
onClick={() => {
|
||||
!!fieldsetError
|
||||
? setFieldsetError(undefined)
|
||||
: setFieldsetError("Fieldset error message");
|
||||
}}
|
||||
>
|
||||
Toggle fieldset-error
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginBottom: "2rem" }}
|
||||
onClick={() => {
|
||||
!!groupError
|
||||
? setGroupError(undefined)
|
||||
: setGroupError("CheckboxGroup error message");
|
||||
}}
|
||||
>
|
||||
Toggle checkboxgroup-error
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginBottom: "2rem" }}
|
||||
onClick={() => {
|
||||
!!error ? setError(undefined) : setError("Textfield error message");
|
||||
}}
|
||||
>
|
||||
Toggle checkbox-error
|
||||
</Button>
|
||||
<Button
|
||||
style={{ marginBottom: "2rem" }}
|
||||
onClick={() => setPropagation(!propagation)}
|
||||
>
|
||||
Toggle errorPropagation
|
||||
</Button>
|
||||
</div>
|
||||
<Fieldset
|
||||
errorId="FIELDSET-ERROR"
|
||||
legend="Mollit eiusmod"
|
||||
error={fieldsetError}
|
||||
>
|
||||
<CheckboxGroup
|
||||
errorId="GROUP-ERROR"
|
||||
errorPropagation={propagation}
|
||||
error={groupError}
|
||||
legend="checkboxgroup"
|
||||
hideLegend
|
||||
>
|
||||
<Checkbox>Checkbox nr 1</Checkbox>
|
||||
<Checkbox errorId="CHECKBOX-ERROR" error={error}>
|
||||
Checkbox nr 2
|
||||
</Checkbox>
|
||||
<Checkbox>Checkbox nr 3</Checkbox>
|
||||
</CheckboxGroup>
|
||||
</Fieldset>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import React, { useState } from "react";
|
||||
import { ConfirmationPanel } from "..";
|
||||
import { Link } from "../..";
|
||||
|
||||
export const ConfirmationPanelExample = ({
|
||||
size = "m",
|
||||
error,
|
||||
}: {
|
||||
size: "m" | "s";
|
||||
error?: string;
|
||||
}) => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
return (
|
||||
<ConfirmationPanel
|
||||
checked={checked}
|
||||
onChange={() => setChecked(!checked)}
|
||||
label="Checkbox label text"
|
||||
size={size}
|
||||
error={error}
|
||||
>
|
||||
Ipsum voluptate pariatur <Link href="#123">demolink</Link> anim officia
|
||||
minim ut mollit voluptate exercitation nulla mollit.
|
||||
</ConfirmationPanel>
|
||||
);
|
||||
};
|
||||
@@ -1,28 +1,48 @@
|
||||
import { useContext } from "react";
|
||||
import cl from "classnames";
|
||||
import { FieldsetContext } from "./index";
|
||||
import useId from "./useId";
|
||||
import { useId } from "../index";
|
||||
|
||||
export interface FormFieldProps {
|
||||
/**
|
||||
* Error message for element
|
||||
*/
|
||||
error?: React.ReactNode;
|
||||
/**
|
||||
* Override internal errorId
|
||||
*/
|
||||
errorId?: string;
|
||||
/**
|
||||
* Changes font-size, padding and gaps
|
||||
*/
|
||||
size?: "m" | "s";
|
||||
/**
|
||||
* Disables element
|
||||
*/
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* Adds a description to extend labling of a field
|
||||
*/
|
||||
description?: React.ReactNode;
|
||||
/**
|
||||
* Override internal id
|
||||
*/
|
||||
id?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles props and their state for various form-fields in context with Fieldset
|
||||
*/
|
||||
export const useFormField = (props: FormFieldProps, prefix?: string) => {
|
||||
export const useFormField = (props: FormFieldProps, prefix: string) => {
|
||||
const { size, error, errorId: propErrorId } = props;
|
||||
|
||||
const fieldset = useContext(FieldsetContext);
|
||||
|
||||
const id = useId({ id: props.id, prefix: prefix ?? "" });
|
||||
const errorId = useId({ id: propErrorId, prefix: prefix + "Error" ?? "" });
|
||||
const inputDescriptionId = useId({ prefix: prefix + "Description" });
|
||||
const genId = useId();
|
||||
|
||||
const id = props.id ?? `${prefix}-${genId}`;
|
||||
const errorId = propErrorId ?? `${prefix}-error-${genId}`;
|
||||
const inputDescriptionId = `${prefix}-description-${genId}`;
|
||||
|
||||
const disabled = fieldset?.disabled || props.disabled;
|
||||
const hasError: boolean = !disabled && !!(error || fieldset?.error);
|
||||
@@ -40,6 +60,8 @@ export const useFormField = (props: FormFieldProps, prefix?: string) => {
|
||||
"aria-describedby":
|
||||
cl(props["aria-describedby"], {
|
||||
[inputDescriptionId]: !!props?.description,
|
||||
[errorId]: showErrorMsg,
|
||||
[fieldset?.errorId ?? ""]: hasError && !!fieldset?.error,
|
||||
}) || undefined,
|
||||
disabled,
|
||||
},
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import ShortUuid from "short-uuid";
|
||||
|
||||
const useId = (props?: { id?: string; prefix?: string }): string => {
|
||||
const { id = null, prefix = "" } = props ? props : {};
|
||||
const [localId, setlocalId] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
setlocalId(`${prefix}-${ShortUuid.generate()}`);
|
||||
}, [prefix]);
|
||||
|
||||
return id ?? localId;
|
||||
};
|
||||
|
||||
export default useId;
|
||||
@@ -4,11 +4,7 @@ import cl from "classnames";
|
||||
type Column = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
export interface CellProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Component content
|
||||
* Cell content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
|
||||
@@ -3,13 +3,9 @@ import cl from "classnames";
|
||||
|
||||
export interface GridProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Component content
|
||||
* Collection of <Cell>-elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
const Grid = forwardRef<HTMLDivElement, GridProps>(
|
||||
({ children, className, ...rest }, ref) => (
|
||||
|
||||
@@ -6,10 +6,6 @@ export interface HeaderProps extends HTMLAttributes<HTMLDivElement> {
|
||||
* Header title
|
||||
*/
|
||||
children: string;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Pictogram placed in header
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from "./accordion";
|
||||
export * from "./accordion-anchor-menu";
|
||||
export * from "./accordion-menu";
|
||||
export * from "./alert";
|
||||
export * from "./button";
|
||||
@@ -10,7 +9,6 @@ export * from "./form";
|
||||
export * from "./grid";
|
||||
export * from "./header";
|
||||
export * from "./internal-header";
|
||||
export * from "./layouts";
|
||||
export * from "./link";
|
||||
export * from "./link-panel";
|
||||
export * from "./loader";
|
||||
|
||||
@@ -6,10 +6,6 @@ export interface InternalHeaderProps extends HTMLAttributes<HTMLElement> {
|
||||
* Component content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const InternalHeader = forwardRef<HTMLElement, InternalHeaderProps>(
|
||||
|
||||
@@ -6,10 +6,6 @@ export interface InternalHeaderTitleProps extends HTMLAttributes<HTMLElement> {
|
||||
* Component content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Tag this component will use. Usefull for defining a button/link
|
||||
* @default "h1"
|
||||
|
||||
@@ -3,10 +3,6 @@ import cl from "classnames";
|
||||
|
||||
export interface InternalHeaderUserProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* user name
|
||||
*/
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as ProductPageLayout } from "./product-page/ProductPageLayout";
|
||||
export { default as ProductPagePanel } from "./product-page/ProductPagePanel";
|
||||
export { default as ProductPageSection } from "./product-page/ProductPageSection";
|
||||
@@ -1,61 +0,0 @@
|
||||
import cl from "classnames";
|
||||
import React, { Children, forwardRef, HTMLAttributes, useEffect } from "react";
|
||||
import { ContentContainer, Title } from "../../index";
|
||||
|
||||
const cls = (className, columns) =>
|
||||
cl(
|
||||
"navds-layout__container",
|
||||
`navds-layout__container--${columns}-columns`,
|
||||
className
|
||||
);
|
||||
|
||||
export interface ProductPageLayoutProps extends HTMLAttributes<HTMLElement> {
|
||||
title: string;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ProductPageLayout = forwardRef<HTMLDivElement, ProductPageLayoutProps>(
|
||||
({ children, title, className, ...rest }, ref) => {
|
||||
const columns = Children.toArray(children).length;
|
||||
|
||||
useEffect(() => {
|
||||
const layoutBody = document.getElementById("navds-layout-body");
|
||||
layoutBody?.classList.add(`navds-layout__body--${columns}-columns`);
|
||||
document.body.classList.add("navds-layout__body--white");
|
||||
return () => {
|
||||
layoutBody?.classList.remove(`navds-layout__body--${columns}-columns`);
|
||||
document.body.classList.remove("navds-layout__body--white");
|
||||
};
|
||||
}, [columns]);
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<div id={"navds-layout-header"} className={"navds-layout__header"}>
|
||||
<ContentContainer>
|
||||
<div className={cls(className, columns)} {...rest}>
|
||||
<div className={cl("navds-layout__header-content")}>
|
||||
<Title
|
||||
size="2xl"
|
||||
className={cl("navds-layout__header-title")}
|
||||
level={1}
|
||||
>
|
||||
{title}
|
||||
</Title>
|
||||
</div>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
<div id={"navds-layout-body"} className={"navds-layout__body"}>
|
||||
<ContentContainer>
|
||||
<div className={cls(className, columns)} {...rest}>
|
||||
{children}
|
||||
</div>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ProductPageLayout;
|
||||
@@ -1,73 +0,0 @@
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { forwardRef, ReactNode } from "react";
|
||||
import cl from "classnames";
|
||||
import { Title, CopyToClipboard } from "../../";
|
||||
import { Attachment } from "@navikt/ds-icons";
|
||||
|
||||
export interface ProductPagePanelProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
anchor: string;
|
||||
className?: string;
|
||||
title: string;
|
||||
icon?: ReactNode;
|
||||
highlight?: boolean;
|
||||
whiteBackground?: boolean;
|
||||
}
|
||||
|
||||
const ProductPagePanel = forwardRef<HTMLDivElement, ProductPagePanelProps>(
|
||||
({ children, className, title, highlight, icon, anchor, ...rest }, ref) => {
|
||||
const copyRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const header = document.getElementById("navds-layout-body");
|
||||
header?.classList.add("navds-layout__body--padding");
|
||||
}, []);
|
||||
|
||||
const getLink = () => {
|
||||
const { href, hash } = window.location;
|
||||
const urlWithoutHash = href.replace(hash, "");
|
||||
return `${urlWithoutHash}#${anchor}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-layout__panel",
|
||||
icon && "navds-layout__panel--icon-margin",
|
||||
highlight && "navds-layout__panel--highlight",
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<div className="navds-layout__panel-anchor">
|
||||
<div
|
||||
id={anchor}
|
||||
className={cl("navds-layout__panel-anchor--child", {
|
||||
"navds-layout__panel-anchor--child--icon": !!icon,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
{icon && <div className={"navds-layout__panel-icon"}>{icon}</div>}
|
||||
<Title size={"xl"} className={"navds-layout__panel-title"} level={2}>
|
||||
{title}
|
||||
</Title>
|
||||
|
||||
<CopyToClipboard
|
||||
className="navds-layout__panel-copy"
|
||||
ref={copyRef}
|
||||
text={getLink()}
|
||||
label="Kopierte lenke til panel"
|
||||
icon={<Attachment />}
|
||||
>
|
||||
Kopier lenke
|
||||
</CopyToClipboard>
|
||||
|
||||
<div className={"navds-layout__panel-content"}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ProductPagePanel;
|
||||
@@ -1,46 +0,0 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface ProductPageSectionProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
left?: boolean;
|
||||
right?: boolean;
|
||||
whiteBackground?: boolean;
|
||||
withPadding?: boolean;
|
||||
sticky?: boolean;
|
||||
}
|
||||
|
||||
const ProductPageSection = forwardRef<HTMLDivElement, ProductPageSectionProps>(
|
||||
(
|
||||
{
|
||||
left,
|
||||
right,
|
||||
children,
|
||||
whiteBackground = true,
|
||||
withPadding = true,
|
||||
sticky,
|
||||
className,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-layout__section",
|
||||
left && "navds-layout__section--left",
|
||||
right && "navds-layout__section--right",
|
||||
!left && !right && "navds-layout__section--main",
|
||||
whiteBackground && "navds-layout__section--white",
|
||||
withPadding && "navds-layout__section--padding",
|
||||
sticky && "navds-layout__section--sticky",
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
export default ProductPageSection;
|
||||
@@ -1,22 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Button, Link } from "../../../../index";
|
||||
|
||||
export const Left = () => (
|
||||
<ul className={"navds-story-menu"}>
|
||||
<li>
|
||||
<Link href={"#leo-quis"}>Leo quis</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#proin-accumsan"}>Proin accumsan</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#nulla-pariatur"}>Nulla pariatur?</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#maecenas-in-pretium"}>Maecenas in pretium</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Button>Søk ...</Button>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
@@ -1,133 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Button, Cell, Grid, Title, Link, BodyLong } from "../../../../index";
|
||||
|
||||
export const Main = ({ title = true }) => (
|
||||
<>
|
||||
<MainOne title={title} />
|
||||
<MainTwo title={title} />
|
||||
<MainThree title={title} />
|
||||
</>
|
||||
);
|
||||
|
||||
export const MainOne = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Title level={1} size={"xl"} id={"leo-quis"}>
|
||||
Leo quis
|
||||
</Title>
|
||||
)}
|
||||
<BodyLong>
|
||||
Sed ullamcorper quam eget lorem volutpat, quis cursus risus fermentum.
|
||||
Quisque varius ornare nulla, ut condimentum sapien dapibus non. Nullam
|
||||
eget interdum nibh
|
||||
</BodyLong>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MainTwo = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Title level={1} size={"xl"} id={"proin-accumsan"}>
|
||||
Proin accumsan
|
||||
</Title>
|
||||
)}
|
||||
<BodyLong className={"section"}>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
|
||||
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo
|
||||
inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
</BodyLong>
|
||||
<Grid className={"section"}>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Ea voluptate</Link>
|
||||
</Cell>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Quis autem</Link>
|
||||
</Cell>
|
||||
</Grid>
|
||||
<BodyLong className={"section"}>
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
|
||||
consectetur, adipisci velit, sed quia non numquam eius modi tempora.
|
||||
</BodyLong>
|
||||
<Title level={2} size={"l"} id={"nulla-pariatur"}>
|
||||
Nulla pariatur?
|
||||
</Title>
|
||||
<BodyLong className={"section"}>
|
||||
Etiam viverra neque sit amet libero dapibus tincidunt. Pellentesque quis
|
||||
imperdiet erat. Morbi sodales bibendum volutpat.
|
||||
</BodyLong>
|
||||
<table className={"section tabell tabell--stripet"}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Fornavn</th>
|
||||
<th>Etternavn</th>
|
||||
<th>Rolle</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Jean-Luc</td>
|
||||
<td>Picard</td>
|
||||
<td>Kaptein</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>William</td>
|
||||
<td>Riker</td>
|
||||
<td>Kommandør</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Geordi</td>
|
||||
<td>La Forge</td>
|
||||
<td>Sjefsingeniør</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<BodyLong className={"section"}>
|
||||
Curabitur a purus pretium, condimentum magna ac, pellentesque diam. Nulla
|
||||
facilisi. Nullam consequat, dui sed bibendum faucibus, metus mauris
|
||||
commodo tortor.
|
||||
</BodyLong>
|
||||
<Title level={2} size={"l"} id={"luctus-justo"}>
|
||||
Luctus justo
|
||||
</Title>
|
||||
<BodyLong className={"section"}>
|
||||
Nunc eget consectetur felis, id scelerisque sapien. Ut id feugiat nulla,
|
||||
ut cursus sem. In viverra felis vitae aliquet finibus.
|
||||
</BodyLong>
|
||||
<Button>Søk ...</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MainThree = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Title level={1} size={"xl"} id={"maecenas-in-pretium"}>
|
||||
Maecenas in pretium
|
||||
</Title>
|
||||
)}
|
||||
<BodyLong>
|
||||
Sed ullamcorper quam eget lorem volutpat, quis cursus risus fermentum.
|
||||
Quisque varius ornare nulla, ut condimentum sapien dapibus non. Nullam
|
||||
eget interdum nibh
|
||||
</BodyLong>
|
||||
<BodyLong>
|
||||
Cras tempor eros sed dapibus egestas. Curabitur bibendum quam quis lectus
|
||||
pretium lacinia. Nunc consequat ac augue quis laoreet. Donec porta, erat
|
||||
vitae blandit egestas, arcu metus pharetra nulla, et laoreet risus purus
|
||||
convallis turpis.
|
||||
</BodyLong>
|
||||
<BodyLong>
|
||||
Suspendisse potenti. Praesent at elit interdum, porttitor sem eget,
|
||||
blandit dolor. Nunc eget consectetur felis, id scelerisque sapien. Ut id
|
||||
feugiat nulla, ut cursus sem. In viverra felis vitae aliquet finibus.
|
||||
</BodyLong>
|
||||
<BodyLong>
|
||||
Vivamus id mi lectus. Duis ac augue magna. Aliquam ut euismod dui. Duis
|
||||
consectetur, magna a malesuada tempus, elit urna fermentum arcu, at
|
||||
porttitor magna sapien id enim.
|
||||
</BodyLong>
|
||||
</div>
|
||||
);
|
||||
@@ -1,8 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Accordion } from "../../../../index";
|
||||
|
||||
export const Right = () => (
|
||||
<div>
|
||||
<Accordion heading={"Snareveier"}>Test</Accordion>
|
||||
</div>
|
||||
);
|
||||
@@ -1,12 +0,0 @@
|
||||
.navds-story-menu {
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.navds-story-menu li:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.navds-story-section {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Meta, Canvas } from "@storybook/addon-docs";
|
||||
|
||||
<Meta title="ds-react/layouts/intro" />
|
||||
|
||||
# Layouts
|
||||
|
||||
Komponenten og storybook-stories her er utdaterte og anbefales ikke å bruke, før
|
||||
react-pakken er publisert så kommer disse til å forgå store endringer og evt fjernes fra pakken.
|
||||
@@ -1,90 +0,0 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
ProductPageLayout as Layout,
|
||||
ProductPageSection as Section,
|
||||
ProductPagePanel as Panel,
|
||||
} from "../../index";
|
||||
import { Left } from "./components/sections/Left";
|
||||
import { Main, MainOne, MainTwo, MainThree } from "./components/sections/Main";
|
||||
import { Right } from "./components/sections/Right";
|
||||
import { LightBulb, Telephone } from "@navikt/ds-icons";
|
||||
import "./components/styles.css";
|
||||
|
||||
export default {
|
||||
title: "ds-react/layouts/ProductPage",
|
||||
component: Layout,
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
};
|
||||
|
||||
const title = "Nunc et lorem";
|
||||
export const ThreeColumns = () => (
|
||||
<Layout title={title}>
|
||||
<Section left sticky>
|
||||
<Left />
|
||||
</Section>
|
||||
<Section whiteBackground={false} withPadding={false}>
|
||||
<Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</Panel>
|
||||
<Panel title={"Proin accumsan"} anchor={"proin-accumsan"}>
|
||||
<MainTwo title={false} />
|
||||
</Panel>
|
||||
<Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</Panel>
|
||||
</Section>
|
||||
<Section right sticky>
|
||||
<Right />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export const TwoColumnsLeft = () => (
|
||||
<Layout title={title}>
|
||||
<Section left sticky>
|
||||
<Left />
|
||||
<Left />
|
||||
</Section>
|
||||
<Section>
|
||||
<Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</Panel>
|
||||
<Main />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export const TwoColumnsRight = () => (
|
||||
<Layout title={title}>
|
||||
<Section>
|
||||
<Main />
|
||||
</Section>
|
||||
<Section right sticky>
|
||||
<Right />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export const OneColumn = () => (
|
||||
<Layout title={title}>
|
||||
<Section>
|
||||
<Main />
|
||||
</Section>
|
||||
</Layout>
|
||||
);
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "../util";
|
||||
import { Panel } from "../index";
|
||||
import { Panel } from "..";
|
||||
import { Next } from "@navikt/ds-icons";
|
||||
import cl from "classnames";
|
||||
|
||||
@@ -8,9 +8,13 @@ export type LinkPanelType = OverridableComponent<LinkPanelProps>;
|
||||
|
||||
export interface LinkPanelProps {
|
||||
props: {
|
||||
/**
|
||||
* Panel content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
noHeading?: boolean;
|
||||
/**
|
||||
* Toggles border on panel
|
||||
*/
|
||||
border?: boolean;
|
||||
} & React.HTMLAttributes<HTMLAnchorElement>;
|
||||
defaultComponent: "a";
|
||||
|
||||
@@ -4,13 +4,9 @@ import cl from "classnames";
|
||||
export interface LinkProps
|
||||
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
/**
|
||||
* Component content
|
||||
* Link text
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Link anchor should direct to
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from "react";
|
||||
import { Link } from "../index";
|
||||
import { Alert } from "../..";
|
||||
import { Link } from "..";
|
||||
import { Add } from "@navikt/ds-icons";
|
||||
import { ConfirmationPanel } from "../../form";
|
||||
export default {
|
||||
title: "ds-react/link",
|
||||
component: Link,
|
||||
@@ -11,16 +13,41 @@ export const All = () => {
|
||||
<>
|
||||
<h1>Link</h1>
|
||||
<Link href="#">Dette er en tekstlenke</Link>
|
||||
<h1>Icon after</h1>
|
||||
<h2>Icon after</h2>
|
||||
<Link href="#">
|
||||
<span>Dette er en tekstlenke</span>
|
||||
<Add />
|
||||
</Link>
|
||||
<h1>Icon before</h1>
|
||||
<h2>Icon before</h2>
|
||||
<Link href="#">
|
||||
<Add />
|
||||
<span>Dette er en tekstlenke </span>
|
||||
</Link>
|
||||
<h2>På farget bakgrunn</h2>
|
||||
<Alert variant="error">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</Alert>
|
||||
<Alert variant="info">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</Alert>
|
||||
<Alert variant="success">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</Alert>
|
||||
<Alert variant="warning">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</Alert>
|
||||
<ConfirmationPanel label="Samtykke?" checked={false} error="feilmelding">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</ConfirmationPanel>
|
||||
<ConfirmationPanel label="Samtykke?" checked error="feilmelding">
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</ConfirmationPanel>
|
||||
<ConfirmationPanel label="Samtykke?" checked={false}>
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</ConfirmationPanel>
|
||||
<ConfirmationPanel label="Samtykke?" checked>
|
||||
Her er en <Link href="#about">lenke</Link> på farget bakgrunn
|
||||
</ConfirmationPanel>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,12 +1,8 @@
|
||||
import React, { forwardRef, SVGProps, useRef } from "react";
|
||||
import React, { forwardRef, SVGProps } from "react";
|
||||
import cl from "classnames";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useId } from "..";
|
||||
|
||||
export interface LoaderProps extends SVGProps<SVGSVGElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Changes sizing
|
||||
* 64px | 40px | 32px | 24px | 20px | 16px
|
||||
@@ -43,11 +39,11 @@ const Loader = forwardRef<SVGSVGElement, LoaderProps>(
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const internalId = useRef(uuidv4());
|
||||
const internalId = useId(id);
|
||||
|
||||
return (
|
||||
<svg
|
||||
aria-labelledby={id ?? internalId.current}
|
||||
aria-labelledby={internalId}
|
||||
ref={ref}
|
||||
className={cl("navds-loader", className, `navds-loader--${size}`, {
|
||||
"navds-loader--transparent": transparent,
|
||||
@@ -60,7 +56,7 @@ const Loader = forwardRef<SVGSVGElement, LoaderProps>(
|
||||
preserveAspectRatio="xMidYMid"
|
||||
{...rest}
|
||||
>
|
||||
<title id={id ?? internalId.current}>{title}</title>
|
||||
<title id={internalId}>{title}</title>
|
||||
<circle
|
||||
className="navds-loader__background"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
Loaded 100 of 289 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user