mirror of
https://github.com/navikt/aksel.git
synced 2026-10-14 09:42:02 +00:00
Compare commits
49
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5ecd66a57 | ||
|
|
78817fef45 | ||
|
|
38357b1a2e | ||
|
|
65c17db2e5 | ||
|
|
59e88773d1 | ||
|
|
f175d0f781 | ||
|
|
18419f7d98 | ||
|
|
f63a7ec36d | ||
|
|
107489bd3f | ||
|
|
792962592f | ||
|
|
4a02a1987c | ||
|
|
700943b4a5 | ||
|
|
521c982457 | ||
|
|
8c17099087 | ||
|
|
29241a7153 | ||
|
|
7e4ee40a7f | ||
|
|
2be97970d6 | ||
|
|
5b3c1f33c4 | ||
|
|
f44ff44410 | ||
|
|
855669538e | ||
|
|
3d830dc123 | ||
|
|
dcca2a9560 | ||
|
|
26fb028f07 | ||
|
|
d928769d6f | ||
|
|
e96d33d13e | ||
|
|
00ebe1c18b | ||
|
|
53be894ad0 | ||
|
|
614946097e | ||
|
|
74ac20ea7c | ||
|
|
d299137774 | ||
|
|
304f6d6a12 | ||
|
|
bf6952c2b2 | ||
|
|
7705dd4ae5 | ||
|
|
d9ce1299d9 | ||
|
|
0890eed59e | ||
|
|
dbd7150762 | ||
|
|
58933e2584 | ||
|
|
86279919c8 | ||
|
|
8866572e69 | ||
|
|
a1accdbd95 | ||
|
|
fdfdebfa99 | ||
|
|
56abe568e2 | ||
|
|
34acbb87a5 | ||
|
|
fd479e3160 | ||
|
|
03ca21b4f6 | ||
|
|
e7804297bf | ||
|
|
a246c9d707 | ||
|
|
d3fb3d4d96 | ||
|
|
d734d3071b |
No files matched your search
@@ -11,6 +11,10 @@ on:
|
||||
paths:
|
||||
- "@navikt/**"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
visual_regression_test:
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'ignore-chromatic') }}
|
||||
@@ -55,7 +59,9 @@ jobs:
|
||||
exitZeroOnChanges: false
|
||||
buildScriptName: "build:storybook"
|
||||
onlyChanged: true
|
||||
untraced: "**/package.json|yarn.lock|**/*.md"
|
||||
externals: \@navikt/core/css/**/*.css
|
||||
traceChanged: true
|
||||
env:
|
||||
STORYBOOK_GITHUB_SHA: ${{ github.sha }}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".changeset/**"
|
||||
- "@navikt/**"
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
name: Update article views
|
||||
name: Redeploy Naisjob (update-article-views)
|
||||
on:
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
execute:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: # TODO: remove once merged
|
||||
permissions:
|
||||
packages: "write"
|
||||
contents: "read"
|
||||
id-token: "write"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: gp-popular-articles # TODO: remove once merged
|
||||
fetch-depth: 1
|
||||
- uses: denoland/setup-deno@v1
|
||||
with:
|
||||
@@ -31,7 +30,7 @@ jobs:
|
||||
with:
|
||||
team: designsystem
|
||||
push_image: true
|
||||
dockerfile: scripts/article-views/Dockerfile
|
||||
dockerfile: scripts/article-views/Dockerfile.update-article-views
|
||||
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
|
||||
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
|
||||
- name: start naisjob prod-gcp
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
**/nais-dev.yaml
|
||||
**/nais-prod.yaml
|
||||
**/nais*.yaml
|
||||
**/nais*.yml
|
||||
**/codemod/**/tests/**/*.js
|
||||
node_modules
|
||||
.next
|
||||
|
||||
@@ -10,7 +10,7 @@ export const parameters = {
|
||||
"Getting started",
|
||||
"ds-react",
|
||||
["Primitives"],
|
||||
["Default"],
|
||||
["Default", "Controls"],
|
||||
"Aksel-icons",
|
||||
],
|
||||
},
|
||||
|
||||
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"denoland.vscode-deno",
|
||||
"esbenp.prettier-vscode",
|
||||
"github.vscode-github-actions",
|
||||
"ms-playwright.playwright",
|
||||
"sanity-io.vscode-sanity",
|
||||
"stylelint.vscode-stylelint",
|
||||
"vunguyentuan.vscode-css-variables",
|
||||
"bradlc.vscode-tailwindcss"
|
||||
]
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"cssVariables.lookupFiles": ["@navikt/core/css/dist/index.css"],
|
||||
"eslint.problems.shortenToSingleLine": true,
|
||||
"deno.enablePaths": ["scripts/article-views", "scripts/changelog"],
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"deno.lint": true,
|
||||
"files.watcherExclude": {
|
||||
"**/.yarn/**": true,
|
||||
"**/dist": true,
|
||||
"**/esm": true,
|
||||
"**/cjs": true
|
||||
},
|
||||
"playwright.reuseBrowser": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/aksel-icons
|
||||
|
||||
## 5.18.2
|
||||
|
||||
## 5.18.1
|
||||
|
||||
## 5.18.0
|
||||
|
||||
## 5.17.5
|
||||
|
||||
## 5.17.4
|
||||
|
||||
## 5.17.3
|
||||
|
||||
## 5.17.2
|
||||
|
||||
## 5.17.1
|
||||
|
||||
## 5.17.0
|
||||
|
||||
## 5.16.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel-icons",
|
||||
"version": "5.16.0",
|
||||
"version": "5.18.2",
|
||||
"author": "Aksel | NAV",
|
||||
"homepage": "https://aksel.nav.no/ikoner",
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/aksel-stylelint
|
||||
|
||||
## 5.18.2
|
||||
|
||||
## 5.18.1
|
||||
|
||||
## 5.18.0
|
||||
|
||||
## 5.17.5
|
||||
|
||||
## 5.17.4
|
||||
|
||||
## 5.17.3
|
||||
|
||||
## 5.17.2
|
||||
|
||||
## 5.17.1
|
||||
|
||||
## 5.17.0
|
||||
|
||||
## 5.16.0
|
||||
|
||||
## 5.15.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel-stylelint",
|
||||
"version": "5.16.0",
|
||||
"version": "5.18.2",
|
||||
"author": "Aksel | NAV",
|
||||
"homepage": "https://aksel.nav.no/grunnleggende/kode/stylelint",
|
||||
"repository": {
|
||||
@@ -35,8 +35,8 @@
|
||||
"dev": "yarn watch:lint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-css": "^5.16.0",
|
||||
"@navikt/ds-tokens": "^5.16.0",
|
||||
"@navikt/ds-css": "^5.18.2",
|
||||
"@navikt/ds-tokens": "^5.18.2",
|
||||
"@types/jest": "^29.0.0",
|
||||
"concurrently": "7.2.1",
|
||||
"copyfiles": "2.4.1",
|
||||
|
||||
@@ -1,5 +1,68 @@
|
||||
# @navikt/aksel
|
||||
|
||||
## 5.18.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.18.2
|
||||
|
||||
## 5.18.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.18.1
|
||||
|
||||
## 5.18.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.18.0
|
||||
|
||||
## 5.17.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`dcca2a956`](https://github.com/navikt/aksel/commit/dcca2a95600152cb84c3b79ba5bb3894ac63e881)]:
|
||||
- @navikt/ds-css@5.17.5
|
||||
|
||||
## 5.17.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.17.4
|
||||
|
||||
## 5.17.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.17.3
|
||||
|
||||
## 5.17.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`fdfdebfa9`](https://github.com/navikt/aksel/commit/fdfdebfa99e594099bcea7b5addde9cdabc727a7)]:
|
||||
- @navikt/ds-css@5.17.2
|
||||
|
||||
## 5.17.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.17.1
|
||||
|
||||
## 5.17.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`d3fb3d4d9`](https://github.com/navikt/aksel/commit/d3fb3d4d962fac028e7d803dc7c50315d48b4987)]:
|
||||
- @navikt/ds-css@5.17.0
|
||||
|
||||
## 5.16.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel",
|
||||
"version": "5.16.0",
|
||||
"version": "5.18.2",
|
||||
"description": "Aksel command line interface. Handles css-imports, codemods and more",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"homepage": "https://aksel.nav.no/grunnleggende/kode/kommandolinje",
|
||||
"dependencies": {
|
||||
"@navikt/ds-css": "5.16.0",
|
||||
"@navikt/ds-css": "5.18.2",
|
||||
"axios": "1.6.0",
|
||||
"chalk": "4.1.0",
|
||||
"clipboardy": "^2.3.0",
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
# @navikt/ds-css
|
||||
|
||||
## 5.18.2
|
||||
|
||||
## 5.18.1
|
||||
|
||||
## 5.18.0
|
||||
|
||||
## 5.17.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ExpansionCard: Padding-top for Content er justert opp 8px (medium) og 4px (small) ([#2699](https://github.com/navikt/aksel/pull/2699))
|
||||
|
||||
## 5.17.4
|
||||
|
||||
## 5.17.3
|
||||
|
||||
## 5.17.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Checkbox: I noen edgecaser ved bruk av shadow-dom ble ikke checkmark sentert i Checkbox ([#2682](https://github.com/navikt/aksel/pull/2682))
|
||||
|
||||
## 5.17.1
|
||||
|
||||
## 5.17.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Høykontrast: Komponenter støtter nå standard høykontrast-modus på Windows ([#2680](https://github.com/navikt/aksel/pull/2680))
|
||||
|
||||
## 5.16.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -74,7 +74,8 @@
|
||||
}
|
||||
|
||||
.navds-accordion__header:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 3px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
border-radius: var(--a-border-radius-large);
|
||||
}
|
||||
@@ -185,3 +186,17 @@
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-accordion__header {
|
||||
border: 1px solid buttonborder;
|
||||
background-color: canvas;
|
||||
color: canvastext;
|
||||
}
|
||||
|
||||
.navds-accordion__header:hover {
|
||||
background-color: canvas;
|
||||
border: 1px solid highlight;
|
||||
color: highlight;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
font-size: 1.5rem;
|
||||
align-self: flex-start;
|
||||
height: var(--a-font-line-height-xlarge);
|
||||
background: radial-gradient(circle, var(--a-surface-default) 50%, 0, transparent);
|
||||
background: radial-gradient(circle, var(--a-surface-default) 47%, 0, transparent);
|
||||
}
|
||||
|
||||
.navds-alert--small > .navds-alert__icon {
|
||||
@@ -64,7 +64,7 @@
|
||||
}
|
||||
|
||||
.navds-alert--warning > .navds-alert__icon {
|
||||
background: radial-gradient(circle at 50% 57%, var(--a-surface-default) 32%, 0, transparent);
|
||||
background: radial-gradient(circle at 50% 57%, var(--a-surface-default) 30%, 0, transparent);
|
||||
color: var(--ac-alert-icon-warning-color, var(--a-icon-warning));
|
||||
}
|
||||
|
||||
@@ -99,3 +99,11 @@
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-alert {
|
||||
border: 1px solid canvastext;
|
||||
background-color: canvas;
|
||||
color: canvastext;
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,8 @@
|
||||
}
|
||||
|
||||
.navds-button:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
|
||||
@@ -129,6 +130,16 @@
|
||||
background-color: var(--ac-button-primary-bg, var(--__ac-button-primary-bg, var(--a-surface-action)));
|
||||
color: var(--ac-button-primary-text, var(--__ac-button-primary-text, var(--a-text-on-action)));
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.navds-button.navds-button--primary {
|
||||
background-color: highlight;
|
||||
color: highlighttext;
|
||||
}
|
||||
|
||||
.navds-button.navds-button--primary span {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-button--primary:hover {
|
||||
background-color: var(--ac-button-primary-hover-bg, var(--__ac-button-primary-hover-bg, var(--a-surface-action-hover)));
|
||||
@@ -139,10 +150,17 @@
|
||||
}
|
||||
|
||||
.navds-button--primary:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px var(--ac-button-primary-focus-border, var(--__ac-button-primary-focus-border, var(--a-surface-default))),
|
||||
var(--a-shadow-focus);
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.navds-button--primary:focus-visible {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-button--primary:focus {
|
||||
@@ -478,6 +496,7 @@
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
/* Loader overrides */
|
||||
.navds-button .navds-loader .navds-loader__foreground {
|
||||
stroke: var(--ac-button-loader-stroke, currentColor);
|
||||
}
|
||||
@@ -486,3 +505,36 @@
|
||||
.navds-button--danger .navds-loader .navds-loader__background {
|
||||
stroke: var(--ac-button-primary-loader-stroke-bg, rgb(255 255 255 / 0.3));
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-button:not(.navds-button--loading):where(:disabled, .navds-button--disabled) {
|
||||
opacity: 1;
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.navds-button {
|
||||
border: 1px solid transparent;
|
||||
color: ButtonText;
|
||||
background-color: ButtonFace;
|
||||
}
|
||||
|
||||
.navds-button:hover {
|
||||
background-color: highlighttext;
|
||||
border-color: highlight;
|
||||
color: highlight;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-button:hover span {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-button .navds-loader .navds-loader__foreground {
|
||||
stroke: canvas;
|
||||
}
|
||||
|
||||
.navds-button--primary .navds-loader .navds-loader__background,
|
||||
.navds-button--danger .navds-loader .navds-loader__background {
|
||||
stroke: canvastext;
|
||||
}
|
||||
}
|
||||
@@ -105,3 +105,16 @@
|
||||
.navds-chat--right .navds-chat__top-text--left {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-chat__bubble,
|
||||
.navds-chat__avatar {
|
||||
border: 1px solid canvastext;
|
||||
background-color: canvas;
|
||||
color: canvastext;
|
||||
}
|
||||
|
||||
.navds-chat__avatar svg {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
}
|
||||
@@ -191,3 +191,44 @@
|
||||
.navds-chips--small .navds-chips--icon-right {
|
||||
padding-right: var(--a-spacing-05);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-chips__chip {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.navds-chips__chip:hover {
|
||||
background-color: highlighttext;
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-chips__chip:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-chips__chip:where([aria-pressed="true"], :active, :hover) > span {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-chips__toggle:active {
|
||||
background-color: highlight;
|
||||
color: highlighttext;
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"] {
|
||||
background-color: selecteditem;
|
||||
color: selecteditemtext;
|
||||
border: 1px solid selecteditem;
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"]:hover {
|
||||
background-color: selecteditemtext;
|
||||
color: selecteditem;
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"]:active {
|
||||
background-color: highlight;
|
||||
color: highlighttext;
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,21 @@
|
||||
place-content: center;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-copybutton {
|
||||
background-color: ButtonFace;
|
||||
border-color: ButtonText;
|
||||
border: solid 1px ButtonText;
|
||||
color: ButtonText;
|
||||
}
|
||||
|
||||
.navds-copybutton.navds-copybutton:focus-visible {
|
||||
box-shadow: none;
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-copybutton--icon-right {
|
||||
--__ac-copybutton-padding: var(--a-spacing-3) var(--a-spacing-4) var(--a-spacing-3) var(--a-spacing-5);
|
||||
}
|
||||
@@ -201,3 +216,10 @@
|
||||
cursor: not-allowed;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-copybutton:where(:disabled) {
|
||||
opacity: 1;
|
||||
border-color: GrayText;
|
||||
}
|
||||
}
|
||||
@@ -58,13 +58,15 @@
|
||||
}
|
||||
|
||||
.navds-dropdown__item:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: -2px;
|
||||
box-shadow: inset 0 0 0 2px var(--a-border-focus);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-dropdown__item:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: -2px;
|
||||
box-shadow: inset 0 0 0 2px var(--a-border-focus);
|
||||
}
|
||||
}
|
||||
@@ -75,3 +77,14 @@
|
||||
background: transparent;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-dropdown__item:hover {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-dropdown__item:disabled {
|
||||
opacity: 1;
|
||||
color: graytext;
|
||||
}
|
||||
}
|
||||
@@ -145,13 +145,13 @@
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-button:focus-visible {
|
||||
outline: none;
|
||||
outline: 3px solid transparent;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-expansioncard__header-button:focus {
|
||||
outline: none;
|
||||
outline: 3px solid transparent;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@
|
||||
* Content *
|
||||
*************************/
|
||||
.navds-expansioncard__content {
|
||||
--__ac-expansioncard-padding-block: var(--a-spacing-3);
|
||||
--__ac-expansioncard-padding-block: var(--a-spacing-5);
|
||||
|
||||
border-end-end-radius: var(--__ac-expansioncard-border-radius);
|
||||
border-end-start-radius: var(--__ac-expansioncard-border-radius);
|
||||
@@ -187,6 +187,10 @@
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.navds-expansioncard--small .navds-expansioncard__content {
|
||||
--__ac-expansioncard-padding-block: var(--a-spacing-4);
|
||||
}
|
||||
|
||||
.navds-expansioncard__content--closed {
|
||||
display: none;
|
||||
}
|
||||
@@ -221,3 +225,11 @@
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-expansioncard:hover {
|
||||
--__ac-expansioncard-border-color: highlight;
|
||||
|
||||
outline: 1px solid highlight;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
.navds-combobox--error
|
||||
.navds-text-field__input:not(:hover):not(:disabled):not(.navds-combobox__wrapper-inner--virtually-unfocused):focus-within {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--ac-combobox-error-border, var(--a-border-danger)),
|
||||
var(--a-shadow-focus);
|
||||
@@ -94,10 +96,13 @@
|
||||
0 0 0 1px var(--a-surface-default) inset,
|
||||
var(--a-shadow-focus);
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: 3px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-combobox__wrapper-inner:has(.navds-combobox__input:focus-visible).navds-combobox__wrapper-inner--virtually-unfocused {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
@@ -112,10 +117,13 @@
|
||||
0 0 0 1px var(--a-surface-default) inset,
|
||||
var(--a-shadow-focus);
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: 3px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-combobox__wrapper-inner:has(.navds-combobox__input:focus).navds-combobox__wrapper-inner--virtually-unfocused {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,10 +133,13 @@
|
||||
0 0 0 1px var(--a-surface-default) inset,
|
||||
var(--a-shadow-focus);
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: 3px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-combobox--focused .navds-combobox__wrapper-inner.navds-combobox__wrapper-inner--virtually-unfocused {
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,3 +379,49 @@
|
||||
gap: var(--a-spacing-1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-combobox__button-clear:hover {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-combobox__wrapper-inner:has(.navds-combobox__input:focus-visible) {
|
||||
outline-color: highlight;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item--focus,
|
||||
.navds-combobox__list--with-hover
|
||||
.navds-combobox__list-item:not([data-no-focus="true"], .navds-combobox__list-item--new-option):hover {
|
||||
border-left-color: highlight;
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item[data-no-focus="true"] {
|
||||
opacity: 1;
|
||||
color: graytext;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item--selected {
|
||||
background-color: selecteditem;
|
||||
color: selecteditemtext;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item--selected > * {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item--selected.navds-combobox__list-item--focus,
|
||||
.navds-combobox__list--with-hover .navds-combobox__list-item--selected:hover {
|
||||
border-left-color: highlight;
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-combobox__list--with-hover .navds-combobox__list-item--new-option:hover {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-combobox__list-item--new-option--focus {
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: -3px;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
background-color: var(--ac-confirmation-panel-bg, var(--a-surface-warning-subtle));
|
||||
transition: background-color linear 100ms;
|
||||
justify-self: stretch;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel__content {
|
||||
@@ -23,3 +24,26 @@
|
||||
border-color: var(--ac-confirmation-panel-error-border, var(--a-border-danger));
|
||||
background-color: var(--ac-confirmation-panel-error-bg, var(--a-surface-danger-subtle));
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-confirmation-panel__inner::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
border-left: 8px solid;
|
||||
border-color: orange;
|
||||
forced-color-adjust: none;
|
||||
border-start-start-radius: calc(var(--a-border-radius-medium) - 1px);
|
||||
border-end-start-radius: calc(var(--a-border-radius-medium) - 1px);
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--checked .navds-confirmation-panel__inner::before {
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.navds-confirmation-panel--error .navds-confirmation-panel__inner::before {
|
||||
border-color: red;
|
||||
}
|
||||
}
|
||||
@@ -42,3 +42,10 @@
|
||||
.navds-fieldset:disabled > .navds-fieldset__description {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-fieldset:disabled > .navds-fieldset__legend,
|
||||
.navds-fieldset:disabled > .navds-fieldset__description {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@@ -51,3 +51,9 @@
|
||||
flex-shrink: 0;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-form-field--disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,8 @@
|
||||
|
||||
.navds-checkbox__input:focus-visible + .navds-checkbox__label::before,
|
||||
.navds-radio__input:focus-visible + .navds-radio__label::before {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow:
|
||||
0 0 0 2px var(--ac-radio-checkbox-border, var(--a-border-default)),
|
||||
0 0 0 2px var(--ac-radio-checkbox-bg, var(--a-surface-default)),
|
||||
@@ -81,6 +83,8 @@
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-checkbox__input:focus + .navds-checkbox__label::before,
|
||||
.navds-radio__input:focus + .navds-radio__label::before {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow:
|
||||
0 0 0 2px var(--ac-radio-checkbox-border, var(--a-border-default)),
|
||||
0 0 0 4px var(--a-border-focus);
|
||||
@@ -139,6 +143,10 @@
|
||||
height: 1.5rem;
|
||||
transform: translate(var(--a-spacing-1-alt));
|
||||
pointer-events: none;
|
||||
|
||||
/* Fixed edcase where when using in shadow-dom, svg will not center */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navds-checkbox--small .navds-checkbox__input:checked + .navds-checkbox__label > .navds-checkbox__icon {
|
||||
@@ -352,3 +360,81 @@
|
||||
.navds-checkbox--readonly > .navds-checkbox__input:indeterminate + .navds-checkbox__label::after {
|
||||
background-color: var(--a-icon-subtle);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-checkbox__input:focus-visible + .navds-checkbox__label::before,
|
||||
.navds-radio__input:focus-visible + .navds-radio__label::before {
|
||||
outline-color: highlight;
|
||||
}
|
||||
|
||||
.navds-checkbox,
|
||||
.navds-radio {
|
||||
--__ac-radio-checkbox-high-contrast-bg: field;
|
||||
--__ac-radio-checkbox-high-contrast-text: fieldtext;
|
||||
--__ac-radio-checkbox-high-contrast-highlight: highlight;
|
||||
}
|
||||
|
||||
.navds-checkbox__label::before,
|
||||
.navds-radio__label::before {
|
||||
border: 1px solid var(--__ac-radio-checkbox-high-contrast-text);
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-bg);
|
||||
}
|
||||
|
||||
.navds-checkbox__input:checked + .navds-checkbox__label > .navds-checkbox__icon {
|
||||
color: var(--__ac-radio-checkbox-high-contrast-text);
|
||||
}
|
||||
|
||||
.navds-checkbox__input:indeterminate + .navds-checkbox__label::after {
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-text);
|
||||
}
|
||||
|
||||
.navds-radio__input:checked + .navds-radio__label::before {
|
||||
border: 1px solid var(--__ac-radio-checkbox-high-contrast-text);
|
||||
outline: 3px solid var(--__ac-radio-checkbox-high-contrast-bg);
|
||||
outline-offset: -4px;
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-text);
|
||||
}
|
||||
|
||||
.navds-radio__input:checked:focus-visible + .navds-radio__label::before {
|
||||
border: 1px solid var(--__ac-radio-checkbox-high-contrast-bg);
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
:not(.navds-checkbox--readonly) > .navds-checkbox__input:hover:not(:disabled) + .navds-checkbox__label,
|
||||
:not(.navds-radio--readonly) > .navds-radio__input:hover:not(:disabled) + .navds-radio__label {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-checkbox__input:focus-visible + .navds-checkbox__label::before {
|
||||
outline: 2px solid var(--__ac-radio-checkbox-high-contrast-highlight);
|
||||
}
|
||||
|
||||
.navds-checkbox--readonly > .navds-checkbox__input:checked + .navds-checkbox__label::before {
|
||||
border: 1px solid var(--__ac-radio-checkbox-high-contrast-text);
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-bg);
|
||||
}
|
||||
|
||||
.navds-checkbox--readonly > .navds-checkbox__input:indeterminate + .navds-checkbox__label::after {
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-text);
|
||||
}
|
||||
|
||||
.navds-radio--readonly > .navds-radio__input:checked + .navds-radio__label::before {
|
||||
border: 1px solid var(--__ac-radio-checkbox-high-contrast-text);
|
||||
outline: 3px solid var(--__ac-radio-checkbox-high-contrast-bg);
|
||||
outline-offset: -4px;
|
||||
background-color: var(--__ac-radio-checkbox-high-contrast-text);
|
||||
}
|
||||
|
||||
.navds-checkbox--disabled,
|
||||
.navds-radio--disabled {
|
||||
opacity: 1;
|
||||
|
||||
--__ac-radio-checkbox-high-contrast-bg: field;
|
||||
--__ac-radio-checkbox-high-contrast-text: graytext;
|
||||
}
|
||||
|
||||
:is(.navds-checkbox--disabled, .navds-radio--disabled) :is(.navds-checkbox__label, .navds-radio__label) {
|
||||
color: graytext;
|
||||
}
|
||||
}
|
||||
@@ -99,14 +99,14 @@
|
||||
}
|
||||
|
||||
.navds-search__button-clear:focus-visible {
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-search__button-clear:focus {
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,3 +216,13 @@
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-modal {
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
|
||||
.navds-search__button-clear:hover {
|
||||
color: highlight;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,21 @@
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-select__input.navds-select__input.navds-select__input {
|
||||
background-color: ButtonFace;
|
||||
border-color: ButtonText;
|
||||
color: ButtonText;
|
||||
forced-color-adjust: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-select__input.navds-select__input.navds-select__input:focus-visible {
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-select__input:hover {
|
||||
border-color: var(--ac-select-hover-bg, var(--a-border-action));
|
||||
cursor: pointer;
|
||||
@@ -46,6 +61,12 @@
|
||||
color: var(--ac-select-text, var(--a-text-default));
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-select__chevron {
|
||||
color: ButtonText;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-select__input {
|
||||
min-height: 2rem;
|
||||
padding: 0 var(--a-spacing-8) 0 var(--a-spacing-2);
|
||||
|
||||
@@ -111,6 +111,8 @@
|
||||
}
|
||||
|
||||
.navds-switch__input:focus-visible ~ .navds-switch__track {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-surface-default),
|
||||
var(--a-shadow-focus);
|
||||
@@ -118,6 +120,7 @@
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-switch__input:focus ~ .navds-switch__track {
|
||||
outline: 2px solid transparent;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-surface-default),
|
||||
var(--a-shadow-focus);
|
||||
@@ -218,3 +221,49 @@
|
||||
transform: translateX(1.25rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-switch__input:hover ~ .navds-switch__label-wrapper,
|
||||
.navds-switch__label-wrapper:hover {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-switch__thumb,
|
||||
.navds-switch--readonly .navds-switch__thumb {
|
||||
background-color: fieldtext;
|
||||
}
|
||||
|
||||
.navds-switch__input:checked ~ .navds-switch__track > .navds-switch__thumb,
|
||||
.navds-switch--readonly .navds-switch__input:checked ~ .navds-switch__track > .navds-switch__thumb {
|
||||
color: field;
|
||||
}
|
||||
|
||||
.navds-switch__track {
|
||||
width: calc(2.75rem + 4px);
|
||||
height: calc(1.5rem + 4px);
|
||||
top: var(--a-spacing-3);
|
||||
border: 2px solid fieldtext;
|
||||
}
|
||||
|
||||
.navds-switch__input:focus-visible ~ .navds-switch__track {
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-switch--disabled:not(.navds-switch--loading) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.navds-switch--disabled:not(.navds-switch--loading) .navds-switch__thumb {
|
||||
background-color: graytext;
|
||||
}
|
||||
|
||||
.navds-switch--disabled:not(.navds-switch--loading) .navds-switch__track {
|
||||
border-color: graytext;
|
||||
}
|
||||
|
||||
.navds-switch--disabled:not(.navds-switch--loading) .navds-switch__label-wrapper,
|
||||
.navds-switch--disabled:not(.navds-switch--loading) .navds-switch__label-wrapper:hover {
|
||||
color: graytext !important;
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,8 @@
|
||||
}
|
||||
|
||||
.navds-text-field__input:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
|
||||
@@ -101,3 +102,10 @@
|
||||
.navds-text-field__input[type="search"]::-webkit-search-results-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-text-field__input {
|
||||
background-color: field;
|
||||
color: fieldtext;
|
||||
}
|
||||
}
|
||||
@@ -52,13 +52,15 @@
|
||||
}
|
||||
|
||||
.navds-textarea__input:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-textarea__input:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
}
|
||||
@@ -141,3 +143,10 @@
|
||||
border-color: var(--a-border-subtle);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-textarea__input {
|
||||
background-color: field;
|
||||
color: fieldtext;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
|
||||
.navds-help-text__button:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-border-focus),
|
||||
inset 0 0 0 1px var(--a-border-focus);
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-help-text__button:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-border-focus),
|
||||
inset 0 0 0 1px var(--a-border-focus);
|
||||
@@ -64,3 +64,17 @@
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-help-text__button:where(:hover, :focus-visible, [aria-expanded="true"]) > .navds-help-text__icon {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.navds-help-text__button:hover > .navds-help-text__icon {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-help-text__button:where(:hover, :focus-visible, [aria-expanded="true"]) > .navds-help-text__icon--filled {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,27 @@
|
||||
--navds-internalheader-focus: inset 0 0 0 2px var(--a-border-focus-on-inverted);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-internalheader {
|
||||
background-color: ButtonFace;
|
||||
border-color: ButtonText;
|
||||
border: solid 1px ButtonText;
|
||||
color: ButtonText;
|
||||
}
|
||||
|
||||
.navds-internalheader a:focus-visible {
|
||||
box-shadow: none;
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-internalheader .navds-internalheader__button:focus-visible {
|
||||
box-shadow: none;
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-internalheader__title {
|
||||
border: none;
|
||||
overflow: visible;
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
}
|
||||
|
||||
.navds-link-panel:focus-visible {
|
||||
outline: 3px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-link-panel:focus {
|
||||
outline: 3px solid transparent;
|
||||
outline-offset: 2px;
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
}
|
||||
|
||||
.navds-link:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
color: var(--ac-link-focus-text, var(--a-text-on-action));
|
||||
text-decoration: none;
|
||||
background-color: var(--ac-link-focus-bg, var(--a-border-focus));
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-link:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
color: var(--ac-link-focus-text, var(--a-text-on-action));
|
||||
text-decoration: none;
|
||||
background-color: var(--ac-link-focus-bg, var(--a-border-focus));
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
|
||||
.navds-link:active {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
color: var(--ac-link-active-text, var(--a-text-on-action));
|
||||
text-decoration: none;
|
||||
background-color: var(--ac-link-active-bg, var(--a-border-focus));
|
||||
|
||||
@@ -111,3 +111,9 @@
|
||||
stroke-dashoffset: -120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-loader__background {
|
||||
stroke: canvastext;
|
||||
}
|
||||
}
|
||||
@@ -168,3 +168,9 @@
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-modal {
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "5.16.0",
|
||||
"version": "5.18.2",
|
||||
"description": "CSS for NAV Designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
@@ -27,7 +27,7 @@
|
||||
"css:get-version": "node config/get-version.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^5.16.0",
|
||||
"@navikt/ds-tokens": "^5.18.2",
|
||||
"cssnano": "6.0.0",
|
||||
"fast-glob": "3.2.11",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -59,3 +59,26 @@
|
||||
border-right-color: transparent;
|
||||
border-top-color: transparent;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-popover[data-placement^="top"] > .navds-popover__arrow {
|
||||
border-left-color: canvas;
|
||||
border-top-color: canvas;
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.navds-popover[data-placement^="bottom"] > .navds-popover__arrow {
|
||||
border-bottom-color: canvas;
|
||||
border-right-color: canvas;
|
||||
}
|
||||
|
||||
.navds-popover[data-placement^="left"] > .navds-popover__arrow {
|
||||
border-left-color: canvas;
|
||||
border-bottom-color: canvas;
|
||||
}
|
||||
|
||||
.navds-popover[data-placement^="right"] > .navds-popover__arrow {
|
||||
border-right-color: canvas;
|
||||
border-top-color: canvas;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,21 @@
|
||||
padding: var(--a-spacing-05) var(--a-spacing-1) var(--a-spacing-05) var(--a-spacing-05);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-read-more__button {
|
||||
background-color: ButtonFace;
|
||||
border-color: ButtonText;
|
||||
border: solid 1px ButtonText;
|
||||
color: ButtonText;
|
||||
}
|
||||
|
||||
.navds-read-more__button.navds-read-more__button:focus-visible {
|
||||
box-shadow: none;
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-read-more__button:hover {
|
||||
background-color: var(--ac-read-more-hover-bg, var(--a-surface-hover));
|
||||
}
|
||||
|
||||
Vendored
+8
@@ -57,3 +57,11 @@
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-skeleton {
|
||||
forced-color-adjust: none;
|
||||
background-color: var(--a-surface-neutral);
|
||||
animation-duration: 2s;
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,41 @@
|
||||
margin: calc(var(--navds-stepper-border-width) * -1) calc(var(--navds-stepper-border-width) * -1) 1.75rem;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-stepper__step {
|
||||
background-color: ButtonFace;
|
||||
color: ButtonText;
|
||||
}
|
||||
|
||||
.navds-stepper__circle.navds-stepper__circle {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.navds-stepper__step .navds-stepper__circle {
|
||||
forced-color-adjust: none;
|
||||
background-color: ButtonText;
|
||||
border-color: ButtonText;
|
||||
color: ButtonFace;
|
||||
}
|
||||
|
||||
.navds-stepper__step.navds-stepper__step:focus-visible {
|
||||
box-shadow: none;
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-stepper__step.navds-stepper__step--active .navds-stepper__circle {
|
||||
forced-color-adjust: none;
|
||||
background-color: highlight;
|
||||
border-color: highlighttext;
|
||||
color: highlighttext;
|
||||
}
|
||||
|
||||
.navds-stepper__line {
|
||||
background-color: ButtonText;
|
||||
}
|
||||
}
|
||||
|
||||
button.navds-stepper__step {
|
||||
appearance: none;
|
||||
border: none;
|
||||
|
||||
@@ -264,3 +264,29 @@
|
||||
.navds-table--small .navds-table__expanded-row-content {
|
||||
padding: var(--a-spacing-2) calc(var(--a-spacing-2) + 3rem);
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-date.navds-date button.rdp-day_selected {
|
||||
forced-color-adjust: none;
|
||||
background-color: highlight;
|
||||
color: highlighttext;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-date.navds-date button {
|
||||
color: buttontext;
|
||||
forced-color-adjust: none;
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-date button:focus-visible {
|
||||
color: buttontext;
|
||||
forced-color-adjust: none;
|
||||
outline: 2px solid highlight;
|
||||
}
|
||||
|
||||
.navds-date.navds-date button.rdp-day_disabled {
|
||||
color: GrayText;
|
||||
}
|
||||
}
|
||||
@@ -63,14 +63,15 @@
|
||||
}
|
||||
|
||||
.navds-tabs__tab:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: -2px;
|
||||
box-shadow: inset var(--a-shadow-focus);
|
||||
color: var(--ac-tabs-focus-text, var(--a-text-default));
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-tabs__tab:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: inset var(--a-shadow-focus);
|
||||
color: var(--ac-tabs-focus-text, var(--a-text-default));
|
||||
}
|
||||
@@ -117,13 +118,29 @@
|
||||
}
|
||||
|
||||
.navds-tabs__tabpanel:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: inset 0 0 0 2px var(--a-border-focus);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-tabs__tabpanel:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
box-shadow: inset 0 0 0 2px var(--a-border-focus);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-tabs__tab[aria-selected="true"] {
|
||||
border-bottom: 3px solid canvastext;
|
||||
padding-block-end: calc(var(--a-spacing-3) - 3px);
|
||||
}
|
||||
|
||||
.navds-tabs__tab--small[aria-selected="true"] {
|
||||
padding-block-end: calc(var(--a-spacing-1-alt) - 3px);
|
||||
}
|
||||
|
||||
.navds-tabs__tab-icon--top[aria-selected="true"],
|
||||
.navds-tabs__tab--small.navds-tabs__tab-icon--top[aria-selected="true"] {
|
||||
padding-block-end: calc(var(--a-spacing-1) - 3px);
|
||||
}
|
||||
}
|
||||
@@ -180,3 +180,15 @@
|
||||
background-color: var(--ac-tag-alt-3-moderate-bg, var(--a-surface-alt-3-moderate));
|
||||
color: var(--ac-tag-alt-3-moderate-text, var(--a-text-default));
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-tag {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-tag--neutral,
|
||||
.navds-tag--neutral-moderate {
|
||||
border-color: canvastext;
|
||||
color: canvastext;
|
||||
}
|
||||
}
|
||||
@@ -393,3 +393,57 @@
|
||||
border-right-color: transparent;
|
||||
border-top-color: transparent;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-timeline__period:focus {
|
||||
outline: 2px solid highlight;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.navds-timeline__period--success,
|
||||
.navds-timeline__period--warning,
|
||||
.navds-timeline__period--info,
|
||||
.navds-timeline__period--neutral,
|
||||
.navds-timeline__period--danger {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-timeline__row {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.navds-timeline__pin-wrapper::before {
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.navds-timeline__pin-button {
|
||||
outline: 4px solid transparent;
|
||||
}
|
||||
|
||||
.navds-timeline__pin-button:focus,
|
||||
.navds-timeline__pin-button:focus-visible {
|
||||
outline: 4px solid highlight;
|
||||
outline-offset: 2px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-timeline__popover[data-placement^="top"] > .navds-timeline__popover-arrow {
|
||||
border-left-color: canvas;
|
||||
border-top-color: canvas;
|
||||
}
|
||||
|
||||
.navds-timeline__popover[data-placement^="bottom"] > .navds-timeline__popover-arrow {
|
||||
border-bottom-color: canvas;
|
||||
border-right-color: canvas;
|
||||
}
|
||||
|
||||
.navds-timeline__popover[data-placement^="left"] > .navds-timeline__popover-arrow {
|
||||
border-left-color: canvas;
|
||||
border-bottom-color: canvas;
|
||||
}
|
||||
|
||||
.navds-timeline__popover[data-placement^="right"] > .navds-timeline__popover-arrow {
|
||||
border-right-color: canvas;
|
||||
border-top-color: canvas;
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,8 @@
|
||||
}
|
||||
|
||||
.navds-toggle-group__button:focus-visible {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 1px;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-surface-default),
|
||||
0 0 0 4px var(--a-border-focus);
|
||||
@@ -73,7 +74,8 @@
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
.navds-toggle-group__button:focus {
|
||||
outline: none;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 1px;
|
||||
box-shadow:
|
||||
0 0 0 1px var(--a-surface-default),
|
||||
0 0 0 4px var(--a-border-focus);
|
||||
@@ -144,3 +146,32 @@
|
||||
.navds-toggle-group--small > .navds-toggle-group__button > .navds-toggle-group__button-inner > svg {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-toggle-group {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.navds-toggle-group__button:hover {
|
||||
color: highlight;
|
||||
}
|
||||
|
||||
.navds-toggle-group__button[aria-checked="true"],
|
||||
.navds-toggle-group__button[aria-pressed="true"] {
|
||||
background-color: selecteditem;
|
||||
color: selecteditemtext;
|
||||
}
|
||||
|
||||
.navds-toggle-group__button[aria-checked="true"] > *,
|
||||
.navds-toggle-group__button[aria-pressed="true"] > * {
|
||||
forced-color-adjust: none;
|
||||
}
|
||||
|
||||
.navds-toggle-group__button:active {
|
||||
background-color: none !important;
|
||||
}
|
||||
|
||||
.navds-toggle-group__button:focus-visible {
|
||||
outline-color: highlight;
|
||||
}
|
||||
}
|
||||
@@ -51,3 +51,31 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.navds-tooltip {
|
||||
--__a-tooltip-high-contrast-border: 1px solid transparent;
|
||||
|
||||
border: var(--__a-tooltip-high-contrast-border);
|
||||
}
|
||||
|
||||
.navds-tooltip[data-side="top"] .navds-tooltip__arrow {
|
||||
border-bottom: var(--__a-tooltip-high-contrast-border);
|
||||
border-right: var(--__a-tooltip-high-contrast-border);
|
||||
}
|
||||
|
||||
.navds-tooltip[data-side="right"] .navds-tooltip__arrow {
|
||||
border-bottom: var(--__a-tooltip-high-contrast-border);
|
||||
border-left: var(--__a-tooltip-high-contrast-border);
|
||||
}
|
||||
|
||||
.navds-tooltip[data-side="bottom"] .navds-tooltip__arrow {
|
||||
border-left: var(--__a-tooltip-high-contrast-border);
|
||||
border-top: var(--__a-tooltip-high-contrast-border);
|
||||
}
|
||||
|
||||
.navds-tooltip[data-side="left"] .navds-tooltip__arrow {
|
||||
border-top: var(--__a-tooltip-high-contrast-border);
|
||||
border-right: var(--__a-tooltip-high-contrast-border);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,101 @@
|
||||
# @navikt/ds-react
|
||||
|
||||
## 5.18.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Modal: Oppdatert intern håntering av context i komponent ([#2714](https://github.com/navikt/aksel/pull/2714))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.18.2
|
||||
- @navikt/aksel-icons@5.18.2
|
||||
|
||||
## 5.18.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Panel: Komponent er nå markert som deprecated. Bruk `Box` i fremtiden. ([#2712](https://github.com/navikt/aksel/pull/2712))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.18.1
|
||||
- @navikt/aksel-icons@5.18.1
|
||||
|
||||
## 5.18.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Portal: Ny komponent `Portal` som lar deg enkelt bruke `createPortal`, også på serversiden ([#2697](https://github.com/navikt/aksel/pull/2697))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.18.0
|
||||
- @navikt/aksel-icons@5.18.0
|
||||
|
||||
## 5.17.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.5
|
||||
- @navikt/aksel-icons@5.17.5
|
||||
|
||||
## 5.17.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Bleed: `marginInline='full'` og `reflectivePadding` kan nå brukes sammen. ([#2695](https://github.com/navikt/aksel/pull/2695))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.4
|
||||
- @navikt/aksel-icons@5.17.4
|
||||
|
||||
## 5.17.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :bug: Textarea: maxLength virker nå selv om man sender inn onChange uten å sende inn value ([#2690](https://github.com/navikt/aksel/pull/2690))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.3
|
||||
- @navikt/aksel-icons@5.17.3
|
||||
|
||||
## 5.17.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :bug: Textarea: Sett riktig høyde når brukt i Modal + StrictMode ([#2679](https://github.com/navikt/aksel/pull/2679))
|
||||
|
||||
- DatePicker: Knapper fikk ikke riktig aria-label ([#2678](https://github.com/navikt/aksel/pull/2678))
|
||||
|
||||
- Textarea: debounce ResizeObserver for å unngå feilmelding ([#2685](https://github.com/navikt/aksel/pull/2685))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.2
|
||||
- @navikt/aksel-icons@5.17.2
|
||||
|
||||
## 5.17.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Eksponer variabelen "role" i Search-komponenten ([#2667](https://github.com/navikt/aksel/pull/2667))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.1
|
||||
- @navikt/aksel-icons@5.17.1
|
||||
|
||||
## 5.17.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Høykontrast: Komponenter støtter nå standard høykontrast-modus på Windows ([#2680](https://github.com/navikt/aksel/pull/2680))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.17.0
|
||||
- @navikt/aksel-icons@5.17.0
|
||||
|
||||
## 5.16.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "5.16.0",
|
||||
"version": "5.18.2",
|
||||
"description": "Aksel react-components for NAV designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -38,8 +38,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "0.25.4",
|
||||
"@navikt/aksel-icons": "^5.16.0",
|
||||
"@navikt/ds-tokens": "^5.16.0",
|
||||
"@navikt/aksel-icons": "^5.18.2",
|
||||
"@navikt/ds-tokens": "^5.18.2",
|
||||
"@radix-ui/react-tabs": "1.0.0",
|
||||
"@radix-ui/react-toggle-group": "1.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { StoryObj } from "@storybook/react";
|
||||
import React, { useState } from "react";
|
||||
import { Accordion, AccordionProps } from ".";
|
||||
import { Table } from "..";
|
||||
import AccordionContent from "./AccordionContent";
|
||||
import AccordionHeader from "./AccordionHeader";
|
||||
import AccordionItem from "./AccordionItem";
|
||||
@@ -13,13 +13,15 @@ export default {
|
||||
AccordionContent,
|
||||
AccordionHeader,
|
||||
},
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div
|
||||
style={{
|
||||
width: "600px",
|
||||
minHeight: "100vh",
|
||||
padding: "10rem 0",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "1rem",
|
||||
@@ -29,25 +31,10 @@ export default {
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: ["default", "neutral"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
headingSize: {
|
||||
options: ["large", "medium", "small", "xsmall"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
size: {
|
||||
options: ["large", "medium", "small"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
nItems: {
|
||||
control: { type: "number" },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
type Story = StoryObj<typeof Accordion>;
|
||||
|
||||
const Content = () => (
|
||||
<Accordion.Content>
|
||||
Magna aliquip aliquip fugiat nostrud nostrud velit pariatur veniam officia
|
||||
@@ -103,22 +90,34 @@ const Item = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: ({ nItems, ...props }) => {
|
||||
export const Controls: Story = {
|
||||
render: ({ ...props }) => {
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Accordion {...props}>
|
||||
{[...Array(nItems ? nItems : 2)].map((_, y) => (
|
||||
{[...Array(4)].map((_, y) => (
|
||||
<Item key={y} {...props} />
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: ["default", "neutral"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
headingSize: {
|
||||
options: ["large", "medium", "small", "xsmall"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
size: {
|
||||
options: ["large", "medium", "small"],
|
||||
control: { type: "select" },
|
||||
},
|
||||
},
|
||||
|
||||
args: {
|
||||
controlled: false,
|
||||
nItems: 2,
|
||||
variant: "default",
|
||||
headingSize: "medium",
|
||||
size: "medium",
|
||||
@@ -126,37 +125,31 @@ export const Default = {
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultOpen = {
|
||||
render: ({ nItems, openItems, ...props }) => {
|
||||
export const DefaultOpen: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Accordion {...props}>
|
||||
{[...Array(nItems ? nItems : 2)].map((_, y) => (
|
||||
<Item key={y} defaultOpen={openItems.includes(y)} {...props} />
|
||||
<Accordion>
|
||||
{[...Array(4)].map((_, y) => (
|
||||
<Item key={y} defaultOpen={y === 2} />
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
args: {
|
||||
openItems: [1, 2],
|
||||
controlled: false,
|
||||
nItems: 5,
|
||||
variant: "neutral",
|
||||
headingSize: "large",
|
||||
},
|
||||
};
|
||||
|
||||
export const Variants = {
|
||||
export const Variants: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
<h3>Default</h3>
|
||||
<Accordion>
|
||||
{[...Array(2)].map((_, y) => (
|
||||
<Item key={y} defaultOpen />
|
||||
))}
|
||||
</Accordion>
|
||||
<h3>Neutral</h3>
|
||||
<Accordion variant="neutral">
|
||||
{[...Array(2)].map((_, y) => (
|
||||
<Item key={y} defaultOpen />
|
||||
@@ -167,96 +160,32 @@ export const Variants = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Controlled = (props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [open2, setOpen2] = useState(false);
|
||||
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Accordion {...props}>
|
||||
<Accordion.Item open={open}>
|
||||
<Accordion.Header onClick={() => setOpen(!open)}>
|
||||
Accordion header text
|
||||
</Accordion.Header>
|
||||
<Content />
|
||||
</Accordion.Item>
|
||||
<Accordion.Item open={open2}>
|
||||
<Accordion.Header onClick={() => setOpen2(!open2)}>
|
||||
Accordion header text
|
||||
</Accordion.Header>
|
||||
<Content />
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const WithTable = {
|
||||
render: (props) => {
|
||||
const ExampleTable = () => {
|
||||
return (
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>ID</Table.HeaderCell>
|
||||
<Table.HeaderCell>Fornavn</Table.HeaderCell>
|
||||
<Table.HeaderCell>Etternavn</Table.HeaderCell>
|
||||
<Table.HeaderCell>Rolle</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>1</Table.HeaderCell>
|
||||
<Table.DataCell>Jean-Luc</Table.DataCell>
|
||||
<Table.DataCell>Picard</Table.DataCell>
|
||||
<Table.DataCell>Kaptein</Table.DataCell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>2</Table.HeaderCell>
|
||||
<Table.DataCell>William</Table.DataCell>
|
||||
<Table.DataCell>Riker</Table.DataCell>
|
||||
<Table.DataCell>Kommandør</Table.DataCell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>3</Table.HeaderCell>
|
||||
<Table.DataCell>Geordi</Table.DataCell>
|
||||
<Table.DataCell>La Forge</Table.DataCell>
|
||||
<Table.DataCell>Sjefsingeniør</Table.DataCell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
const ContentWithTable = () => {
|
||||
return (
|
||||
<Accordion.Content>
|
||||
<ExampleTable />
|
||||
</Accordion.Content>
|
||||
);
|
||||
};
|
||||
export const ControlledState: Story = {
|
||||
render: () => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [open, setOpen] = useState(false);
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [open2, setOpen2] = useState(false);
|
||||
|
||||
return (
|
||||
<div style={{ width: 500 }}>
|
||||
<Accordion {...props}>
|
||||
<Accordion.Item>
|
||||
<Accordion.Header>Table of people</Accordion.Header>
|
||||
<ContentWithTable />
|
||||
<Accordion>
|
||||
<Accordion.Item open={open}>
|
||||
<Accordion.Header onClick={() => setOpen(!open)}>
|
||||
Accordion header text
|
||||
</Accordion.Header>
|
||||
<Content />
|
||||
</Accordion.Item>
|
||||
<Accordion.Item>
|
||||
<Accordion.Header>Table of people</Accordion.Header>
|
||||
<ContentWithTable />
|
||||
<Accordion.Item open={open2}>
|
||||
<Accordion.Header onClick={() => setOpen2(!open2)}>
|
||||
Accordion header text
|
||||
</Accordion.Header>
|
||||
<Content />
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
args: {
|
||||
variant: "default",
|
||||
headingSize: "large",
|
||||
indent: false,
|
||||
},
|
||||
};
|
||||
|
||||
const SingleHeaderAccordion = ({
|
||||
@@ -269,9 +198,11 @@ const SingleHeaderAccordion = ({
|
||||
<Accordion.Header>{`${size} size + ${headingSize} heading`}</Accordion.Header>
|
||||
<Accordion.Content>a</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
<Accordion.Item>
|
||||
<Accordion.Item open>
|
||||
<Accordion.Header>{`${size} size + ${headingSize} heading`}</Accordion.Header>
|
||||
<Accordion.Content>a</Accordion.Content>
|
||||
<Accordion.Content>
|
||||
lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
</Accordion.Content>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
);
|
||||
@@ -285,18 +216,73 @@ const headingSizes: AccordionProps["headingSize"][] = [
|
||||
"xsmall",
|
||||
];
|
||||
|
||||
export const Size = (props) => (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
{sizes.map((size) => (
|
||||
<SingleHeaderAccordion key={size} size={size} {...props} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
export const Size: Story = {
|
||||
render: () => (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
{sizes.map((size) => (
|
||||
<SingleHeaderAccordion key={size} size={size} />
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const HeadingSize = (props) => (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
{headingSizes.map((size) => (
|
||||
<SingleHeaderAccordion key={size} headingSize={size} {...props} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
export const HeadingSize: Story = {
|
||||
render: () => (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
{headingSizes.map((size) => (
|
||||
<SingleHeaderAccordion key={size} headingSize={size} />
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Indent: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<div style={{ width: 500 }} className="colgap">
|
||||
<h3>No indent</h3>
|
||||
<Accordion indent>
|
||||
{[...Array(2)].map((_, y) => (
|
||||
<Item key={y} defaultOpen />
|
||||
))}
|
||||
</Accordion>
|
||||
<h3>Indent</h3>
|
||||
<Accordion indent={false}>
|
||||
{[...Array(2)].map((_, y) => (
|
||||
<Item key={y} defaultOpen />
|
||||
))}
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Chromatic: Story = {
|
||||
render: (...props) => (
|
||||
<div>
|
||||
<div>
|
||||
<h2>Variants</h2>
|
||||
{Variants.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Size</h2>
|
||||
{Size.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>HeadingSize</h2>
|
||||
{HeadingSize.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>DefaultOpen</h2>
|
||||
{DefaultOpen.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Indent</h2>
|
||||
{Indent.render?.(...props)}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
chromatic: { disable: false },
|
||||
},
|
||||
};
|
||||
@@ -1,12 +1,16 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { expect, userEvent, within } from "@storybook/test";
|
||||
import React from "react";
|
||||
import { Alert, AlertProps } from ".";
|
||||
import { BodyLong, Heading as DsHeading, Link } from "..";
|
||||
import { VStack } from "../layout/stack";
|
||||
import { Link } from "../link";
|
||||
import { BodyLong, Heading as DsHeading } from "../typography";
|
||||
import Alert, { AlertProps } from "./Alert";
|
||||
|
||||
const meta: Meta<typeof Alert> = {
|
||||
title: "ds-react/Alert",
|
||||
component: Alert,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@@ -20,12 +24,13 @@ const variants: AlertProps["variant"][] = [
|
||||
"success",
|
||||
];
|
||||
|
||||
export const Default: Story = {
|
||||
export const Controls: Story = {
|
||||
render: (props) => <Alert {...props} />,
|
||||
|
||||
args: {
|
||||
children: "Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
fullWidth: false,
|
||||
inline: false,
|
||||
variant: "info",
|
||||
size: "medium",
|
||||
closeButton: false,
|
||||
@@ -42,43 +47,18 @@ export const Default: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
render: (props) => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Alert
|
||||
key={variant}
|
||||
variant={variant}
|
||||
size="small"
|
||||
closeButton={props.closeButton}
|
||||
>
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
</Alert>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
args: {
|
||||
closeButton: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const FullWidth = () => {
|
||||
export const Variants = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Alert key={variant} variant={variant} fullWidth>
|
||||
<Alert key={variant} variant={variant}>
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
</Alert>
|
||||
))}
|
||||
{variants.map((variant, i) => (
|
||||
<Alert key={variant} variant={variant} fullWidth size="small">
|
||||
<Alert key={variant} variant={variant} size="small">
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
@@ -88,24 +68,42 @@ export const FullWidth = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const FullWidth = () => {
|
||||
return (
|
||||
<VStack gap="4">
|
||||
<Alert variant="info" fullWidth>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" fullWidth size="small">
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
export const Inline = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Alert key={variant} variant={variant} inline>
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
</Alert>
|
||||
))}
|
||||
{variants.map((variant, i) => (
|
||||
<Alert key={variant} variant={variant} inline size="small">
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
</Alert>
|
||||
))}
|
||||
</div>
|
||||
<VStack gap="4">
|
||||
<h2>Inline</h2>
|
||||
<Alert variant="info" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim reprehenderit
|
||||
enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim reprehenderit
|
||||
enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -136,82 +134,173 @@ export const Heading = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Links = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
{variants.map((variant) => (
|
||||
<Alert key={variant} variant={variant}>
|
||||
<Link href="#">Id elit esse enim reprehenderit</Link>
|
||||
</Alert>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const AlertWithCloseButton = ({
|
||||
children,
|
||||
size,
|
||||
}: {
|
||||
size?: "medium" | "small";
|
||||
children?: React.ReactNode;
|
||||
}) => {
|
||||
const [show, setShow] = React.useState(true);
|
||||
|
||||
return show ? (
|
||||
<Alert
|
||||
variant="warning"
|
||||
size={size}
|
||||
closeButton
|
||||
onClose={() => setShow(false)}
|
||||
>
|
||||
{children || "Content"}
|
||||
</Alert>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export const WithCloseButton: Story = {
|
||||
export const CloseButton: Story = {
|
||||
render: () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<AlertWithCloseButton />
|
||||
<AlertWithCloseButton>
|
||||
<BodyLong>Ullamco ullamco laborum et commodo sint culpa</BodyLong>
|
||||
</AlertWithCloseButton>
|
||||
<AlertWithCloseButton>
|
||||
<DsHeading spacing size="small" level="3">
|
||||
Aliquip duis est in commodo pariatur
|
||||
<VStack gap="4">
|
||||
<h2>CloseButton</h2>
|
||||
<Alert variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert size="small" variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert size="small" variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" closeButton>
|
||||
<DsHeading size="small" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong>
|
||||
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
|
||||
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
|
||||
sint commodo consequat eu aute.
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</AlertWithCloseButton>
|
||||
<AlertWithCloseButton size="small">
|
||||
<BodyLong>Ullamco ullamco laborum et commodo</BodyLong>
|
||||
</AlertWithCloseButton>
|
||||
<AlertWithCloseButton size="small">
|
||||
<DsHeading spacing size="small" level="3">
|
||||
Aliquip duis est in commodo pariatur
|
||||
</Alert>
|
||||
<Alert variant="info" closeButton size="small">
|
||||
<DsHeading size="xsmall" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong>
|
||||
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
|
||||
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
|
||||
sint commodo consequat eu aute.
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</AlertWithCloseButton>
|
||||
</div>
|
||||
</Alert>
|
||||
</VStack>
|
||||
);
|
||||
},
|
||||
play: async ({ canvasElement, step }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const buttons = canvas.getAllByTitle("Lukk Alert");
|
||||
};
|
||||
|
||||
await step("click button", async () => {
|
||||
await userEvent.click(buttons[0]);
|
||||
});
|
||||
export const Chromatic: Story = {
|
||||
render: () => (
|
||||
<VStack gap="6">
|
||||
<VStack gap="2">
|
||||
<h2>Variant</h2>
|
||||
{variants.map((variant, i) => (
|
||||
<Alert key={variant} variant={variant}>
|
||||
{new Array(i + 1).fill(
|
||||
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
)}
|
||||
</Alert>
|
||||
))}
|
||||
</VStack>
|
||||
<VStack gap="2">
|
||||
<h2>Small</h2>
|
||||
<Alert variant="info" size="small">
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small">
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
</VStack>
|
||||
<VStack gap="2">
|
||||
<h2>FullWidth</h2>
|
||||
<Alert variant="info" fullWidth>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" fullWidth>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
</VStack>
|
||||
<VStack gap="2">
|
||||
<h2>Inline</h2>
|
||||
<Alert variant="info" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" inline>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
</VStack>
|
||||
<VStack gap="2">
|
||||
<h2>Heading</h2>
|
||||
<Alert variant="info">
|
||||
<DsHeading size="small" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</Alert>
|
||||
<Alert variant="info" size="small">
|
||||
<DsHeading size="xsmall" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong size="small">
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</Alert>
|
||||
</VStack>
|
||||
<VStack gap="2">
|
||||
<h2>CloseButton</h2>
|
||||
<Alert variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert size="small" variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert size="small" variant="info" closeButton>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
|
||||
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud. Id elit esse enim
|
||||
reprehenderit enim nisi veniam nostrud.
|
||||
</Alert>
|
||||
<Alert variant="info" closeButton>
|
||||
<DsHeading size="small" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong>
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</Alert>
|
||||
<Alert variant="info" size="small" closeButton>
|
||||
<DsHeading size="xsmall" level="3">
|
||||
Id elit esse enim reprehenderit
|
||||
</DsHeading>
|
||||
<BodyLong size="small">
|
||||
Id elit esse enim reprehenderit enim nisi veniam nostrud.
|
||||
</BodyLong>
|
||||
</Alert>
|
||||
</VStack>
|
||||
|
||||
const buttonsAfter = canvas.getAllByTitle("Lukk Alert");
|
||||
expect(buttonsAfter.length).toBe(4);
|
||||
<VStack gap="2">
|
||||
<h2>Links</h2>
|
||||
{variants.map((variant) => (
|
||||
<Alert key={variant} variant={variant}>
|
||||
<Link href="#">Id elit esse enim reprehenderit</Link>
|
||||
</Alert>
|
||||
))}
|
||||
</VStack>
|
||||
</VStack>
|
||||
),
|
||||
parameters: {
|
||||
chromatic: { disable: false },
|
||||
},
|
||||
};
|
||||
@@ -1,15 +1,21 @@
|
||||
import { StoryObj } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { StarIcon } from "@navikt/aksel-icons";
|
||||
import { StarIcon as BaseStarIcon } from "@navikt/aksel-icons";
|
||||
import { HStack, VStack } from "../layout/stack";
|
||||
import { Button } from "./index";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Button",
|
||||
component: Button,
|
||||
parameters: {
|
||||
chromatic: { delay: 600 },
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
type Story = StoryObj<typeof Button>;
|
||||
|
||||
const StarIcon = () => <BaseStarIcon aria-hidden />;
|
||||
|
||||
const variants: (
|
||||
| "primary"
|
||||
| "secondary"
|
||||
@@ -28,17 +34,7 @@ const variants: (
|
||||
"tertiary-neutral",
|
||||
];
|
||||
|
||||
const varSwitch = {
|
||||
primary: "Primary",
|
||||
secondary: "Secondary",
|
||||
tertiary: "Tertiary",
|
||||
danger: "Danger",
|
||||
"primary-neutral": "Primary",
|
||||
"secondary-neutral": "Secondary",
|
||||
"tertiary-neutral": "Tertiary",
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
export const Controls: Story = {
|
||||
render: (props) => {
|
||||
return (
|
||||
<Button
|
||||
@@ -57,7 +53,7 @@ export const Default = {
|
||||
icon: false,
|
||||
loading: false,
|
||||
iconPosition: "left",
|
||||
children: "Knapp",
|
||||
children: "Button",
|
||||
variant: "primary",
|
||||
size: "medium",
|
||||
},
|
||||
@@ -91,192 +87,99 @@ export const Default = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Small = () => (
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} size="small">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const XSmall = () => (
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} size="xsmall">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Link = () => (
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} as="a" href="#thecakeisalie">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Loading = {
|
||||
render: () => (
|
||||
<div className="colgap chromatic-ignore">
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} loading>
|
||||
{varSwitch[variant]}
|
||||
function ButtonGrid(props: any) {
|
||||
return (
|
||||
<VStack gap="2">
|
||||
{variants.map((variant) => (
|
||||
<HStack gap="2" key={variant}>
|
||||
<Button variant={variant} {...props}>
|
||||
Button
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} loading size="small">
|
||||
{varSwitch[variant]}
|
||||
<Button variant={variant} {...props} icon={<StarIcon />}>
|
||||
Button
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} loading size="xsmall">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
},
|
||||
};
|
||||
|
||||
export const Icon = () => (
|
||||
<div className="colgap ">
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
size="small"
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
size="xsmall"
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const IconWText = () => (
|
||||
<div className="colgap">
|
||||
<div className="rowgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
iconPosition={i % 2 ? "left" : "right"}
|
||||
>
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
size="small"
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
iconPosition={i % 2 ? "left" : "right"}
|
||||
>
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant, i) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
size="xsmall"
|
||||
icon={<StarIcon title="Stjerne" />}
|
||||
iconPosition={i % 2 ? "left" : "right"}
|
||||
>
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Disabled = () => (
|
||||
<div className="colgap">
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} disabled>
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} disabled as="a" href="#">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const LoadingWithAs = {
|
||||
render: () => (
|
||||
<div className="colgap chromatic-ignore">
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button key={variant} variant={variant} loading size="small">
|
||||
{varSwitch[variant]}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
<div className="rowgap">
|
||||
{variants.map((variant) => (
|
||||
<Button
|
||||
key={variant}
|
||||
variant={variant}
|
||||
loading
|
||||
size="small"
|
||||
as="a"
|
||||
href="#"
|
||||
{...props}
|
||||
icon={<StarIcon />}
|
||||
iconPosition="right"
|
||||
>
|
||||
{varSwitch[variant]}
|
||||
Button
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
<Button variant={variant} {...props} icon={<StarIcon />} />
|
||||
</HStack>
|
||||
))}
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
||||
export const Medium: Story = {
|
||||
render: () => <ButtonGrid size="medium" />,
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
render: () => <ButtonGrid size="small" />,
|
||||
};
|
||||
|
||||
export const XSmall: Story = {
|
||||
render: () => <ButtonGrid size="xsmall" />,
|
||||
};
|
||||
|
||||
export const AsLink: Story = {
|
||||
render: () => (
|
||||
<VStack gap="4">
|
||||
<Button href="#" as="a">
|
||||
Button as a-tag
|
||||
</Button>
|
||||
<Button href="#" as="a" disabled>
|
||||
Disabled Button as a-tag
|
||||
</Button>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
render: () => <ButtonGrid loading />,
|
||||
};
|
||||
|
||||
export const LoadingAsLink: Story = {
|
||||
render: () => <ButtonGrid loading href="#" as="a" />,
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
render: () => <ButtonGrid disabled />,
|
||||
};
|
||||
|
||||
export const DisabledAsLink: Story = {
|
||||
render: () => <ButtonGrid disabled href="#" as="a" />,
|
||||
};
|
||||
|
||||
export const Chromatic: Story = {
|
||||
render: () => (
|
||||
<VStack gap="6" align="center">
|
||||
<div>
|
||||
<h2>Medium</h2>
|
||||
<ButtonGrid size="medium" />
|
||||
</div>
|
||||
<div>
|
||||
<h2>Small</h2>
|
||||
<ButtonGrid size="small" />
|
||||
</div>
|
||||
<div>
|
||||
<h2>XSmall</h2>
|
||||
<ButtonGrid size="xsmall" />
|
||||
</div>
|
||||
<div>
|
||||
<h2>As Link</h2>
|
||||
<ButtonGrid as="a" href="#" />
|
||||
</div>
|
||||
<div>
|
||||
<h2>Disabled</h2>
|
||||
<ButtonGrid disabled />
|
||||
</div>
|
||||
</VStack>
|
||||
),
|
||||
parameters: {
|
||||
chromatic: { disableSnapshot: true },
|
||||
chromatic: { disable: false },
|
||||
},
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { Chat } from "../index";
|
||||
import { Chat, VStack } from "../index";
|
||||
import { POSITIONS, SIZES } from "./Chat";
|
||||
|
||||
export default {
|
||||
@@ -30,9 +30,14 @@ export default {
|
||||
options: SIZES,
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
} satisfies Meta<typeof Chat>;
|
||||
|
||||
export const Default = {
|
||||
type Story = StoryObj<typeof Chat>;
|
||||
|
||||
export const Controls: Story = {
|
||||
render: (props) => {
|
||||
return (
|
||||
<Chat {...props}>
|
||||
@@ -55,219 +60,292 @@ export const Default = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Small = () => (
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 14:00" size="small">
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
);
|
||||
export const Size: Story = {
|
||||
render: () => (
|
||||
<VStack gap="4">
|
||||
<h3>Medium</h3>
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Normann"
|
||||
timestamp="01.01.21 14:00"
|
||||
size="medium"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint
|
||||
laboris labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Small</h3>
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Normann"
|
||||
timestamp="01.01.21 14:00"
|
||||
size="small"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint
|
||||
laboris labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export const Colors = () => (
|
||||
<Chat
|
||||
avatar="NAV"
|
||||
name="NAV"
|
||||
timestamp="01.01.21 14:00"
|
||||
avatarBgColor="var(--a-surface-alt-1-subtle)"
|
||||
backgroundColor="var(--a-surface-warning-subtle)"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble backgroundColor="lightYellow">
|
||||
Tempor fugiat amet eu sint in in ullamco.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
);
|
||||
export const Variants: Story = {
|
||||
render: () => (
|
||||
<VStack gap="4">
|
||||
<h3>Info</h3>
|
||||
<Chat avatar="NAV" name="NAV" timestamp="01.01.21 14:00" variant="info">
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Neutral</h3>
|
||||
<Chat
|
||||
avatar="KN"
|
||||
name="Kari Nordmann"
|
||||
timestamp="01.01.21 14:03"
|
||||
variant="neutral"
|
||||
position="right"
|
||||
>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Subtle</h3>
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Nordmann"
|
||||
timestamp="01.01.21 14:07"
|
||||
variant="subtle"
|
||||
position="right"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint
|
||||
laboris labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export const Variants = () => (
|
||||
<div className="colgap">
|
||||
<Chat avatar="NAV" name="NAV" timestamp="01.01.21 14:00" variant="info">
|
||||
export const Position: Story = {
|
||||
render: () => (
|
||||
<VStack gap="4">
|
||||
<h3>Default</h3>
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 14:00">
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint
|
||||
laboris labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Right</h3>
|
||||
<Chat
|
||||
avatar="KH"
|
||||
name="Kari Høyli"
|
||||
timestamp="01.01.21 14:32"
|
||||
position="right"
|
||||
variant="info"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Reprehenderit pariatur officia exercitation laboris.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit
|
||||
est dolore incididunt. Occaecat cupidatat magna.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Left</h3>
|
||||
<Chat
|
||||
position="left"
|
||||
avatar="ON"
|
||||
name="Ola Normann"
|
||||
timestamp="01.01.21 15:00"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Exercitation irure Lorem cupidatat culpa anim cillum esse ullamco qui
|
||||
dolore laborum et Lorem. Labore sunt duis id Lorem voluptate commodo
|
||||
ea esse. Dolore esse aliqua proident ea ad commodo ut dolore voluptate
|
||||
labore sunt aute.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export const ToptextPosition: Story = {
|
||||
render: () => (
|
||||
<VStack gap="4">
|
||||
<h3>Right</h3>
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Normann"
|
||||
timestamp="01.01.21 14:00"
|
||||
toptextPosition="right"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint
|
||||
laboris labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Left</h3>
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 15:00">
|
||||
<Chat.Bubble toptextPosition="left">
|
||||
Exercitation irure Lorem cupidatat culpa anim cillum esse ullamco qui
|
||||
dolore laborum et Lorem. Labore sunt duis id Lorem voluptate commodo
|
||||
ea esse. Dolore esse aliqua proident ea ad commodo ut dolore voluptate
|
||||
labore sunt aute.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Left</h3>
|
||||
<Chat
|
||||
name="Kari Høyli"
|
||||
timestamp="01.01.21 14:32"
|
||||
position="right"
|
||||
toptextPosition="left"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Reprehenderit pariatur officia exercitation laboris.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit
|
||||
est dolore incididunt. Occaecat cupidatat magna.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<h3>Right</h3>
|
||||
<Chat
|
||||
name="Kari Høyli"
|
||||
timestamp="01.01.21 14:32"
|
||||
position="right"
|
||||
toptextPosition="right"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Reprehenderit pariatur officia exercitation laboris.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit
|
||||
est dolore incididunt. Occaecat cupidatat magna.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export const Avatar: Story = {
|
||||
render: () => (
|
||||
<Chat avatar={<Illustration />}>
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat
|
||||
avatar="KN"
|
||||
name="Kari Nordmann"
|
||||
timestamp="01.01.21 14:03"
|
||||
variant="neutral"
|
||||
position="right"
|
||||
>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Nordmann"
|
||||
timestamp="01.01.21 14:07"
|
||||
variant="subtle"
|
||||
position="right"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</div>
|
||||
);
|
||||
),
|
||||
};
|
||||
|
||||
export const Position = () => (
|
||||
<div className="colgap">
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 14:00">
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat
|
||||
avatar="KH"
|
||||
name="Kari Høyli"
|
||||
timestamp="01.01.21 14:32"
|
||||
position="right"
|
||||
variant="info"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Reprehenderit pariatur officia exercitation laboris.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit est
|
||||
dolore incididunt. Occaecat cupidatat magna.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 15:00">
|
||||
<Chat.Bubble>
|
||||
Exercitation irure Lorem cupidatat culpa anim cillum esse ullamco qui
|
||||
dolore laborum et Lorem. Labore sunt duis id Lorem voluptate commodo ea
|
||||
esse. Dolore esse aliqua proident ea ad commodo ut dolore voluptate
|
||||
labore sunt aute.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</div>
|
||||
);
|
||||
function Illustration() {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 93">
|
||||
<path
|
||||
fill="#e7e5e2"
|
||||
d="M14 50.7C15 52.3 17.9 81 26.5 81S39 51.8 39 50.3c-13.2-7.6-25 .4-25 .4z"
|
||||
/>
|
||||
<path
|
||||
fill="#5c4378"
|
||||
d="M38.7 50.2c6 2.9 15.3 10.9 15.3 18.3V93H0V68.5c0-7.1 8.5-14.8 14.5-18-.3.2-.5.3-.5.3 1 1.7 3.8 9.2 12.4 9.2C35 60 39 51.9 39 50.4c-.1-.1-.2-.2-.3-.2z"
|
||||
/>
|
||||
<path
|
||||
fill="#d2242a"
|
||||
d="M46.7 76H31.2c-.7 0-1.3-.6-1.2-1.3v-8.5c0-.7.6-1.3 1.3-1.3h15.5c.7 0 1.3.6 1.3 1.3v8.5c-.1.7-.7 1.3-1.4 1.3"
|
||||
/>
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M42.9 71c0 2.1-1.7 3.8-3.8 3.8-2.1 0-3.8-1.7-3.8-3.8s1.7-3.8 3.8-3.8c2.1 0 3.8 1.7 3.8 3.8m-8.7 1.7h-.7l.8-1.9h.7l-.8 1.9zm9.3 0H43l.8-1.9h.5l-.8 1.9zm1.2 0h-.2l.8-1.9h.2l-.8 1.9z"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M36.2 72.7h.6s.1 0 .1-.1v-1.8s0-.1-.1-.1h-.6s-.1 0-.1.1l-.2.6v.1h.2l.1 1.2c0-.1 0 0 0 0"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M37.5 72.7h.6s.1 0 .1-.1v-1.8s0-.1-.1-.1h-.9s-.1 0-.1.1l-.2.6-.1.1h.5c.1 0 .2.1.2.2v1c-.1-.1-.1 0 0 0m2.6-1.9h-.6s-.1 0-.1.1v1.8s0 .1.1.1h.6s.1 0 .1-.1l.2-.6V72h-.2l-.1-1.2"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M37.7 72.7h.4s.1 0 .1-.1l.2-.6v-.1h-.2c0 .1-.5.8-.5.8zm3.9-1.9h.7s.1 0 0 .1l-.7 1.8H41l.6-1.9"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M40.8 70.8h-1c-.1 0 .3.1.3.1l.7 1.7s0 .1.1.1h.6l-.7-1.9m-1.3.6v.4s-.1-.4-.3-.4c-.3 0-.3.2-.3.3 0 .1.1.3.2.3h.5l-.3.7H39c-.2 0-.9-.3-.9-.9 0-.6.5-1 .9-1 .2-.1.5.2.5.6 0-.1 0-.1 0 0z"
|
||||
/>
|
||||
<path
|
||||
fill="#5a1f57"
|
||||
d="M39.9 66.7h-1.6c-.1 0-.2-.1-.2-.2v-.3c0-.1.1-.2.2-.2h1.6c.1 0 .2.1.2.2v.3c0 .2-.1.2-.2.2"
|
||||
/>
|
||||
<path fill="#c2b5cf" d="M38.7 66.5h.9V64h-.9v2.5z" />
|
||||
<path
|
||||
fill="#e7e5e2"
|
||||
d="M47.2 35.3C44.7 45.6 36.6 53.1 27 53.1S9.3 45.6 6.8 35.3c-.2.1-.5.1-.8.1-1.1 0-2-.8-2-1.7v-7c0-1 .9-1.7 2-1.7h.2C7.7 13.1 16.4 4 27 4c10.6 0 19.3 9.1 20.8 21h.2c1.1 0 2 .8 2 1.7v7c0 1-.9 1.7-2 1.7-.3 0-.5 0-.8-.1z"
|
||||
/>
|
||||
<path
|
||||
fill="#635e59"
|
||||
d="M19 27.6c-1.4.1-1.9-2-1.4-3.4.1-.3.6-1.5 1.4-1.5.8 0 1.2.7 1.3.8.6 1.4.3 4-1.3 4.1m16.2 0c1.4.1 1.9-2 1.4-3.4-.1-.3-.6-1.5-1.4-1.5-.8 0-1.2.7-1.3.8-.6 1.4-.3 4 1.3 4.1"
|
||||
/>
|
||||
<path
|
||||
fill="#d1bfa3"
|
||||
d="M26.8 34.6c-.4 0-.7-.1-1-.2-.3-.1-.4-.4-.3-.7.1-.3.4-.4.7-.3.5.2 1.5.1 2.2-.4.7-.4 1.1-1 1.2-1.5.1-.4-.1-.9-.4-1.3-.2-.2-.8-.2-1.6-.1-.3 0-.5-.1-.6-.4 0-.3.1-.5.4-.6 1.2-.2 2.1 0 2.6.6.5.7.8 1.4.6 2.1-.1.8-.7 1.6-1.7 2.2-.6.3-1.4.6-2.1.6z"
|
||||
/>
|
||||
<path
|
||||
fill="#593a32"
|
||||
d="M27.1 42.1h-.3c-5.3-.2-7.3-4.1-7.4-4.3-.1-.3 0-.6.2-.7.2-.1.6 0 .7.2.1.1 1.9 3.6 6.6 3.8 4.7.2 6.4-3.7 6.4-3.7.1-.3.4-.4.7-.3.3.1.4.4.3.7-.1 0-2.1 4.3-7.2 4.3z"
|
||||
/>
|
||||
<path
|
||||
fill="#f6b873"
|
||||
d="M6.6 30.7c.1-.1.1-.2.1-.3v-2c-.1-5.6 1.8-8.1 3.4-10.1 0 0-1 4.3-.3 3.4 3.8-5 21.4-1.6 25-8.1.5 3.6-4.1 4.6-4.1 4.6 3.7.7 6.9-.8 7.7-2.5.3 1.4-.6 2.4-1.9 3.4 4.5-.9 4.6-4 4.6-4 .6 4.1 5.3 2.5 5.3 9.3v6c0 .3.2.6.5.6h.5c.3 0 .5-.3.5-.6V26c.3-15.6-8.5-26-20.6-26C15.9 0 5 10.4 5 24.1v6.3c0 .4.2.6.5.6h.6c.2 0 .3-.1.5-.3"
|
||||
/>
|
||||
<path
|
||||
fill="#f6b873"
|
||||
d="M25.9 43.4c-4.4 0-8-1.4-8-3.2s3.6-3.2 8-3.2 8 1.4 8 3.2c0 1.8-3.6 3.2-8 3.2m.8-9.4c-2.9 0-4.7.7-8.8 2.1-12.7 4.6-11.6-14-11.6-14C3.4 46 18.6 52 26.5 52c8.1 0 24.1-8.1 21-30 0 0 .4 17.1-12.9 13.8-3.7-.9-5-1.8-7.9-1.8z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export const ToptextPosition = () => (
|
||||
<div className="colgap">
|
||||
<Chat
|
||||
avatar="ON"
|
||||
name="Ola Normann"
|
||||
timestamp="01.01.21 14:00"
|
||||
toptextPosition="right"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat
|
||||
name="Kari Høyli"
|
||||
timestamp="01.01.21 14:32"
|
||||
position="right"
|
||||
variant="info"
|
||||
toptextPosition="left"
|
||||
>
|
||||
<Chat.Bubble>
|
||||
Reprehenderit pariatur officia exercitation laboris.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit est
|
||||
dolore incididunt. Occaecat cupidatat magna.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
<Chat avatar="ON" name="Ola Normann" timestamp="01.01.21 15:00">
|
||||
<Chat.Bubble toptextPosition="right">
|
||||
Exercitation irure Lorem cupidatat culpa anim cillum esse ullamco qui
|
||||
dolore laborum et Lorem. Labore sunt duis id Lorem voluptate commodo ea
|
||||
esse. Dolore esse aliqua proident ea ad commodo ut dolore voluptate
|
||||
labore sunt aute.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const Avatar = () => (
|
||||
<Chat avatar={<Illustration />} timestamp="01.01.21 14:00">
|
||||
<Chat.Bubble>
|
||||
Aute minim nisi sunt mollit duis sunt nulla minim non proident.
|
||||
</Chat.Bubble>
|
||||
<Chat.Bubble>Tempor fugiat amet eu sint in in ullamco.</Chat.Bubble>
|
||||
<Chat.Bubble>
|
||||
Adipisicing laborum est eu laborum est sit in commodo enim sint laboris
|
||||
labore nisi ut.
|
||||
</Chat.Bubble>
|
||||
</Chat>
|
||||
);
|
||||
|
||||
const Illustration = () => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 93">
|
||||
<path
|
||||
fill="#e7e5e2"
|
||||
d="M14 50.7C15 52.3 17.9 81 26.5 81S39 51.8 39 50.3c-13.2-7.6-25 .4-25 .4z"
|
||||
/>
|
||||
<path
|
||||
fill="#5c4378"
|
||||
d="M38.7 50.2c6 2.9 15.3 10.9 15.3 18.3V93H0V68.5c0-7.1 8.5-14.8 14.5-18-.3.2-.5.3-.5.3 1 1.7 3.8 9.2 12.4 9.2C35 60 39 51.9 39 50.4c-.1-.1-.2-.2-.3-.2z"
|
||||
/>
|
||||
<path
|
||||
fill="#d2242a"
|
||||
d="M46.7 76H31.2c-.7 0-1.3-.6-1.2-1.3v-8.5c0-.7.6-1.3 1.3-1.3h15.5c.7 0 1.3.6 1.3 1.3v8.5c-.1.7-.7 1.3-1.4 1.3"
|
||||
/>
|
||||
<path
|
||||
fill="#fff"
|
||||
d="M42.9 71c0 2.1-1.7 3.8-3.8 3.8-2.1 0-3.8-1.7-3.8-3.8s1.7-3.8 3.8-3.8c2.1 0 3.8 1.7 3.8 3.8m-8.7 1.7h-.7l.8-1.9h.7l-.8 1.9zm9.3 0H43l.8-1.9h.5l-.8 1.9zm1.2 0h-.2l.8-1.9h.2l-.8 1.9z"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M36.2 72.7h.6s.1 0 .1-.1v-1.8s0-.1-.1-.1h-.6s-.1 0-.1.1l-.2.6v.1h.2l.1 1.2c0-.1 0 0 0 0"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M37.5 72.7h.6s.1 0 .1-.1v-1.8s0-.1-.1-.1h-.9s-.1 0-.1.1l-.2.6-.1.1h.5c.1 0 .2.1.2.2v1c-.1-.1-.1 0 0 0m2.6-1.9h-.6s-.1 0-.1.1v1.8s0 .1.1.1h.6s.1 0 .1-.1l.2-.6V72h-.2l-.1-1.2"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M37.7 72.7h.4s.1 0 .1-.1l.2-.6v-.1h-.2c0 .1-.5.8-.5.8zm3.9-1.9h.7s.1 0 0 .1l-.7 1.8H41l.6-1.9"
|
||||
/>
|
||||
<path
|
||||
fill="#c52d35"
|
||||
d="M40.8 70.8h-1c-.1 0 .3.1.3.1l.7 1.7s0 .1.1.1h.6l-.7-1.9m-1.3.6v.4s-.1-.4-.3-.4c-.3 0-.3.2-.3.3 0 .1.1.3.2.3h.5l-.3.7H39c-.2 0-.9-.3-.9-.9 0-.6.5-1 .9-1 .2-.1.5.2.5.6 0-.1 0-.1 0 0z"
|
||||
/>
|
||||
<path
|
||||
fill="#5a1f57"
|
||||
d="M39.9 66.7h-1.6c-.1 0-.2-.1-.2-.2v-.3c0-.1.1-.2.2-.2h1.6c.1 0 .2.1.2.2v.3c0 .2-.1.2-.2.2"
|
||||
/>
|
||||
<path fill="#c2b5cf" d="M38.7 66.5h.9V64h-.9v2.5z" />
|
||||
<path
|
||||
fill="#e7e5e2"
|
||||
d="M47.2 35.3C44.7 45.6 36.6 53.1 27 53.1S9.3 45.6 6.8 35.3c-.2.1-.5.1-.8.1-1.1 0-2-.8-2-1.7v-7c0-1 .9-1.7 2-1.7h.2C7.7 13.1 16.4 4 27 4c10.6 0 19.3 9.1 20.8 21h.2c1.1 0 2 .8 2 1.7v7c0 1-.9 1.7-2 1.7-.3 0-.5 0-.8-.1z"
|
||||
/>
|
||||
<path
|
||||
fill="#635e59"
|
||||
d="M19 27.6c-1.4.1-1.9-2-1.4-3.4.1-.3.6-1.5 1.4-1.5.8 0 1.2.7 1.3.8.6 1.4.3 4-1.3 4.1m16.2 0c1.4.1 1.9-2 1.4-3.4-.1-.3-.6-1.5-1.4-1.5-.8 0-1.2.7-1.3.8-.6 1.4-.3 4 1.3 4.1"
|
||||
/>
|
||||
<path
|
||||
fill="#d1bfa3"
|
||||
d="M26.8 34.6c-.4 0-.7-.1-1-.2-.3-.1-.4-.4-.3-.7.1-.3.4-.4.7-.3.5.2 1.5.1 2.2-.4.7-.4 1.1-1 1.2-1.5.1-.4-.1-.9-.4-1.3-.2-.2-.8-.2-1.6-.1-.3 0-.5-.1-.6-.4 0-.3.1-.5.4-.6 1.2-.2 2.1 0 2.6.6.5.7.8 1.4.6 2.1-.1.8-.7 1.6-1.7 2.2-.6.3-1.4.6-2.1.6z"
|
||||
/>
|
||||
<path
|
||||
fill="#593a32"
|
||||
d="M27.1 42.1h-.3c-5.3-.2-7.3-4.1-7.4-4.3-.1-.3 0-.6.2-.7.2-.1.6 0 .7.2.1.1 1.9 3.6 6.6 3.8 4.7.2 6.4-3.7 6.4-3.7.1-.3.4-.4.7-.3.3.1.4.4.3.7-.1 0-2.1 4.3-7.2 4.3z"
|
||||
/>
|
||||
<path
|
||||
fill="#f6b873"
|
||||
d="M6.6 30.7c.1-.1.1-.2.1-.3v-2c-.1-5.6 1.8-8.1 3.4-10.1 0 0-1 4.3-.3 3.4 3.8-5 21.4-1.6 25-8.1.5 3.6-4.1 4.6-4.1 4.6 3.7.7 6.9-.8 7.7-2.5.3 1.4-.6 2.4-1.9 3.4 4.5-.9 4.6-4 4.6-4 .6 4.1 5.3 2.5 5.3 9.3v6c0 .3.2.6.5.6h.5c.3 0 .5-.3.5-.6V26c.3-15.6-8.5-26-20.6-26C15.9 0 5 10.4 5 24.1v6.3c0 .4.2.6.5.6h.6c.2 0 .3-.1.5-.3"
|
||||
/>
|
||||
<path
|
||||
fill="#f6b873"
|
||||
d="M25.9 43.4c-4.4 0-8-1.4-8-3.2s3.6-3.2 8-3.2 8 1.4 8 3.2c0 1.8-3.6 3.2-8 3.2m.8-9.4c-2.9 0-4.7.7-8.8 2.1-12.7 4.6-11.6-14-11.6-14C3.4 46 18.6 52 26.5 52c8.1 0 24.1-8.1 21-30 0 0 .4 17.1-12.9 13.8-3.7-.9-5-1.8-7.9-1.8z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
export const Chromatic: Story = {
|
||||
render: (...props) => (
|
||||
<div>
|
||||
<div>
|
||||
<h2>Size</h2>
|
||||
{Size.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Variants</h2>
|
||||
{Variants.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Position</h2>
|
||||
{Position.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Toptext</h2>
|
||||
{ToptextPosition.render?.(...props)}
|
||||
</div>
|
||||
<div>
|
||||
<h2>Avatar</h2>
|
||||
{Avatar.render?.(...props)}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
chromatic: { disable: false },
|
||||
},
|
||||
};
|
||||
@@ -11,7 +11,6 @@ import { DateWrapper } from "../parts/DateWrapper";
|
||||
import { getLocaleFromString, labels } from "../utils";
|
||||
import DatePickerStandalone from "./DatePickerStandalone";
|
||||
import Caption from "./parts/Caption";
|
||||
import DayButton from "./parts/DayButton";
|
||||
import DropdownCaption from "./parts/DropdownCaption";
|
||||
import { HeadRow } from "./parts/HeadRow";
|
||||
import Row from "./parts/Row";
|
||||
@@ -124,7 +123,6 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(
|
||||
HeadRow,
|
||||
WeekNumber,
|
||||
Row,
|
||||
Day: DayButton,
|
||||
}}
|
||||
className={cl("navds-date", className)}
|
||||
classNames={{
|
||||
|
||||
@@ -5,7 +5,6 @@ import { DateRange, DayPicker, isMatch } from "react-day-picker";
|
||||
import { omit } from "../../util";
|
||||
import { getLocaleFromString, labels } from "../utils";
|
||||
import Caption from "./parts/Caption";
|
||||
import DayButton from "./parts/DayButton";
|
||||
import DropdownCaption from "./parts/DropdownCaption";
|
||||
import { HeadRow } from "./parts/HeadRow";
|
||||
import Row from "./parts/Row";
|
||||
@@ -94,7 +93,6 @@ export const DatePickerStandalone: DatePickerStandaloneType = forwardRef<
|
||||
HeadRow,
|
||||
WeekNumber,
|
||||
Row,
|
||||
Day: DayButton,
|
||||
}}
|
||||
className="navds-date"
|
||||
classNames={{ vhidden: "navds-sr-only" }}
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
import isSameDay from "date-fns/isSameDay";
|
||||
import React, { useId, useState } from "react";
|
||||
import { useDatepicker, useRangeDatepicker } from "..";
|
||||
import { BodyLong, Button, HGrid, Modal, VStack } from "../..";
|
||||
import { Button } from "../../button";
|
||||
import { HGrid } from "../../layout/grid";
|
||||
import { VStack } from "../../layout/stack";
|
||||
import Modal from "../../modal/Modal";
|
||||
import { BodyLong } from "../../typography";
|
||||
import { useDatepicker, useRangeDatepicker } from "../hooks";
|
||||
import DatePicker, { DatePickerProps } from "./DatePicker";
|
||||
|
||||
const disabledDays = [
|
||||
@@ -27,13 +31,13 @@ export const Default: StoryObj<DefaultStoryProps> = {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const rangeCtx = useRangeDatepicker({
|
||||
fromDate: new Date("Aug 23 2020"),
|
||||
toDate: new Date("Aug 23 2023"),
|
||||
fromDate: new Date("Aug 23 2023"),
|
||||
toDate: new Date("Aug 23 2029"),
|
||||
});
|
||||
|
||||
const singleCtx = useDatepicker({
|
||||
fromDate: new Date("Aug 23 2020"),
|
||||
toDate: new Date("Aug 23 2023"),
|
||||
toDate: new Date("Aug 23 2029"),
|
||||
});
|
||||
|
||||
const newProps = {
|
||||
@@ -42,7 +46,7 @@ export const Default: StoryObj<DefaultStoryProps> = {
|
||||
open,
|
||||
onClose: () => setOpen(false),
|
||||
fromDate: new Date("Aug 23 2020"),
|
||||
toDate: new Date("Aug 23 2023"),
|
||||
toDate: new Date("Aug 23 2029"),
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { getUnixTime } from "date-fns";
|
||||
import React from "react";
|
||||
import { Day, useDayPicker } from "react-day-picker";
|
||||
import { useDayPicker } from "react-day-picker";
|
||||
import { Hide } from "../../../layout/responsive";
|
||||
import DayButton from "./DayButton";
|
||||
import WeekNumber from "./WeekNumber";
|
||||
|
||||
/**
|
||||
@@ -37,7 +38,7 @@ function Row(props: RowProps): JSX.Element {
|
||||
style={styles.cell}
|
||||
key={getUnixTime(date)}
|
||||
>
|
||||
<Day displayMonth={props.displayMonth} date={date} />
|
||||
<DayButton displayMonth={props.displayMonth} date={date} />
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
|
||||
@@ -53,7 +53,7 @@ export interface UseDatepickerOptions
|
||||
* Allows input of with 'yy' year format.
|
||||
* @default true
|
||||
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
|
||||
* In 2023 this equals to 1943 - 2042
|
||||
* In 2024 this equals to 1944 - 2043
|
||||
*/
|
||||
allowTwoDigitYear?: boolean;
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,7 @@ export interface UseMonthPickerOptions
|
||||
* Allows input of with 'yy' year format.
|
||||
* @default true
|
||||
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
|
||||
* In 2023 this equals to 1943 - 2042
|
||||
* In 2024 this equals to 1944 - 2043
|
||||
*/
|
||||
allowTwoDigitYear?: boolean;
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
import setYear from "date-fns/setYear";
|
||||
import React, { useId, useState } from "react";
|
||||
import { Button, DateInputProps } from "../..";
|
||||
import { Button } from "../../button";
|
||||
import { useMonthpicker } from "../hooks";
|
||||
import { DateInputProps } from "../parts/DateInput";
|
||||
import MonthPicker from "./MonthPicker";
|
||||
import { MonthPickerProps } from "./types";
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface DateInputProps
|
||||
*/
|
||||
label: React.ReactNode;
|
||||
/**
|
||||
* Shows label and description for screenreaders-only
|
||||
* Shows label and description for screen readers only
|
||||
* @default false
|
||||
*/
|
||||
hideLabel?: boolean;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import cl from "clsx";
|
||||
import React, { useContext, useRef } from "react";
|
||||
import React, { useRef } from "react";
|
||||
import { Button } from "../../button";
|
||||
import { Modal } from "../../modal";
|
||||
import { ModalContext } from "../../modal/ModalContext";
|
||||
import { useModalContext } from "../../modal/Modal.context";
|
||||
import { Popover } from "../../popover";
|
||||
import { useMedia } from "../../util/hooks";
|
||||
import { modalCloseButtonLabel, modalLabel } from "../utils/labels";
|
||||
@@ -30,7 +30,7 @@ export const DateWrapper = ({
|
||||
popoverProps,
|
||||
}: DateWrapperProps) => {
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
const isInModal = useContext(ModalContext) !== null;
|
||||
const isInModal = useModalContext(false) !== undefined;
|
||||
const hideModal =
|
||||
useMedia("screen and (min-width: 768px)", true) && !isInModal;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React, { useState } from "react";
|
||||
import { Dropdown } from "..";
|
||||
import { Button } from "../button";
|
||||
import Dropdown from "./Dropdown";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Dropdown",
|
||||
|
||||
@@ -3,6 +3,7 @@ import React, { forwardRef, useState } from "react";
|
||||
import { BodyShort, ErrorMessage, Label } from "../typography";
|
||||
import { omit } from "../util";
|
||||
import TextareaAutosize from "../util/TextareaAutoSize";
|
||||
import { composeEventHandlers } from "../util/composeEventHandlers";
|
||||
import { useId } from "../util/hooks";
|
||||
import { ReadOnlyIcon } from "./ReadOnlyIcon";
|
||||
import Counter from "./TextareaCounter";
|
||||
@@ -102,7 +103,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
const maxLengthId = useId();
|
||||
const hasMaxLength = maxLength !== undefined && maxLength > 0;
|
||||
|
||||
const [controlledValue, setControlledValue] = useState<string>(
|
||||
const [uncontrolledValue, setUncontrolledValue] = useState(
|
||||
props?.defaultValue ?? "",
|
||||
);
|
||||
|
||||
@@ -161,11 +162,12 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
<TextareaAutosize
|
||||
{...omit(rest, ["error", "errorId", "size"])}
|
||||
{...inputProps}
|
||||
onChange={(e) =>
|
||||
props.onChange
|
||||
? props.onChange(e)
|
||||
: setControlledValue(e.target.value)
|
||||
}
|
||||
onChange={composeEventHandlers(
|
||||
props.onChange,
|
||||
props.value === undefined
|
||||
? (e) => setUncontrolledValue(e.target.value)
|
||||
: undefined,
|
||||
)}
|
||||
minRows={getMinRows()}
|
||||
autoScrollbar={UNSAFE_autoScrollbar}
|
||||
ref={ref}
|
||||
@@ -184,7 +186,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
</span>
|
||||
<Counter
|
||||
maxLength={maxLength}
|
||||
currentLength={props.value?.length ?? controlledValue?.length}
|
||||
currentLength={props.value?.length ?? uncontrolledValue.length}
|
||||
size={size}
|
||||
i18n={i18n}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { ErrorSummary } from "..";
|
||||
import { ErrorSummary } from "./ErrorSummary";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Errorsummary",
|
||||
|
||||
@@ -66,6 +66,10 @@ export interface SearchProps
|
||||
* Exposes the HTML size attribute
|
||||
*/
|
||||
htmlSize?: number | string;
|
||||
/*
|
||||
* Exposes role attribute
|
||||
*/
|
||||
role?: string;
|
||||
}
|
||||
|
||||
interface SearchComponent
|
||||
@@ -114,6 +118,7 @@ export const Search = forwardRef<HTMLInputElement, SearchProps>(
|
||||
onChange,
|
||||
onSearchClick,
|
||||
htmlSize,
|
||||
role,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@@ -205,7 +210,7 @@ export const Search = forwardRef<HTMLInputElement, SearchProps>(
|
||||
value={value ?? internalValue}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
type="search"
|
||||
role="searchbox"
|
||||
role={role ?? "searchbox"}
|
||||
className={cl(
|
||||
className,
|
||||
"navds-search__input",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "../..";
|
||||
import { Link } from "../../link";
|
||||
import { ConfirmationPanel } from "../index";
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Meta, StoryFn, StoryObj } from "@storybook/react";
|
||||
import { expect, userEvent, within } from "@storybook/test";
|
||||
import React, { useState } from "react";
|
||||
import { Button } from "../../button";
|
||||
import { Modal } from "../../modal";
|
||||
import { Textarea } from "../index";
|
||||
|
||||
const meta: Meta<typeof Textarea> = {
|
||||
@@ -124,6 +126,24 @@ export const Resize: StoryFn = () => {
|
||||
return <Textarea resize label="Ipsum enim quis culpa" />;
|
||||
};
|
||||
|
||||
export const OnChange: StoryFn = () => {
|
||||
return (
|
||||
<Textarea
|
||||
label="Ipsum enim quis culpa"
|
||||
onChange={console.log}
|
||||
maxLength={50}
|
||||
/>
|
||||
);
|
||||
};
|
||||
OnChange.play = async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const input = canvas.getByLabelText("Ipsum enim quis culpa");
|
||||
userEvent.click(input);
|
||||
await userEvent.type(input, "Aute fugiat ut culpa");
|
||||
const text = canvas.getByText("30 tegn igjen");
|
||||
expect(text).toBeVisible();
|
||||
};
|
||||
|
||||
export const Controlled: StoryFn = () => {
|
||||
const [value, setValue] = useState("");
|
||||
return (
|
||||
@@ -186,3 +206,20 @@ AutoScrollbar.argTypes = {
|
||||
maxRows: { type: "number" },
|
||||
minRows: { type: "number" },
|
||||
};
|
||||
|
||||
export const ModalStrictMode: StoryFn<typeof Textarea> = () => {
|
||||
// Story added after fixing an issue where TextareaAutoSize would reach max re-renders
|
||||
// and set the height to 2px when used in StrictMode in a Modal that is initially open.
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<Modal open>
|
||||
<Modal.Body>
|
||||
<Textarea label="Har du noen tilbakemeldinger?" />
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</React.StrictMode>
|
||||
);
|
||||
};
|
||||
ModalStrictMode.parameters = {
|
||||
chromatic: { disable: true }, // Not reproducable in Chromatic
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Meta, StoryFn, StoryObj } from "@storybook/react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { BodyLong, Heading, HelpText } from "..";
|
||||
import { BodyLong, Heading } from "../typography";
|
||||
import HelpText from "./HelpText";
|
||||
|
||||
const meta: Meta<typeof HelpText> = {
|
||||
title: "ds-react/HelpText",
|
||||
|
||||
@@ -10,6 +10,7 @@ export * from "./expansion-card";
|
||||
export * from "./form";
|
||||
export * from "./grid";
|
||||
export * from "./guide-panel";
|
||||
export * from "./overlays";
|
||||
export * from "./help-text";
|
||||
export * from "./internal-header";
|
||||
export * from "./link";
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
MenuGridIcon,
|
||||
} from "@navikt/aksel-icons";
|
||||
import { BodyLong, BodyShort, Detail } from "@navikt/ds-react";
|
||||
import { Dropdown, InternalHeader } from "..";
|
||||
import { Dropdown } from "../dropdown";
|
||||
import InternalHeader from "./InternalHeader";
|
||||
|
||||
export default {
|
||||
title: "ds-react/InternalHeader",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { Meta } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { Box, HStack, VStack } from "../..";
|
||||
import { BodyLong } from "../../typography";
|
||||
import { Box } from "../box";
|
||||
import { HStack, VStack } from "../stack";
|
||||
import { Bleed } from "./Bleed";
|
||||
|
||||
export default {
|
||||
@@ -272,6 +273,19 @@ export const Full = {
|
||||
</Bleed>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
className="maxWidth"
|
||||
background="surface-alt-1-subtle"
|
||||
padding="10"
|
||||
>
|
||||
<Box background="surface-alt-2-subtle" padding="10">
|
||||
<Bleed marginInline="full" reflectivePadding asChild>
|
||||
<Box background="surface-success-subtle">
|
||||
<BodyLong>full + reflectivePadding</BodyLong>
|
||||
</Box>
|
||||
</Bleed>
|
||||
</Box>
|
||||
</Box>
|
||||
</VStack>
|
||||
</>
|
||||
),
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { Meta } from "@storybook/react";
|
||||
import React, { ReactNode } from "react";
|
||||
import { ChevronRightIcon } from "@navikt/aksel-icons";
|
||||
import { HGrid, HStack, VStack } from "../..";
|
||||
import { BodyLong, Detail, Heading } from "../../typography";
|
||||
import { HGrid } from "../grid";
|
||||
import { HStack, VStack } from "../stack";
|
||||
import { BackgroundToken, BorderRadiiToken } from "../utilities/types";
|
||||
import { Box } from "./Box";
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { Box, HGrid, Hide, Show, VStack } from "../..";
|
||||
import { Box } from "../box";
|
||||
import { HGrid } from "../grid";
|
||||
import { Hide, Show } from "../responsive";
|
||||
import { VStack } from "../stack";
|
||||
import { Content } from "./Content";
|
||||
import { FilterCard } from "./Filter";
|
||||
import { Header } from "./Header";
|
||||
@@ -13,6 +16,7 @@ const meta = {
|
||||
title: "kitchen sink/navno-sidemal",
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
} satisfies Meta;
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ const translateTokenStringToCSS = (
|
||||
if (componentProp === "margin-inline" && x === "full") {
|
||||
const width = 100 / arr.length;
|
||||
return `calc((100vw - ${width}%)/-2)`;
|
||||
} else if (componentProp === "padding-inline" && x === "full") {
|
||||
const width = 100 / arr.length;
|
||||
return `calc((100vw - ${width}%)/2)`;
|
||||
}
|
||||
|
||||
let output = `var(--a-${tokenSubgroup}-${x})`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { LinkPanel } from "..";
|
||||
import LinkPanel from "./LinkPanel";
|
||||
|
||||
export default {
|
||||
title: "ds-react/LinkPanel",
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import React from "react";
|
||||
import { PlusCircleFillIcon } from "@navikt/aksel-icons";
|
||||
import {
|
||||
BodyLong,
|
||||
Alert as DsAlert,
|
||||
ConfirmationPanel as DsConfirmationPanel,
|
||||
Link,
|
||||
} from "../..";
|
||||
import { Alert } from "../../alert";
|
||||
import { ConfirmationPanel } from "../../form";
|
||||
import { BodyLong } from "../../typography";
|
||||
import Link from "../Link";
|
||||
import { RandomIcon } from "./RandomIcon";
|
||||
|
||||
export default {
|
||||
@@ -139,37 +137,37 @@ const DemoLink = () => (
|
||||
|
||||
export const Icon = () => <DemoLink />;
|
||||
|
||||
export const Alert = () => {
|
||||
export const InAlert = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<DsAlert variant="info">
|
||||
<Alert variant="info">
|
||||
<DemoLink />
|
||||
</DsAlert>
|
||||
<DsAlert variant="success">
|
||||
</Alert>
|
||||
<Alert variant="success">
|
||||
<DemoLink />
|
||||
</DsAlert>
|
||||
<DsAlert variant="warning">
|
||||
</Alert>
|
||||
<Alert variant="warning">
|
||||
<DemoLink />
|
||||
</DsAlert>
|
||||
<DsAlert variant="error">
|
||||
</Alert>
|
||||
<Alert variant="error">
|
||||
<DemoLink />
|
||||
</DsAlert>
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConfirmationPanel = () => {
|
||||
export const InConfirmationPanel = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<DsConfirmationPanel label="demo">
|
||||
<ConfirmationPanel label="demo">
|
||||
<DemoLink />
|
||||
</DsConfirmationPanel>
|
||||
<DsConfirmationPanel checked label="demo">
|
||||
</ConfirmationPanel>
|
||||
<ConfirmationPanel checked label="demo">
|
||||
<DemoLink />
|
||||
</DsConfirmationPanel>
|
||||
<DsConfirmationPanel error="demo" label="demo">
|
||||
</ConfirmationPanel>
|
||||
<ConfirmationPanel error="demo" label="demo">
|
||||
<DemoLink />
|
||||
</DsConfirmationPanel>
|
||||
</ConfirmationPanel>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
HeadHeartIcon,
|
||||
RecycleIcon,
|
||||
} from "@navikt/aksel-icons";
|
||||
import { List, VStack } from "..";
|
||||
import { VStack } from "../layout/stack";
|
||||
import List from "./List";
|
||||
|
||||
export default {
|
||||
title: "ds-react/List",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { Loader, LoaderProps } from "..";
|
||||
import Loader, { LoaderProps } from "./Loader";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Loader",
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { createContext } from "../util/create-context";
|
||||
|
||||
interface ModalContextProps {
|
||||
closeHandler?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
ref: React.RefObject<HTMLDialogElement>;
|
||||
}
|
||||
|
||||
export const [ModalContextProvider, useModalContext] =
|
||||
createContext<ModalContextProps>({
|
||||
name: "ModalContext",
|
||||
errorMessage: "<Modal.Header> must be used within a <Modal>",
|
||||
});
|
||||
@@ -8,8 +8,8 @@ import { Detail, Heading } from "../typography";
|
||||
import { composeEventHandlers } from "../util/composeEventHandlers";
|
||||
import { useId } from "../util/hooks";
|
||||
import { useMergeRefs } from "../util/hooks/useMergeRefs";
|
||||
import { ModalContextProvider, useModalContext } from "./Modal.context";
|
||||
import ModalBody from "./ModalBody";
|
||||
import { ModalContext } from "./ModalContext";
|
||||
import ModalFooter from "./ModalFooter";
|
||||
import ModalHeader from "./ModalHeader";
|
||||
import { getCloseHandler, useBodyScrollLock } from "./ModalUtils";
|
||||
@@ -98,7 +98,7 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
|
||||
const portalNode = useFloatingPortalNode({ root: rootElement });
|
||||
|
||||
const dateContext = useContext(DateContext);
|
||||
const modalContext = useContext(ModalContext);
|
||||
const modalContext = useModalContext(false);
|
||||
if (modalContext && !dateContext) {
|
||||
console.error("Modals should not be nested");
|
||||
}
|
||||
@@ -185,11 +185,9 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
|
||||
onClick={composeEventHandlers(onClick, handleModalClick)}
|
||||
aria-labelledby={mergedAriaLabelledBy}
|
||||
>
|
||||
<ModalContext.Provider
|
||||
value={{
|
||||
closeHandler: getCloseHandler(modalRef, header, onBeforeClose),
|
||||
ref: modalRef,
|
||||
}}
|
||||
<ModalContextProvider
|
||||
closeHandler={getCloseHandler(modalRef, header, onBeforeClose)}
|
||||
ref={modalRef}
|
||||
>
|
||||
{header && (
|
||||
<ModalHeader>
|
||||
@@ -208,7 +206,7 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
|
||||
)}
|
||||
|
||||
{children}
|
||||
</ModalContext.Provider>
|
||||
</ModalContextProvider>
|
||||
</dialog>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
interface ModalContextProps {
|
||||
closeHandler?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
ref: React.RefObject<HTMLDialogElement>;
|
||||
}
|
||||
export const ModalContext = React.createContext<ModalContextProps | null>(null);
|
||||
@@ -1,8 +1,8 @@
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import React, { forwardRef } from "react";
|
||||
import { XMarkIcon } from "@navikt/aksel-icons";
|
||||
import { Button } from "../button";
|
||||
import { ModalContext } from "./ModalContext";
|
||||
import { useModalContext } from "./Modal.context";
|
||||
|
||||
export interface ModalHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children?: React.ReactNode;
|
||||
@@ -15,11 +15,7 @@ export interface ModalHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
|
||||
const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>(
|
||||
({ children, className, closeButton = true, ...rest }, ref) => {
|
||||
const context = useContext(ModalContext);
|
||||
if (context === null) {
|
||||
console.error("<Modal.Header> has to be used within a <Modal>");
|
||||
return null;
|
||||
}
|
||||
const context = useModalContext();
|
||||
|
||||
return (
|
||||
<div {...rest} ref={ref} className={cl("navds-modal__header", className)}>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { FileIcon } from "@navikt/aksel-icons";
|
||||
import { BodyLong, Button, Heading, Tooltip } from "..";
|
||||
import { Button } from "../button";
|
||||
import { Checkbox, CheckboxGroup } from "../form/checkbox";
|
||||
import { VStack } from "../layout/stack";
|
||||
import { Tooltip } from "../tooltip";
|
||||
import { BodyLong, Heading } from "../typography";
|
||||
import Modal from "./Modal";
|
||||
|
||||
const meta: Meta<typeof Modal> = {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export { Portal } from "./portal/Portal";
|
||||
export type { PortalProps } from "./portal/Portal";
|
||||
@@ -0,0 +1,99 @@
|
||||
import React from "react";
|
||||
import { Box } from "../../layout/box";
|
||||
import { Provider } from "../../provider";
|
||||
import { Portal } from "./Portal";
|
||||
|
||||
export default {
|
||||
title: "Utilities/Portal",
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = () => {
|
||||
return (
|
||||
<Box background="surface-neutral-subtle" border>
|
||||
<h1>In regular DOM tree</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
|
||||
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio eum
|
||||
commodi tempora unde. Nulla vel tempora incidunt? Voluptatem molestias
|
||||
impedit commodi. Tenetur!
|
||||
</p>
|
||||
<Portal>
|
||||
<h1>Inside Portal to different DOM tree</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
|
||||
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio
|
||||
eum commodi tempora unde. Nulla vel tempora incidunt? Voluptatem
|
||||
molestias impedit commodi. Tenetur!
|
||||
</p>
|
||||
</Portal>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export const CustomPortalRoot = () => {
|
||||
const [portalContainer, setPortalContainer] =
|
||||
React.useState<HTMLDivElement | null>(null);
|
||||
|
||||
return (
|
||||
<Box background="surface-neutral-subtle">
|
||||
<Box background="surface-alt-1-subtle">
|
||||
<h1>Tree A</h1>
|
||||
<Portal rootElement={portalContainer}>
|
||||
<p>This is mounted to Tree B, while created inside Tree A</p>
|
||||
</Portal>
|
||||
</Box>
|
||||
<Box background="surface-alt-3-subtle" ref={setPortalContainer}>
|
||||
<h1>Tree B</h1>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export const CustomPortalRootFromProvider = () => {
|
||||
const [portalContainer, setPortalContainer] =
|
||||
React.useState<HTMLDivElement>();
|
||||
|
||||
return (
|
||||
<Provider rootElement={portalContainer}>
|
||||
<Box background="surface-neutral-subtle">
|
||||
<Box background="surface-alt-1-subtle">
|
||||
<h1>Tree A</h1>
|
||||
<Portal>
|
||||
<p>This is mounted to Tree B, while created inside Tree A</p>
|
||||
</Portal>
|
||||
</Box>
|
||||
<Box background="surface-alt-3-subtle" ref={setPortalContainer}>
|
||||
<h1>Tree B</h1>
|
||||
</Box>
|
||||
</Box>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const AsChild = () => {
|
||||
return (
|
||||
<Box background="surface-neutral-subtle" border>
|
||||
<h1>In regular DOM tree</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
|
||||
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio eum
|
||||
commodi tempora unde. Nulla vel tempora incidunt? Voluptatem molestias
|
||||
impedit commodi. Tenetur!
|
||||
</p>
|
||||
<Portal asChild>
|
||||
<div data-this-is-the-child>
|
||||
<h1>Inside Portal to different DOM tree</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
|
||||
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio
|
||||
eum commodi tempora unde. Nulla vel tempora incidunt? Voluptatem
|
||||
molestias impedit commodi. Tenetur!
|
||||
</p>
|
||||
</div>
|
||||
</Portal>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import React, { HTMLAttributes, forwardRef } from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { useProvider } from "../../provider";
|
||||
import { Slot } from "../../util/Slot";
|
||||
import { AsChildProps } from "../../util/types";
|
||||
|
||||
interface PortalBaseProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* An optional container where the portaled content should be appended.
|
||||
*/
|
||||
rootElement?: HTMLElement | null;
|
||||
}
|
||||
|
||||
export type PortalProps = PortalBaseProps & AsChildProps;
|
||||
|
||||
export const Portal = forwardRef<HTMLDivElement, PortalProps>(
|
||||
({ rootElement, asChild, ...rest }, ref) => {
|
||||
const contextRoot = useProvider()?.rootElement;
|
||||
const root = rootElement ?? contextRoot ?? globalThis?.document?.body;
|
||||
|
||||
const Component = asChild ? Slot : "div";
|
||||
|
||||
return root
|
||||
? ReactDOM.createPortal(
|
||||
<Component ref={ref} data-aksel-portal="" {...rest} />,
|
||||
root,
|
||||
)
|
||||
: null;
|
||||
},
|
||||
);
|
||||
|
||||
export default Portal;
|
||||
@@ -2,6 +2,9 @@ import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "../util/types";
|
||||
|
||||
/**
|
||||
* @deprecated Use Box with padding and border instead
|
||||
*/
|
||||
export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
|
||||
/**
|
||||
* Panel content
|
||||
@@ -17,23 +20,13 @@ export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
|
||||
export type PanelType = OverridableComponent<PanelProps, HTMLElement>;
|
||||
|
||||
/**
|
||||
* A component that displays a bordered panel with heading and body.
|
||||
*
|
||||
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/panel)
|
||||
* @see 🏷️ {@link PanelProps}
|
||||
* @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
|
||||
*
|
||||
* @example
|
||||
* ```jsx
|
||||
* <Panel border>
|
||||
* <Heading spacing level="2" size="large">
|
||||
* Søk om økonomisk sosialhjelp
|
||||
* </Heading>
|
||||
* <BodyLong>
|
||||
* Du kan søke om det du trenger økonomisk støtte til.
|
||||
* </BodyLong>
|
||||
* </Panel>
|
||||
* @deprecated
|
||||
* Use Box with padding and border instead
|
||||
* ```
|
||||
* <Box padding="4" borderRadius="small" />
|
||||
* <Box padding="4" borderWidth="1" borderRadius="small" />
|
||||
* ```
|
||||
* Component will be removed in a future major release
|
||||
*/
|
||||
export const Panel: PanelType = forwardRef(
|
||||
(
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React from "react";
|
||||
import { Panel } from "../index";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Panel",
|
||||
component: Panel,
|
||||
argTypes: {
|
||||
border: {
|
||||
defaultValue: true,
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
export const Default = {
|
||||
render: (props) => {
|
||||
return (
|
||||
<Panel {...props}>
|
||||
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
|
||||
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
|
||||
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
|
||||
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
|
||||
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
|
||||
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
|
||||
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
|
||||
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
|
||||
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
|
||||
</Panel>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Border = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Panel>
|
||||
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
|
||||
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
|
||||
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
|
||||
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
|
||||
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
|
||||
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
|
||||
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
|
||||
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
|
||||
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
|
||||
</Panel>
|
||||
<Panel border>
|
||||
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
|
||||
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
|
||||
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
|
||||
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
|
||||
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
|
||||
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
|
||||
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
|
||||
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
|
||||
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
|
||||
</Panel>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -18,7 +18,7 @@ import React, {
|
||||
useRef,
|
||||
} from "react";
|
||||
import { DateContext } from "../date/context";
|
||||
import { ModalContext } from "../modal/ModalContext";
|
||||
import { useModalContext } from "../modal/Modal.context";
|
||||
import { useClientLayoutEffect, useEventListener } from "../util/hooks";
|
||||
import { useMergeRefs } from "../util/hooks/useMergeRefs";
|
||||
import PopoverContent, { PopoverContentType } from "./PopoverContent";
|
||||
@@ -126,7 +126,7 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
|
||||
ref,
|
||||
) => {
|
||||
const arrowRef = useRef<HTMLDivElement | null>(null);
|
||||
const isInModal = useContext(ModalContext) !== null;
|
||||
const isInModal = useModalContext(false) !== undefined;
|
||||
const isInDatepicker = useContext(DateContext) !== null;
|
||||
const chosenStrategy = userStrategy ?? (isInModal ? "fixed" : "absolute");
|
||||
const chosenFlip = isInDatepicker ? false : _flip;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Meta } from "@storybook/react";
|
||||
import React, { useState } from "react";
|
||||
import { BodyLong } from "..";
|
||||
import { BodyLong } from "../typography";
|
||||
import Stepper from "./Stepper";
|
||||
|
||||
const meta: Meta<typeof Stepper> = {
|
||||
|
||||
+120
-94
@@ -1,16 +1,27 @@
|
||||
import React, { useState } from "react";
|
||||
import { Table, TableProps } from "../";
|
||||
import { Alert, Button, Checkbox, CheckboxGroup, Link } from "../..";
|
||||
import { Button } from "../../button";
|
||||
import { Checkbox } from "../../form";
|
||||
import { VStack } from "../../layout/stack";
|
||||
import {
|
||||
Expandable,
|
||||
ExpandableLarge,
|
||||
ExpandableSmall,
|
||||
} from "./table-2-expandable.stories";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Table",
|
||||
component: Table,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
interface Props extends TableProps {
|
||||
button?: boolean;
|
||||
shadeOnHover?: boolean;
|
||||
}
|
||||
|
||||
const TableComponent = ({ button, shadeOnHover, ...rest }: Props) => (
|
||||
<Table {...rest}>
|
||||
<Table.Header>
|
||||
@@ -89,75 +100,59 @@ export const Buttons = () => <TableComponent size="small" button />;
|
||||
|
||||
export const WithDivs = () => {
|
||||
return (
|
||||
<>
|
||||
<Alert variant="warning">
|
||||
Obs! Hvis man skal bygge tabeller uten å bruke vanlig {"<tabell> "}
|
||||
-markup er det svært viktig at man supplerer elementene med{" "}
|
||||
<Link href="https://www.w3.org/TR/wai-aria-practices-1.1/examples/table/table.html">
|
||||
riktige
|
||||
</Link>{" "}
|
||||
role-attributter og display-stiler for å bevare den semantiske verdien i
|
||||
tabellene. Vi anbefaler fortsatt å ikke ta i bruk denne metoden hvis
|
||||
mulig, da nettleseren ikke kan tolke tabellen like bra uten riktig
|
||||
markup.
|
||||
</Alert>
|
||||
<div className="navds-table" role="table">
|
||||
<div className="navds-table__header" role="rowgroup">
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Fornavn
|
||||
</div>
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Etternavn
|
||||
</div>
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Rolle
|
||||
</div>
|
||||
<div className="navds-table" role="table">
|
||||
<div className="navds-table__header" role="rowgroup">
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Fornavn
|
||||
</div>
|
||||
</div>
|
||||
<div className="navds-table__body" role="rowgroup">
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Jean-Luc
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Picard
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Kaptein
|
||||
</div>
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Etternavn
|
||||
</div>
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
William
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Riker
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Kommandør
|
||||
</div>
|
||||
</div>
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Geordi
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
La Forge
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Sjefsingeniør
|
||||
</div>
|
||||
<div className="navds-table__header-cell" role="columnheader">
|
||||
Rolle
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
<div className="navds-table__body" role="rowgroup">
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Jean-Luc
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Picard
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Kaptein
|
||||
</div>
|
||||
</div>
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
William
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Riker
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Kommandør
|
||||
</div>
|
||||
</div>
|
||||
<div className="navds-table__row" role="row">
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Geordi
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
La Forge
|
||||
</div>
|
||||
<div className="navds-table__data-cell" role="cell">
|
||||
Sjefsingeniør
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Selection = () => <SelectionTable />;
|
||||
export const SelectionSmall = () => <SelectionTable size="small" />;
|
||||
|
||||
const SelectionTable = ({ size = "medium" }: { size?: "small" | "medium" }) => {
|
||||
const useToggleList = (initialState) => {
|
||||
const [list, setList] = useState(initialState);
|
||||
@@ -182,7 +177,7 @@ const SelectionTable = ({ size = "medium" }: { size?: "small" | "medium" }) => {
|
||||
<Table.DataCell>
|
||||
<Checkbox
|
||||
size={size}
|
||||
checked={selectedRows.includes("all")}
|
||||
indeterminate
|
||||
onChange={() => toggleSelectedRow("all")}
|
||||
>
|
||||
Select all
|
||||
@@ -212,12 +207,12 @@ const SelectionTable = ({ size = "medium" }: { size?: "small" | "medium" }) => {
|
||||
<Table.DataCell>USA</Table.DataCell>
|
||||
<Table.DataCell>38</Table.DataCell>
|
||||
</Table.Row>
|
||||
<Table.Row selected={selectedRows.includes("2")}>
|
||||
<Table.Row selected>
|
||||
<Table.DataCell>
|
||||
<Checkbox
|
||||
size={size}
|
||||
hideLabel
|
||||
checked={selectedRows.includes("2")}
|
||||
checked
|
||||
onChange={() => toggleSelectedRow("2")}
|
||||
aria-labelledby={`x_r2-${size}`}
|
||||
>
|
||||
@@ -231,36 +226,67 @@ const SelectionTable = ({ size = "medium" }: { size?: "small" | "medium" }) => {
|
||||
<Table.DataCell>Denmark</Table.DataCell>
|
||||
<Table.DataCell>11</Table.DataCell>
|
||||
</Table.Row>
|
||||
<Table.Row selected={selectedRows.includes("3")}>
|
||||
<Table.DataCell>
|
||||
<CheckboxGroup legend="velg flere felt" hideLegend>
|
||||
<Checkbox
|
||||
size={size}
|
||||
hideLabel
|
||||
checked={selectedRows.includes("3")}
|
||||
onChange={() => toggleSelectedRow("3")}
|
||||
aria-labelledby={`x_r3-${size}`}
|
||||
>
|
||||
{" "}
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
size={size}
|
||||
hideLabel
|
||||
checked={selectedRows.includes("3")}
|
||||
onChange={() => toggleSelectedRow("3")}
|
||||
aria-labelledby={`x_r3-${size}`}
|
||||
>
|
||||
{" "}
|
||||
</Checkbox>
|
||||
</CheckboxGroup>
|
||||
</Table.DataCell>
|
||||
<Table.HeaderCell scope="row" colSpan={4}>
|
||||
<span id={`x_r3-${size}`}>
|
||||
Don't stack multiple checkboxes
|
||||
</span>
|
||||
</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
export const Selection = () => <SelectionTable />;
|
||||
export const SelectionSmall = () => <SelectionTable size="small" />;
|
||||
|
||||
export const Chromatic = {
|
||||
render: () => (
|
||||
<VStack gap="8">
|
||||
<div>
|
||||
<h3>Default</h3>
|
||||
<Default />
|
||||
<h3>Zebra</h3>
|
||||
<Zebra />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Large</h3>
|
||||
<SizeLarge />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Medium</h3>
|
||||
<SizeMedium />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Small</h3>
|
||||
<SizeSmall />
|
||||
</div>
|
||||
<div>
|
||||
<h3>With Buttons</h3>
|
||||
<Buttons />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Custom with divs</h3>
|
||||
<WithDivs />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Selection</h3>
|
||||
<Selection />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Selection small</h3>
|
||||
<SelectionSmall />
|
||||
</div>
|
||||
<h2>Expandable</h2>
|
||||
<div>
|
||||
<h3>Large</h3>
|
||||
<ExpandableLarge />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Medium</h3>
|
||||
<Expandable />
|
||||
</div>
|
||||
<div>
|
||||
<h3>Small</h3>
|
||||
<ExpandableSmall />
|
||||
</div>
|
||||
</VStack>
|
||||
),
|
||||
parameters: {
|
||||
chromatic: { disable: false },
|
||||
},
|
||||
};
|
||||
+10
-34
@@ -1,10 +1,15 @@
|
||||
import React, { useState } from "react";
|
||||
import { Table } from "..";
|
||||
import { Button, Checkbox, Link } from "../..";
|
||||
import { Button } from "../../button";
|
||||
import { Checkbox } from "../../form";
|
||||
import { Link } from "../../link";
|
||||
import Table from "../Table";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Table",
|
||||
component: Table,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
export const Expandable = () => {
|
||||
@@ -25,6 +30,7 @@ export const Expandable = () => {
|
||||
content={row.content}
|
||||
key={row.name}
|
||||
togglePlacement="right"
|
||||
defaultOpen
|
||||
>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{row[key]}</Table.DataCell>
|
||||
@@ -50,7 +56,7 @@ export const ExpandableLarge = () => {
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{data.slice(0, 1).map((row) => (
|
||||
<Table.ExpandableRow content={row.content} key={row.name}>
|
||||
<Table.ExpandableRow defaultOpen content={row.content} key={row.name}>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{row[key]}</Table.DataCell>
|
||||
))}
|
||||
@@ -87,7 +93,7 @@ export const ExpandableSmall = () => {
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{data.slice(0, 1).map((row) => (
|
||||
<Table.ExpandableRow content={row.content} key={row.name}>
|
||||
<Table.ExpandableRow defaultOpen content={row.content} key={row.name}>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{row[key]}</Table.DataCell>
|
||||
))}
|
||||
@@ -235,36 +241,6 @@ const data = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ExpandableOpen = () => {
|
||||
return (
|
||||
<Table zebraStripes>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
{columns.map(({ key, name }) => (
|
||||
<Table.HeaderCell key={key}>{name}</Table.HeaderCell>
|
||||
))}
|
||||
<Table.HeaderCell />
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{data.map((row) => (
|
||||
<Table.ExpandableRow
|
||||
expansionDisabled={row.animal === "Sel"}
|
||||
content={row.content}
|
||||
key={row.name}
|
||||
togglePlacement="right"
|
||||
defaultOpen
|
||||
>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{row[key]}</Table.DataCell>
|
||||
))}
|
||||
</Table.ExpandableRow>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
export const ClickableRow = () => {
|
||||
const [isRowOpen1, setIsRowOpen1] = useState(false);
|
||||
const [isRowOpen2, setIsRowOpen2] = useState(false);
|
||||
+5
-3
@@ -1,14 +1,16 @@
|
||||
import React, { useState } from "react";
|
||||
import useSWR from "swr";
|
||||
import { Loader, Pagination, SortState } from "../..";
|
||||
import { Table } from "../index";
|
||||
import { Loader } from "../../loader";
|
||||
import { Pagination } from "../../pagination";
|
||||
import Table from "../Table";
|
||||
import { SortState } from "../types";
|
||||
import peopleJson from "./people.json";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Table",
|
||||
component: Table,
|
||||
parameters: {
|
||||
chromatic: { delay: 500 },
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { expect, fn, userEvent, within } from "@storybook/test";
|
||||
import React from "react";
|
||||
import { Table } from "../..";
|
||||
import Table from "../../Table";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Table/Tests",
|
||||
component: Table,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
};
|
||||
|
||||
export const ClickableRowTest = {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import { Tabs } from "./Tabs";
|
||||
|
||||
const TestTabs = ({
|
||||
value,
|
||||
onChange,
|
||||
defaultValue,
|
||||
selectionFollowsFocus,
|
||||
loop,
|
||||
iconPosition,
|
||||
}: any) => (
|
||||
<Tabs
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
defaultValue={defaultValue}
|
||||
selectionFollowsFocus={selectionFollowsFocus}
|
||||
loop={loop}
|
||||
iconPosition={iconPosition}
|
||||
>
|
||||
<Tabs.List data-testid="tablist">
|
||||
<Tabs.Tab value="tab1" data-testid="tab1" label="Tab 1" />
|
||||
<Tabs.Tab value="tab2" data-testid="tab2" label="Tab 2" />
|
||||
<Tabs.Tab value="tab3" data-testid="tab3" label="Tab 3" />
|
||||
</Tabs.List>
|
||||
<Tabs.Panel value="tab1" data-testid="tabpanel1">
|
||||
Tabpanel 1
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="tab2" data-testid="tabpanel2">
|
||||
Tabpanel 2
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="tab3" data-testid="tabpanel3">
|
||||
Tabpanel 3
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
describe("Tabs", () => {
|
||||
test("sets default value correctly", () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const tab = screen.getByTestId("tab2");
|
||||
const panel = screen.getByTestId("tabpanel2");
|
||||
|
||||
expect(tab).toHaveAttribute("aria-selected", "true");
|
||||
expect(panel).toHaveTextContent("Tabpanel 2");
|
||||
});
|
||||
|
||||
test("label-connection between tab and tabpanel is correct", async () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const tab = screen.getByTestId("tab2");
|
||||
const panel = screen.getByTestId("tabpanel2");
|
||||
|
||||
const controlsId = tab.getAttribute("aria-controls");
|
||||
const panelLabelledBy = panel.getAttribute("aria-labelledby");
|
||||
|
||||
expect(controlsId).toEqual(panel.id);
|
||||
expect(tab.id).toEqual(panelLabelledBy);
|
||||
});
|
||||
|
||||
test("sets correct attributes on active tab", () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const tab = screen.getByTestId("tab2");
|
||||
|
||||
expect(tab).toHaveAttribute("aria-selected", "true");
|
||||
expect(tab).toHaveAttribute("role", "tab");
|
||||
expect(tab).toHaveAttribute("aria-controls");
|
||||
expect(tab).toHaveAttribute("tabindex", "-1");
|
||||
});
|
||||
|
||||
test("sets correct attributes on idle tab", () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const tab = screen.getByTestId("tab1");
|
||||
|
||||
expect(tab).toHaveAttribute("aria-selected", "false");
|
||||
expect(tab).toHaveAttribute("role", "tab");
|
||||
expect(tab).toHaveAttribute("aria-controls");
|
||||
expect(tab).toHaveAttribute("tabindex", "-1");
|
||||
});
|
||||
|
||||
test("sets correct attributes on active tabpanel", () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const panel = screen.getByTestId("tabpanel2");
|
||||
|
||||
expect(panel).toHaveAttribute("aria-labelledby");
|
||||
expect(panel).toHaveAttribute("role", "tabpanel");
|
||||
expect(panel).toHaveAttribute("tabindex", "0");
|
||||
expect(panel).toHaveTextContent("Tabpanel 2");
|
||||
expect(panel).toHaveStyle({ display: "block" });
|
||||
});
|
||||
|
||||
test("sets correct attributes on idle tabpanel", () => {
|
||||
render(<TestTabs defaultValue="tab1" />);
|
||||
const panel = screen.getByTestId("tabpanel2");
|
||||
|
||||
expect(panel).toHaveAttribute("aria-labelledby");
|
||||
expect(panel).toHaveAttribute("role", "tabpanel");
|
||||
expect(panel).toHaveAttribute("tabindex", "0");
|
||||
expect(panel).toBeEmptyDOMElement();
|
||||
expect(panel).toHaveStyle({ display: "none" });
|
||||
});
|
||||
|
||||
test("sets tabindex to 0 when focused", () => {
|
||||
render(<TestTabs defaultValue="tab2" />);
|
||||
const tab = screen.getByTestId("tab2");
|
||||
|
||||
fireEvent.focus(tab);
|
||||
expect(tab).toHaveAttribute("tabindex", "0");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import React from "react";
|
||||
import { ToggleGroup } from "./ToggleGroup";
|
||||
|
||||
const TestToggleGroup = ({ value, onChange, defaultValue }: any) => (
|
||||
<ToggleGroup value={value} onChange={onChange} defaultValue={defaultValue}>
|
||||
<ToggleGroup.Item value="toggle1" data-testid="toggle1">
|
||||
Toggle 1
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="toggle2" data-testid="toggle2">
|
||||
Toggle 2
|
||||
</ToggleGroup.Item>
|
||||
<ToggleGroup.Item value="toggle3" data-testid="toggle3">
|
||||
Toggle 3
|
||||
</ToggleGroup.Item>
|
||||
</ToggleGroup>
|
||||
);
|
||||
|
||||
describe("ToggleGroup", () => {
|
||||
test("sets default value correctly", () => {
|
||||
render(<TestToggleGroup defaultValue="toggle2" />);
|
||||
const toggle = screen.getByTestId("toggle2");
|
||||
|
||||
expect(toggle).toHaveAttribute("aria-checked", "true");
|
||||
});
|
||||
|
||||
test("sets correct attributes on active toggle", () => {
|
||||
render(<TestToggleGroup defaultValue="toggle2" />);
|
||||
const toggle = screen.getByTestId("toggle2");
|
||||
|
||||
expect(toggle).toHaveAttribute("aria-checked", "true");
|
||||
expect(toggle).toHaveAttribute("role", "radio");
|
||||
expect(toggle).toHaveAttribute("type", "button");
|
||||
expect(toggle).toHaveAttribute("tabindex", "-1");
|
||||
});
|
||||
|
||||
test("sets correct attributes on idle toggle", () => {
|
||||
render(<TestToggleGroup defaultValue="toggle1" />);
|
||||
const toggle = screen.getByTestId("toggle2");
|
||||
|
||||
expect(toggle).toHaveAttribute("aria-checked", "false");
|
||||
expect(toggle).toHaveAttribute("role", "radio");
|
||||
expect(toggle).toHaveAttribute("type", "button");
|
||||
expect(toggle).toHaveAttribute("tabindex", "-1");
|
||||
});
|
||||
|
||||
test("sets tabindex to 0 when focused", () => {
|
||||
render(<TestToggleGroup defaultValue="toggle2" />);
|
||||
const toggle = screen.getByTestId("toggle2");
|
||||
|
||||
fireEvent.focus(toggle);
|
||||
expect(toggle).toHaveAttribute("tabindex", "0");
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
FloatingPortal,
|
||||
autoUpdate,
|
||||
arrow as flArrow,
|
||||
flip,
|
||||
@@ -13,15 +12,9 @@ import {
|
||||
useInteractions,
|
||||
} from "@floating-ui/react";
|
||||
import cl from "clsx";
|
||||
import React, {
|
||||
HTMLAttributes,
|
||||
cloneElement,
|
||||
forwardRef,
|
||||
useContext,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { ModalContext } from "../modal/ModalContext";
|
||||
import { useProvider } from "../provider";
|
||||
import React, { HTMLAttributes, cloneElement, forwardRef, useRef } from "react";
|
||||
import { useModalContext } from "../modal/Modal.context";
|
||||
import Portal from "../overlays/portal/Portal";
|
||||
import { Detail } from "../typography";
|
||||
import { useId } from "../util/hooks";
|
||||
import { useControllableState } from "../util/hooks/useControllableState";
|
||||
@@ -122,11 +115,8 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||
});
|
||||
|
||||
const arrowRef = useRef<HTMLDivElement | null>(null);
|
||||
const modalContext = useContext(ModalContext);
|
||||
const providerRootElement = useProvider()?.rootElement;
|
||||
const rootElement = modalContext
|
||||
? modalContext.ref.current
|
||||
: providerRootElement;
|
||||
const modalContext = useModalContext(false);
|
||||
const rootElement = modalContext ? modalContext.ref.current : undefined;
|
||||
|
||||
const {
|
||||
x,
|
||||
@@ -199,7 +189,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||
: children?.props["aria-describedby"],
|
||||
}),
|
||||
)}
|
||||
<FloatingPortal root={rootElement}>
|
||||
<Portal rootElement={rootElement}>
|
||||
{_open && (
|
||||
<div
|
||||
{...getFloatingProps({
|
||||
@@ -253,7 +243,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</FloatingPortal>
|
||||
</Portal>
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
||||
Loaded 100 of 168 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user