Compare commits

...
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] fbc598529c Version Packages (#2262)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-07 14:24:26 +02:00
Ken 1df8dcd857 🎨 Oppdatert prismjs og codeview (#2251) 2023-09-07 14:02:10 +02:00
Ken 7be9dd88ca Responsive Show/Hide-komponenter (#2222) 2023-09-07 12:47:49 +02:00
Ken 4d9691413a 🐛 Fikset lightmode-theming (#2238) 2023-09-07 12:45:31 +02:00
Ken 2989853f39 ♻️ Oppdatert Search escape håndtering (#2245) 2023-09-07 12:41:45 +02:00
Ken bff7c836f8 🎨 ErrorSummary border-radius (#2256) 2023-09-07 12:41:21 +02:00
github-actions[bot]andgithub-actions[bot] b906ca469d Version Packages (#2259)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-07 10:42:56 +02:00
Halvor Haugan ed9286f75b 🐛 Popover: sjekk at det er et HTML-element som får fokus (#2258) 2023-09-07 10:39:03 +02:00
github-actions[bot]andgithub-actions[bot] 445f6b8309 Version Packages (#2252)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-07 09:10:15 +02:00
Ken 27dacfdbe9 🐛 Fikset SVG import path (#2250) 2023-09-06 20:12:49 +02:00
Ken b8b7ad142d 🎨 Synket alert med figma (#2240) 2023-09-06 15:59:31 +02:00
github-actions[bot]andgithub-actions[bot] 29b244e69b Version Packages (#2248)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-06 15:07:20 +02:00
KenandLars Eirik Korsgaard Hansen 6f2325bbb3 🎨 HGrid align-prop (#2242)
Co-authored-by: Lars Eirik Korsgaard Hansen <71271458+larseirikhansen@users.noreply.github.com>
2023-09-06 15:04:26 +02:00
github-actions[bot]andgithub-actions[bot] 9f575b76b8 Version Packages (#2246)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-06 11:11:51 +02:00
Ken 4e05993427 🎨 Skeleton as-prop (#2239) 2023-09-06 11:03:28 +02:00
Halvor Haugan 85a7521197 🐛 fiks createPackageJsonsWithESMPointers i Windows (#2237) 2023-09-05 12:35:31 +02:00
Halvor HauganandKen f635be70d0 🏷️ Forbedret typesjekking i stories (#2234)
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2023-09-04 17:06:34 +02:00
Ken b675a5b9ba 🛂 Permissions for chromatic-workflow (#2235) 2023-09-04 17:04:11 +02:00
Ken cc842113c3 ✨ Primitives-kategori 2023-09-04 12:09:35 +02:00
Ken f36d4c46d7 🐛 Fikset Typo-eksempler, dupliserte prop-entries 2023-09-03 14:22:40 +02:00
Ken d7bd84f6ee ⬆️ Oppdatert sanity (#2228) 2023-09-03 13:18:38 +02:00
189 changed files with 2944 additions and 1455 deletions

No files matched your search

+8 -4
View File
@@ -15,6 +15,10 @@ jobs:
visual_regression_test:
name: "visual regression test (chromatic)"
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
contents: write
steps:
- uses: actions/checkout@v3
with:
@@ -54,7 +58,7 @@ jobs:
- name: replace storybook url
if: "!contains(github.event.head_commit.message, '[ci skip]') && github.event_name != 'push'"
uses: frabert/replace-string-action@v2.0
uses: frabert/replace-string-action@v2
id: storybook_url
with:
pattern: "(iframe.html)"
@@ -70,7 +74,7 @@ jobs:
- name: Find Comment
if: "!contains(github.event.head_commit.message, '[ci skip]') && github.event_name != 'push'"
uses: peter-evans/find-comment@v1
uses: peter-evans/find-comment@v2
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
@@ -79,7 +83,7 @@ jobs:
- name: Create or update comment
if: steps.chromatic_tests.outcome == 'success' && !contains(github.event.head_commit.message, '[ci skip]') && github.event_name != 'push'
uses: peter-evans/create-or-update-comment@v1
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
@@ -91,7 +95,7 @@ jobs:
- name: Create or update failed comment
if: steps.chromatic_tests.outcome != 'success' && !contains(github.event.head_commit.message, '[ci skip]') && github.event_name != 'push'
uses: peter-evans/create-or-update-comment@v1
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
+14
View File
@@ -1,5 +1,19 @@
# @navikt/aksel-icons
## 5.4.0
## 5.3.5
## 5.3.4
### Patch Changes
- :bug: SVG import map er nå riktig path ([#2250](https://github.com/navikt/aksel/pull/2250))
## 5.3.3
## 5.3.2
## 5.3.1
## 5.3.0
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-icons",
"version": "5.3.1",
"version": "5.4.0",
"author": "Aksel | NAV",
"homepage": "https://aksel.nav.no/ikoner",
"repository": {
@@ -33,7 +33,7 @@
"import": "./dist/react/esm/index.js",
"require": "./dist/react/cjs/index.js"
},
"./svg/*.svg": "./dist/react/svg/*.svg",
"./svg/*.svg": "./dist/svg/*.svg",
"./metadata": {
"types": "./dist/metadata.d.ts",
"default": "./dist/metadata.js"
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "../../tsconfig.json",
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"outDir": "./dist/react/cjs",
"module": "commonjs",
+10
View File
@@ -1,5 +1,15 @@
# @navikt/aksel-stylelint
## 5.4.0
## 5.3.5
## 5.3.4
## 5.3.3
## 5.3.2
## 5.3.1
## 5.3.0
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-stylelint",
"version": "5.3.1",
"version": "5.4.0",
"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.3.1",
"@navikt/ds-tokens": "^5.3.1",
"@navikt/ds-css": "^5.4.0",
"@navikt/ds-tokens": "^5.4.0",
"@types/jest": "^29.0.0",
"concurrently": "7.2.1",
"copyfiles": "2.4.1",
+35
View File
@@ -1,5 +1,40 @@
# @navikt/aksel
## 5.4.0
### Patch Changes
- Updated dependencies [[`bff7c836f`](https://github.com/navikt/aksel/commit/bff7c836f8b0c604da1bfac49f60d6ae07d04624), [`7be9dd88c`](https://github.com/navikt/aksel/commit/7be9dd88ca8751aa03ddb9f40c21990b6d81a26a)]:
- @navikt/ds-css@5.4.0
## 5.3.5
### Patch Changes
- Updated dependencies []:
- @navikt/ds-css@5.3.5
## 5.3.4
### Patch Changes
- Updated dependencies [[`b8b7ad142`](https://github.com/navikt/aksel/commit/b8b7ad142dfb8a202c4adb115e3d2491ce917205)]:
- @navikt/ds-css@5.3.4
## 5.3.3
### Patch Changes
- Updated dependencies [[`6f2325bbb`](https://github.com/navikt/aksel/commit/6f2325bbb32de87d649a476a8c58e5f352e1d016)]:
- @navikt/ds-css@5.3.3
## 5.3.2
### Patch Changes
- Updated dependencies [[`4e0599342`](https://github.com/navikt/aksel/commit/4e0599342761f2a0fe2177c370f4bcf4fab7ef8a)]:
- @navikt/ds-css@5.3.2
## 5.3.1
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel",
"version": "5.3.1",
"version": "5.4.0",
"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.3.1",
"@navikt/ds-css": "5.4.0",
"axios": "1.3.6",
"chalk": "4.1.0",
"clipboardy": "^2.3.0",
@@ -7,6 +7,7 @@ import {
componentDir,
rootDir,
globalDir,
primitivesCss,
} from "@navikt/ds-css/config/_mappings";
import { inquiry } from "./inquiry";
import clipboard from "clipboardy";
@@ -143,6 +144,13 @@ function advancedOutput(
componentImportsList.unshift(formCss);
}
if (componentImportsList.find((x) => x === primitivesCss)) {
componentImportsList = componentImportsList.filter(
(x) => x !== primitivesCss
);
componentImportsList.unshift(primitivesCss);
}
if (componentImportsList.find((x) => x === typoCss)) {
componentImportsList = componentImportsList.filter((x) => x !== typoCss);
componentImportsList.unshift(typoCss);
+30
View File
@@ -1,5 +1,35 @@
# @navikt/ds-css
## 5.4.0
### Minor Changes
- Primitives: Nye komponenter `Show` og `Hide` er lagt til. ([#2222](https://github.com/navikt/aksel/pull/2222))
### Patch Changes
- ErrorSummary: Har nå 8px border-radius ([#2256](https://github.com/navikt/aksel/pull/2256))
## 5.3.5
## 5.3.4
### Patch Changes
- Alert: 12px -> 8px gap mellom tekst og ikon ved `size="small"` ([#2240](https://github.com/navikt/aksel/pull/2240))
## 5.3.3
### Patch Changes
- HGrid: Har nå `align`-prop for bedre kontroll over child-elementer ([#2242](https://github.com/navikt/aksel/pull/2242))
## 5.3.2
### Patch Changes
- Skeleton: Lagt til as-prop for inline brk av Skeleton med span ([#2239](https://github.com/navikt/aksel/pull/2239))
## 5.3.1
### Patch Changes
+16 -6
View File
@@ -11,8 +11,17 @@
max-width: 43.5rem;
}
.navds-alert--close-button > .navds-alert__wrapper {
margin-block-start: var(--a-spacing-05);
}
.navds-alert--small.navds-alert--close-button > .navds-alert__wrapper {
margin-block-start: var(--a-spacing-1);
}
.navds-alert--small {
padding: var(--a-spacing-2) var(--a-spacing-4);
gap: var(--a-spacing-2);
}
.navds-alert--full-width {
@@ -24,19 +33,20 @@
font-size: 1.5rem;
align-self: flex-start;
height: var(--a-font-line-height-xlarge);
margin-inline: var(--a-spacing-1);
margin-block: 0;
margin-block-start: -1px;
background: radial-gradient(circle, var(--a-surface-default) 50%, 0, transparent);
}
.navds-alert--close-button > .navds-alert__icon,
.navds-alert--small > .navds-alert__icon {
margin-block-start: 0;
height: var(--a-font-line-height-large);
}
.navds-alert--small > .navds-alert__icon {
height: var(--a-font-line-height-large);
.navds-alert--close-button > .navds-alert__icon {
margin-block-start: var(--a-spacing-05);
}
.navds-alert--small.navds-alert--close-button > .navds-alert__icon {
margin-block-start: var(--a-spacing-1);
}
.navds-alert--error {
+66 -34
View File
@@ -1,18 +1,35 @@
[data-theme="dark"] {
--ac-button-primary-text: var(--a-gray-900);
--ac-button-primary-bg: var(--a-blue-200);
--ac-button-primary-focus-border: var(--a-gray-900);
--ac-button-primary-hover-bg: var(--a-blue-300);
--ac-button-primary-active-bg: var(--a-blue-400);
--ac-button-secondary-text: var(--a-white);
--ac-button-secondary-hover-text: var(--a-white);
--ac-button-secondary-active-text: var(--a-white);
--ac-button-secondary-active-focus-border: var(--a-gray-900);
--ac-button-secondary-bg: var(--a-gray-900);
--ac-button-secondary-border: var(--a-blue-200);
--ac-button-secondary-hover-bg: var(--a-gray-800);
--ac-button-secondary-focus-border: var(--a-blue-200);
--ac-button-secondary-active-bg: var(--a-gray-700);
--__ac-button-primary-text: var(--a-gray-900);
--__ac-button-primary-bg: var(--a-blue-200);
--__ac-button-primary-focus-border: var(--a-gray-900);
--__ac-button-primary-hover-bg: var(--a-blue-300);
--__ac-button-primary-active-bg: var(--a-blue-400);
--__ac-button-secondary-text: var(--a-white);
--__ac-button-secondary-hover-text: var(--a-white);
--__ac-button-secondary-active-text: var(--a-white);
--__ac-button-secondary-active-focus-border: var(--a-gray-900);
--__ac-button-secondary-bg: var(--a-gray-900);
--__ac-button-secondary-border: var(--a-blue-200);
--__ac-button-secondary-hover-bg: var(--a-gray-800);
--__ac-button-secondary-focus-border: var(--a-blue-200);
--__ac-button-secondary-active-bg: var(--a-gray-700);
}
[data-theme="light"] {
--__ac-button-primary-text: initial;
--__ac-button-primary-bg: initial;
--__ac-button-primary-focus-border: initial;
--__ac-button-primary-hover-bg: initial;
--__ac-button-primary-active-bg: initial;
--__ac-button-secondary-text: initial;
--__ac-button-secondary-hover-text: initial;
--__ac-button-secondary-active-text: initial;
--__ac-button-secondary-active-focus-border: initial;
--__ac-button-secondary-bg: initial;
--__ac-button-secondary-border: initial;
--__ac-button-secondary-hover-bg: initial;
--__ac-button-secondary-focus-border: initial;
--__ac-button-secondary-active-bg: initial;
}
.navds-button {
@@ -109,25 +126,29 @@
*************************/
.navds-button--primary {
background-color: var(--ac-button-primary-bg, var(--a-surface-action));
color: var(--ac-button-primary-text, var(--a-text-on-action));
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)));
}
.navds-button--primary:hover {
background-color: var(--ac-button-primary-hover-bg, var(--a-surface-action-hover));
background-color: var(--ac-button-primary-hover-bg, var(--__ac-button-primary-hover-bg, var(--a-surface-action-hover)));
}
.navds-button--primary:active {
background-color: var(--ac-button-primary-active-bg, var(--a-surface-action-active));
background-color: var(--ac-button-primary-active-bg, var(--__ac-button-primary-active-bg, var(--a-surface-action-active)));
}
.navds-button--primary:focus-visible {
box-shadow: inset 0 0 0 1px var(--ac-button-primary-focus-border, var(--a-surface-default)), var(--a-shadow-focus);
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);
}
@supports not selector(:focus-visible) {
.navds-button--primary:focus {
box-shadow: inset 0 0 0 1px var(--ac-button-primary-focus-border, var(--a-surface-default)), var(--a-shadow-focus);
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);
}
}
@@ -173,47 +194,58 @@
**************************/
.navds-button--secondary {
color: var(--ac-button-secondary-text, var(--a-text-action));
background-color: var(--ac-button-secondary-bg, var(--a-surface-transparent));
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-border, var(--a-border-action));
color: var(--ac-button-secondary-text, var(--__ac-button-secondary-text, var(--a-text-action)));
background-color: var(--ac-button-secondary-bg, var(--__ac-button-secondary-bg, var(--a-surface-transparent)));
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-border, var(--__ac-button-secondary-border, var(--a-border-action)));
}
.navds-button--secondary:hover {
color: var(--ac-button-secondary-hover-text, var(--a-text-action-on-action-subtle));
background-color: var(--ac-button-secondary-hover-bg, var(--a-surface-action-subtle-hover));
color: var(--ac-button-secondary-hover-text, var(--__ac-button-secondary-hover-text, var(--a-text-action-on-action-subtle)));
background-color: var(
--ac-button-secondary-hover-bg,
var(--__ac-button-secondary-hover-bg, var(--a-surface-action-subtle-hover))
);
}
.navds-button--secondary:focus-visible {
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-focus-border, var(--a-border-action)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 2px
var(--ac-button-secondary-focus-border, var(--__ac-button-secondary-focus-border, var(--a-border-action))),
var(--a-shadow-focus);
}
@supports not selector(:focus-visible) {
.navds-button--secondary:focus {
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-focus-border, var(--a-border-action)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 2px
var(--ac-button-secondary-focus-border, var(--__ac-button-secondary-focus-border, var(--a-border-action))),
var(--a-shadow-focus);
}
}
.navds-button--secondary:active {
color: var(--ac-button-secondary-active-text, var(--a-text-on-action));
background-color: var(--ac-button-secondary-active-bg, var(--a-surface-action-active));
color: var(--ac-button-secondary-active-text, var(--__ac-button-secondary-active-text, var(--a-text-on-action)));
background-color: var(--ac-button-secondary-active-bg, var(--__ac-button-secondary-active-bg, var(--a-surface-action-active)));
box-shadow: none;
}
.navds-button--secondary:focus-visible:active {
box-shadow: inset 0 0 0 1px var(--ac-button-secondary-active-focus-border, var(--a-surface-default)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 1px
var(--ac-button-secondary-active-focus-border, var(--__ac-button-secondary-active-focus-border, var(--a-surface-default))),
var(--a-shadow-focus);
}
@supports not selector(:focus-visible) {
.navds-button--secondary:focus:active {
box-shadow: inset 0 0 0 1px var(--ac-button-secondary-active-focus-border, var(--a-surface-default)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 1px
var(--ac-button-secondary-active-focus-border, var(--__ac-button-secondary-active-focus-border, var(--a-surface-default))),
var(--a-shadow-focus);
}
}
.navds-button--secondary:where(:disabled, .navds-button--disabled),
.navds-button--secondary:hover:where(:disabled, .navds-button--disabled) {
color: var(--ac-button-secondary-text, var(--a-text-action));
background-color: var(--ac-button-secondary-bg, var(--a-surface-transparent));
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-border, var(--a-border-action));
color: var(--ac-button-secondary-text, var(--__ac-button-secondary-text, var(--a-text-action)));
background-color: var(--ac-button-secondary-bg, var(--__ac-button-secondary-bg, var(--a-surface-transparent)));
box-shadow: inset 0 0 0 2px var(--ac-button-secondary-border, var(--__ac-button-secondary-border, var(--a-border-action)));
}
/**************************
+1
View File
@@ -3,6 +3,7 @@ export declare const globalDir = "dist/global";
export declare const componentDir = "dist/component";
export declare const typoCss = "typography.css";
export declare const formCss = "form.css";
export declare const primitivesCss = "primitives.css";
export declare const componentsCss = "components.css";
export declare const StyleMappings: {
baseline: {
+14 -4
View File
@@ -4,6 +4,7 @@ const componentDir = "dist/component";
const typoCss = "typography.css";
const formCss = "form.css";
const primitivesCss = "primitives.css";
const componentsCss = "components.css";
const StyleMappings = {
@@ -101,7 +102,7 @@ const StyleMappings = {
},
{
component: "HGrid",
main: "hgrid.css",
main: primitivesCss,
},
{ component: "Ingress", main: typoCss },
{
@@ -140,15 +141,23 @@ const StyleMappings = {
{ component: "Stepper", main: "stepper.css", dependencies: [typoCss] },
{
component: "HStack",
main: "stack.css",
main: primitivesCss,
},
{
component: "VStack",
main: "stack.css",
main: primitivesCss,
},
{
component: "Spacer",
main: "stack.css",
main: primitivesCss,
},
{
component: "Show",
main: primitivesCss,
},
{
component: "Hide",
main: primitivesCss,
},
{ component: "Switch", main: formCss, dependencies: [typoCss] },
{ component: "Table", main: "table.css", dependencies: [typoCss] },
@@ -184,6 +193,7 @@ module.exports = {
StyleMappings,
typoCss,
formCss,
primitivesCss,
componentsCss,
rootDir,
globalDir,
+6
View File
@@ -16,6 +16,7 @@ const {
rootDir,
globalDir,
componentDir,
primitivesCss,
} = require("./_mappings.js");
run();
@@ -123,6 +124,11 @@ function buildFragmentFiles() {
output: `${componentDir}/${formCss}`,
});
files.push({
input: "primitives/index.css",
output: `${componentDir}/${primitivesCss}`,
});
return files;
}
+24 -17
View File
@@ -1,10 +1,17 @@
[data-theme="dark"] .navds-copybutton,
[data-theme="dark"].navds-copybutton {
--a-text-action: var(--a-blue-300);
--a-surface-hover: rgb(214 231 255 /0.13);
--a-icon-success: rgb(51 170 95 /1);
--a-text-subtle: rgb(231 240 254 /0.69);
--a-text-default: rgb(251 252 254 /0.96);
[data-theme="dark"] {
--__ac-copybutton-action-text: var(--a-blue-300);
--__ac-copybutton-bg-hover: rgb(214 231 255 /0.13);
--__ac-copybutton-icon-success: rgb(51 170 95 /1);
--__ac-copybutton-neutral-text: rgb(231 240 254 /0.69);
--__ac-copybutton-text: rgb(251 252 254 /0.96);
}
[data-theme="light"] {
--__ac-copybutton-action-text: initial;
--__ac-copybutton-bg-hover: initial;
--__ac-copybutton-icon-success: initial;
--__ac-copybutton-neutral-text: initial;
--__ac-copybutton-text: initial;
}
.navds-copybutton {
@@ -84,46 +91,46 @@
/* Variant/action */
.navds-copybutton--action {
color: var(--ac-copybutton-action-text, var(--a-text-action));
color: var(--ac-copybutton-action-text, var(--__ac-copybutton-action-text, var(--a-text-action)));
background-color: var(--ac-copybutton-action-bg, var(--a-surface-transparent));
}
.navds-copybutton--action:hover {
color: var(--ac-copybutton-action-hover-text, var(--a-text-action));
background-color: var(--ac-copybutton-action-hover-bg, var(--a-surface-hover));
color: var(--ac-copybutton-action-hover-text, var(--__ac-copybutton-action-text, var(--a-text-action)));
background-color: var(--ac-copybutton-action-hover-bg, var(--__ac-copybutton-bg-hover, var(--a-surface-hover)));
}
.navds-copybutton--action:where(:disabled),
.navds-copybutton--action:hover:where(:disabled) {
color: var(--ac-copybutton-action-text, var(--a-text-action));
color: var(--ac-copybutton-action-text, var(--__ac-copybutton-action-text, var(--a-text-action)));
background-color: var(--ac-copybutton-action-bg, var(--a-surface-transparent));
box-shadow: none;
}
.navds-copybutton--active.navds-copybutton--action {
color: var(--ac-copybutton-action-active-text, var(--a-icon-success));
color: var(--ac-copybutton-action-active-text, var(--__ac-copybutton-icon-success, var(--a-icon-success)));
}
/* Variant/neutral */
.navds-copybutton--neutral {
color: var(--ac-copybutton-neutral-text, var(--a-text-subtle));
color: var(--ac-copybutton-neutral-text, var(--__ac-copybutton-neutral-text, var(--a-text-subtle)));
background-color: var(--ac-copybutton-neutral-bg, var(--a-surface-transparent));
}
.navds-copybutton--neutral:hover {
color: var(--ac-copybutton-neutral-hover-text, var(--a-text-default));
background-color: var(--ac-copybutton-neutral-hover-bg, var(--a-surface-hover));
color: var(--ac-copybutton-neutral-hover-text, var(--__ac-copybutton-text, var(--a-text-default)));
background-color: var(--ac-copybutton-neutral-hover-bg, var(--__ac-copybutton-bg-hover, var(--a-surface-hover)));
}
.navds-copybutton--neutral:where(:disabled, .navds-copybutton--disabled),
.navds-copybutton--neutral:hover:where(:disabled, .navds-copybutton--disabled) {
color: var(--ac-copybutton-neutral-text, var(--a-text-default));
color: var(--ac-copybutton-neutral-text, var(--__ac-copybutton-text, var(--a-text-default)));
background-color: var(--ac-copybutton-neutral-bg, var(--a-surface-transparent));
box-shadow: none;
}
.navds-copybutton--active.navds-copybutton--neutral {
color: var(--ac-copybutton-neutral-active-text, var(--a-text-default));
color: var(--ac-copybutton-neutral-active-text, var(--__ac-copybutton-text, var(--a-text-default)));
}
.navds-copybutton__content {
+1
View File
@@ -2,6 +2,7 @@
background-color: var(--ac-error-summary-bg, var(--a-surface-default));
padding: var(--a-spacing-5);
border: 4px solid var(--ac-error-summary-border, var(--a-border-danger));
border-radius: var(--a-border-radius-large);
}
.navds-error-summary--small {
+6 -2
View File
@@ -1,5 +1,9 @@
[data-theme="dark"] {
--ac-form-description: var(--a-text-on-inverted);
--__ac-form-description: var(--a-text-on-inverted);
}
[data-theme="light"] {
--__ac-form-description: initial;
}
.navds-fieldset {
@@ -14,7 +18,7 @@
}
.navds-fieldset__description {
color: var(--ac-form-description, var(--a-text-subtle));
color: var(--ac-form-description, var(--__ac-form-description, var(--a-text-subtle)));
}
.navds-fieldset > .navds-fieldset__description:not(:empty) {
+6 -2
View File
@@ -1,5 +1,9 @@
[data-theme="dark"] {
--ac-form-description: var(--a-text-on-inverted);
--__ac-form-description: var(--a-text-on-inverted);
}
[data-theme="light"] {
--__ac-form-description: initial;
}
.navds-form-field {
@@ -10,7 +14,7 @@
.navds-form-field__description {
margin-top: -0.375rem;
color: var(--ac-form-description, var(--a-text-subtle));
color: var(--ac-form-description, var(--__ac-form-description, var(--a-text-subtle)));
}
.navds-form-field .navds-error-message,
+38 -22
View File
@@ -1,9 +1,17 @@
[data-theme="dark"] {
--ac-search-button-border: var(--a-border-on-inverted);
--ac-search-button-border-hover: var(--a-blue-200);
--ac-search-clear-icon: var(--a-white);
--ac-search-clear-icon-hover: var(--a-blue-200);
--ac-search-error-border: var(--a-red-300);
--__ac-search-button-border: var(--a-border-on-inverted);
--__ac-search-button-border-hover: var(--a-blue-200);
--__ac-search-clear-icon: var(--a-white);
--__ac-search-clear-icon-hover: var(--a-blue-200);
--__ac-search-error-border: var(--a-red-300);
}
[data-theme="light"] {
--__ac-search-button-border: initial;
--__ac-search-button-border-hover: initial;
--__ac-search-clear-icon: initial;
--__ac-search-clear-icon-hover: initial;
--__ac-search-error-border: initial;
}
.navds-search {
@@ -65,7 +73,7 @@
position: absolute;
right: 0.75rem;
border-radius: var(--a-border-radius-medium);
color: var(--ac-search-clear-icon, var(--a-text-default));
color: var(--ac-search-clear-icon, var(--__ac-search-clear-icon, var(--a-text-default)));
height: 32px;
width: 32px;
top: 50%;
@@ -87,7 +95,7 @@
}
.navds-search__button-clear:hover {
color: var(--ac-search-clear-icon-hover, var(--a-text-action));
color: var(--ac-search-clear-icon-hover, var(--__ac-search-clear-icon-hover, var(--a-text-action)));
}
.navds-search__button-clear:focus-visible {
@@ -120,16 +128,17 @@
}
.navds-search__button-search.navds-button--secondary {
box-shadow: -1px 0 0 0 var(--ac-search-button-border, var(--a-border-default)) inset,
0 1px 0 0 var(--ac-search-button-border, var(--a-border-default)) inset,
0 -1px 0 0 var(--ac-search-button-border, var(--a-border-default)) inset;
box-shadow: -1px 0 0 0 var(--ac-search-button-border, var(--__ac-search-button-border, var(--a-border-default))) inset,
0 1px 0 0 var(--ac-search-button-border, var(--__ac-search-button-border, var(--a-border-default))) inset,
0 -1px 0 0 var(--ac-search-button-border, var(--__ac-search-button-border, var(--a-border-default))) inset;
}
.navds-search__button-search.navds-button--secondary:hover {
box-shadow: -1px 0 0 0 var(--ac-search-button-border-hover, var(--a-border-action)) inset,
0 1px 0 0 var(--ac-search-button-border-hover, var(--a-border-action)) inset,
0 -1px 0 0 var(--ac-search-button-border-hover, var(--a-border-action)) inset,
-1px 0 0 0 var(--ac-search-button-border-hover, var(--a-border-action));
box-shadow: -1px 0 0 0 var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action)))
inset,
0 1px 0 0 var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action))) inset,
0 -1px 0 0 var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action))) inset,
-1px 0 0 0 var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action)));
z-index: 1;
}
@@ -138,11 +147,13 @@
}
.navds-search__button-search.navds-button--secondary:focus-visible {
box-shadow: 0 0 0 1px var(--ac-search-button-border, var(--a-border-default)) inset, var(--a-shadow-focus);
box-shadow: 0 0 0 1px var(--ac-search-button-border, var(--__ac-search-button-border, var(--a-border-default))) inset,
var(--a-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus-visible:hover {
box-shadow: 0 0 0 1px var(--ac-search-button-border-hover, var(--a-border-action)) inset, var(--a-shadow-focus);
box-shadow: 0 0 0 1px var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action))) inset,
var(--a-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus-visible:active {
@@ -151,11 +162,14 @@
@supports not selector(:focus-visible) {
.navds-search__button-search.navds-button--secondary:focus {
box-shadow: 0 0 0 1px var(--ac-search-button-border, var(--a-border-default)) inset, var(--a-shadow-focus);
box-shadow: 0 0 0 1px var(--ac-search-button-border, var(--__ac-search-button-border, var(--a-border-default))) inset,
var(--a-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus:hover {
box-shadow: 0 0 0 1px var(--ac-search-button-border-hover, var(--a-border-action)) inset, var(--a-shadow-focus);
box-shadow: 0 0 0 1px var(--ac-search-button-border-hover, var(--__ac-search-button-border-hover, var(--a-border-action)))
inset,
var(--a-shadow-focus);
}
.navds-search__button-search.navds-button--secondary:focus:active {
@@ -165,12 +179,13 @@
/* Error-handling */
.navds-search--error .navds-search__input:not(:hover):not(:disabled) {
border-color: var(--ac-search-error-border, var(--a-border-danger));
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--a-border-danger));
border-color: var(--ac-search-error-border, var(--__ac-search-error-border, var(--a-border-danger)));
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--__ac-search-error-border, var(--a-border-danger)));
}
.navds-search--error .navds-search__input:focus-visible:not(:hover):not(:disabled) {
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--a-border-danger)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--__ac-search-error-border, var(--a-border-danger))),
var(--a-shadow-focus);
}
/* Focus layering */
@@ -182,7 +197,8 @@
@supports not selector(:focus-visible) {
.navds-search--error .navds-search__input:focus:not(:hover):not(:disabled) {
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--a-border-danger)), var(--a-shadow-focus);
box-shadow: inset 0 0 0 1px var(--ac-search-error-border, var(--__ac-search-error-border, var(--a-border-danger))),
var(--a-shadow-focus);
}
.navds-search__input:focus,
+24 -15
View File
@@ -1,21 +1,30 @@
[data-theme="dark"] {
--ac-textfield-text: var(--a-text-on-inverted);
--ac-textfield-bg: var(--a-surface-inverted);
--ac-textfield-border: var(--a-border-on-inverted);
--ac-textfield-hover-border: var(--a-blue-200);
--ac-textfield-placeholder: var(--a-gray-500);
--ac-textfield-error-border: var(--a-red-300);
--__ac-textfield-text: var(--a-text-on-inverted);
--__ac-textfield-bg: var(--a-surface-inverted);
--__ac-textfield-border: var(--a-border-on-inverted);
--__ac-textfield-hover-border: var(--a-blue-200);
--__ac-textfield-placeholder: var(--a-gray-500);
--__ac-textfield-error-border: var(--a-red-300);
}
[data-theme="light"] {
--__ac-textfield-text: initial;
--__ac-textfield-bg: initial;
--__ac-textfield-border: initial;
--__ac-textfield-hover-border: initial;
--__ac-textfield-placeholder: initial;
--__ac-textfield-error-border: initial;
}
.navds-text-field__input {
appearance: none;
padding: var(--a-spacing-2);
background-color: var(--ac-textfield-bg, var(--a-surface-default));
background-color: var(--ac-textfield-bg, var(--__ac-textfield-bg, var(--a-surface-default)));
border-radius: var(--a-border-radius-medium);
border: 1px solid var(--ac-textfield-border, var(--a-border-default));
border: 1px solid var(--ac-textfield-border, var(--__ac-textfield-border, var(--a-border-default)));
min-height: 3rem;
width: 100%;
color: var(--ac-textfield-text, var(--a-text-default));
color: var(--ac-textfield-text, var(--__ac-textfield-text, var(--a-text-default)));
}
.navds-text-field__input[size] {
@@ -23,7 +32,7 @@
}
.navds-text-field__input::placeholder {
color: var(--ac-textfield-placeholder, var(--a-text-subtle));
color: var(--ac-textfield-placeholder, var(--__ac-textfield-placeholder, var(--a-text-subtle)));
}
.navds-form-field--small .navds-text-field__input {
@@ -32,7 +41,7 @@
}
.navds-text-field__input:hover {
border-color: var(--ac-textfield-hover-border, var(--a-border-action));
border-color: var(--ac-textfield-hover-border, var(--__ac-textfield-hover-border, var(--a-border-action)));
}
.navds-text-field__input:focus-visible {
@@ -51,8 +60,8 @@
Error handling
*/
.navds-text-field--error > .navds-text-field__input:not(:hover):not(:disabled) {
border-color: var(--ac-textfield-error-border, var(--a-border-danger));
box-shadow: 0 0 0 1px var(--ac-textfield-error-border, var(--a-border-danger));
border-color: var(--ac-textfield-error-border, var(--__ac-textfield-error-border, var(--a-border-danger)));
box-shadow: 0 0 0 1px var(--ac-textfield-error-border, var(--__ac-textfield-error-border, var(--a-border-danger)));
}
.navds-text-field--error > .navds-text-field__input:focus-visible:not(:hover):not(:disabled) {
@@ -67,8 +76,8 @@
/* Disabled handling */
.navds-text-field__input:disabled {
background-color: var(--ac-textfield-bg, var(--a-surface-default));
border-color: var(--ac-textfield-border, var(--a-border-default));
background-color: var(--ac-textfield-bg, var(--__ac-textfield-bg, var(--a-surface-default)));
border-color: var(--ac-textfield-border, var(--__ac-textfield-border, var(--a-border-default)));
box-shadow: none;
cursor: not-allowed;
}
+32 -21
View File
@@ -1,12 +1,23 @@
[data-theme="dark"] {
--ac-textarea-text: var(--a-text-on-inverted);
--ac-textarea-bg: var(--a-transparent);
--ac-textarea-border: var(--a-border-on-inverted);
--ac-textarea-hover-border: var(--a-blue-200);
--ac-textarea-placeholder: var(--a-gray-500);
--ac-textarea-error-border: var(--a-red-300);
--ac-textarea-counter-text: var(--a-gray-300);
--ac-textarea-counter-error-text: var(--a-red-300);
--__ac-textarea-text: var(--a-text-on-inverted);
--__ac-textarea-bg: var(--a-transparent);
--__ac-textarea-border: var(--a-border-on-inverted);
--__ac-textarea-hover-border: var(--a-blue-200);
--__ac-textarea-placeholder: var(--a-gray-500);
--__ac-textarea-error-border: var(--a-red-300);
--__ac-textarea-counter-text: var(--a-gray-300);
--__ac-textarea-counter-error-text: var(--a-red-300);
}
[data-theme="light"] {
--__ac-textarea-text: initial;
--__ac-textarea-bg: initial;
--__ac-textarea-border: initial;
--__ac-textarea-hover-border: initial;
--__ac-textarea-placeholder: initial;
--__ac-textarea-error-border: initial;
--__ac-textarea-counter-text: initial;
--__ac-textarea-counter-error-text: initial;
}
.navds-textarea__wrapper {
@@ -17,13 +28,13 @@
.navds-textarea__input {
appearance: none;
padding: var(--a-spacing-2);
background-color: var(--ac-textarea-bg, var(--a-surface-default));
background-color: var(--ac-textarea-bg, var(--__ac-textarea-bg, var(--a-surface-default)));
border-radius: var(--a-border-radius-medium);
border: 1px solid var(--ac-textarea-border, var(--a-border-default));
border: 1px solid var(--ac-textarea-border, var(--__ac-textarea-border, var(--a-border-default)));
resize: none;
width: 100%;
display: block;
color: var(--ac-textarea-text, var(--a-text-default));
color: var(--ac-textarea-text, var(--__ac-textarea-text, var(--a-text-default)));
}
.navds-textarea--counter {
@@ -31,11 +42,11 @@
}
.navds-textarea__input::placeholder {
color: var(--ac-textarea-placeholder, var(--a-text-subtle));
color: var(--ac-textarea-placeholder, var(--__ac-textarea-placeholder, var(--a-text-subtle)));
}
.navds-textarea__input:hover {
border-color: var(--ac-textarea-hover-border, var(--a-border-action));
border-color: var(--ac-textarea-hover-border, var(--__ac-textarea-hover-border, var(--a-border-action)));
}
.navds-textarea__input:focus-visible {
@@ -60,7 +71,7 @@
.navds-textarea__counter {
pointer-events: none;
color: var(--ac-textarea-counter-text, var(--a-text-subtle));
color: var(--ac-textarea-counter-text, var(--__ac-textarea-counter-text, var(--a-text-subtle)));
font-style: italic;
position: absolute;
text-align: left;
@@ -70,7 +81,7 @@
}
.navds-textarea__counter--error {
color: var(--ac-textarea-counter-error-text, var(--a-text-danger));
color: var(--ac-textarea-counter-error-text, var(--__ac-textarea-counter-error-text, var(--a-text-danger)));
}
.navds-textarea--resize .navds-textarea__input {
@@ -81,20 +92,20 @@
Error handling
*/
.navds-textarea--error .navds-textarea__input:not(:hover):not(:focus-visible):not(:disabled) {
box-shadow: 0 0 0 1px var(--ac-textarea-error-border, var(--a-border-danger));
border-color: var(--ac-textarea-error-border, var(--a-border-danger));
box-shadow: 0 0 0 1px var(--ac-textarea-error-border, var(--__ac-textarea-error-border, var(--a-border-danger)));
border-color: var(--ac-textarea-error-border, var(--__ac-textarea-error-border, var(--a-border-danger)));
}
@supports not selector(:focus-visible) {
.navds-textarea--error .navds-textarea__input:not(:hover):not(:focus):not(:disabled) {
box-shadow: 0 0 0 1px var(--ac-textarea-error-border, var(--a-border-danger));
border-color: var(--ac-textarea-error-border, var(--a-border-danger));
box-shadow: 0 0 0 1px var(--ac-textarea-error-border, var(--__ac-textarea-error-border, var(--a-border-danger)));
border-color: var(--ac-textarea-error-border, var(--__ac-textarea-error-border, var(--a-border-danger)));
}
}
.navds-textarea__input:disabled {
background-color: var(--ac-textarea-bg, var(--a-surface-default));
border-color: var(--ac-textarea-border, var(--a-border-default));
background-color: var(--ac-textarea-bg, var(--__ac-textarea-bg, var(--a-surface-default)));
border-color: var(--ac-textarea-border, var(--__ac-textarea-border, var(--a-border-default)));
box-shadow: none;
cursor: not-allowed;
}
+1 -2
View File
@@ -1,6 +1,7 @@
@charset "UTF-8";
@import "baseline/index.css";
@import "typography.css";
@import "primitives/index.css";
@import "grid.css";
@import "accordion.css";
@import "alert.css";
@@ -14,7 +15,6 @@
@import "guide-panel.css";
@import "form/index.css";
@import "help-text.css";
@import "hgrid.css";
@import "internalheader.css";
@import "link.css";
@import "loader.css";
@@ -30,7 +30,6 @@
@import "link-panel.css";
@import "read-more.css";
@import "skeleton.css";
@import "stack.css";
@import "stepper.css";
@import "table.css";
@import "tabs.css";
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "5.3.1",
"version": "5.4.0",
"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.3.1",
"@navikt/ds-tokens": "^5.4.0",
"cssnano": "6.0.0",
"fast-glob": "3.2.11",
"lodash": "4.17.21",
@@ -11,10 +11,12 @@
--__ac-hgrid-gap-lg: initial;
--__ac-hgrid-gap-xl: initial;
--__ac-hgrid-gap: var(--__ac-hgrid-gap-xs);
--__ac-hgrid-align: initial;
display: grid;
grid-template-columns: var(--__ac-hgrid-columns);
gap: var(--__ac-hgrid-gap);
align-items: var(--__ac-hgrid-align);
}
@media (min-width: 480px) {
+3
View File
@@ -0,0 +1,3 @@
@import "hgrid.css";
@import "stack.css";
@import "responsive.css";
@@ -0,0 +1,51 @@
.navds-responsive {
display: none;
}
@media (min-width: 480px) {
.navds-responsive__above--sm {
display: revert;
}
}
@media (max-width: 479px) {
.navds-responsive__below--sm {
display: revert;
}
}
@media (min-width: 768px) {
.navds-responsive__above--md {
display: revert;
}
}
@media (max-width: 767px) {
.navds-responsive__below--md {
display: revert;
}
}
@media (min-width: 1024px) {
.navds-responsive__above--lg {
display: revert;
}
}
@media (max-width: 1023px) {
.navds-responsive__below--lg {
display: revert;
}
}
@media (min-width: 1280px) {
.navds-responsive__above--xl {
display: revert;
}
}
@media (max-width: 1279px) {
.navds-responsive__below--xl {
display: revert;
}
}
File renamed without changes.
-1
View File
@@ -1,5 +1,4 @@
.navds-skeleton {
display: block;
background-color: var(--ac-skeleton-bg, var(--a-surface-neutral-moderate));
height: 1.3em;
animation: akselSkeletonAnimation 0.8s linear infinite alternate;
+12 -12
View File
@@ -1,3 +1,13 @@
[data-theme="dark"] {
--__ac-typo-error-text: var(--a-red-300);
--__ac-typo-text-subtle: var(--a-gray-300);
}
[data-theme="light"] {
--__ac-typo-error-text: initial;
--__ac-typo-text-subtle: initial;
}
/* Heading */
.navds-heading {
font-weight: var(--a-font-weight-bold);
@@ -202,13 +212,8 @@
margin-bottom: var(--a-spacing-2);
}
[data-theme="dark"].navds-error-message,
[data-theme="dark"] .navds-error-message {
--a-text-danger: var(--a-red-300);
}
.navds-error-message {
color: var(--ac-typo-error-text, var(--a-text-danger));
color: var(--ac-typo-error-text, var(--__ac-typo-error-text, var(--a-text-danger)));
}
.navds-typo--truncate {
@@ -247,10 +252,5 @@
}
.navds-typo--color-subtle {
color: var(--a-text-subtle);
}
[data-theme="dark"].navds-typo--color-subtle,
[data-theme="dark"] .navds-typo--color-subtle {
--a-text-subtle: var(--a-gray-300);
color: var(--__ac-typo-text-subtle, var(--a-text-subtle));
}
+47
View File
@@ -1,5 +1,52 @@
# @navikt/ds-react
## 5.4.0
### Minor Changes
- Primitives: Nye komponenter `Show` og `Hide` er lagt til. ([#2222](https://github.com/navikt/aksel/pull/2222))
### Patch Changes
- Search: Kjører nå bare preventDefault ved Escape når `input` inneholder tekst ([#2245](https://github.com/navikt/aksel/pull/2245))
- Updated dependencies []:
- @navikt/aksel-icons@5.4.0
## 5.3.5
### Patch Changes
- :bug: Popover: sjekk at det er et HTML-element som får fokus ([#2258](https://github.com/navikt/aksel/pull/2258))
- Updated dependencies []:
- @navikt/aksel-icons@5.3.5
## 5.3.4
### Patch Changes
- Updated dependencies [[`27dacfdbe`](https://github.com/navikt/aksel/commit/27dacfdbe96a861b19c20d4494485c863d0ee8d9)]:
- @navikt/aksel-icons@5.3.4
## 5.3.3
### Patch Changes
- HGrid: Har nå `align`-prop for bedre kontroll over child-elementer ([#2242](https://github.com/navikt/aksel/pull/2242))
- Updated dependencies []:
- @navikt/aksel-icons@5.3.3
## 5.3.2
### Patch Changes
- Skeleton: Lagt til as-prop for inline brk av Skeleton med span ([#2239](https://github.com/navikt/aksel/pull/2239))
- Updated dependencies []:
- @navikt/aksel-icons@5.3.2
## 5.3.1
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "5.3.1",
"version": "5.4.0",
"description": "Aksel react-components for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -32,13 +32,13 @@
"docgen": "yarn ts-node ../../../scripts/docgen.ts",
"create-package-json-pointers-to-esm": "node ../../../scripts/createPackageJsonsWithESMPointers.js",
"clean": "rimraf cjs esm",
"build": "concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"build": "concurrently \"tsc -p tsconfig.build.json\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"watch": "tsc --watch -p tsconfig.esm.json",
"test": "TZ=UTC jest"
},
"dependencies": {
"@floating-ui/react": "0.24.1",
"@navikt/aksel-icons": "^5.3.1",
"@navikt/aksel-icons": "^5.4.0",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
+34 -28
View File
@@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import { Alert } from ".";
import { Alert, AlertProps } from ".";
import { BodyLong, Heading as DsHeading, Link } from "..";
import { within, userEvent } from "@storybook/testing-library";
import { expect } from "@storybook/jest";
@@ -14,7 +14,7 @@ export default meta;
type Story = StoryObj<typeof Alert>;
const variants: Array<"error" | "warning" | "info" | "success"> = [
const variants: AlertProps["variant"][] = [
"error",
"warning",
"info",
@@ -33,24 +33,17 @@ export const Default: Story = {
},
argTypes: {
variant: {
control: {
type: "radio",
},
control: { type: "radio" },
options: ["info", "error", "warning", "success"],
},
size: {
control: {
type: "radio",
},
control: { type: "radio" },
options: ["medium", "small"],
},
closeButton: {
type: "boolean",
},
},
};
export const Small = {
export const Small: Story = {
render: (props) => {
return (
<div className="colgap">
@@ -69,14 +62,10 @@ export const Small = {
</div>
);
},
args: {
closeButton: false,
},
argtypes: {
closeButton: {
type: "boolean",
},
},
};
export const FullWidth = () => {
@@ -160,16 +149,25 @@ export const Links = () => {
);
};
const AlertWithCloseButton = ({ children }: { children?: React.ReactNode }) => {
const AlertWithCloseButton = ({
children,
size,
}: {
size?: "medium" | "small";
children?: React.ReactNode;
}) => {
let [show, setShow] = React.useState(true);
return (
show && (
<Alert variant="success" closeButton onClose={() => setShow(false)}>
{children || "Content"}
</Alert>
)
);
return show ? (
<Alert
variant="warning"
size={size}
closeButton
onClose={() => setShow(false)}
>
{children || "Content"}
</Alert>
) : null;
};
export const WithCloseButton: Story = {
@@ -178,14 +176,22 @@ export const WithCloseButton: Story = {
<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
</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.
</BodyLong>
<Link href="#">Id elit esse enim reprehenderit</Link>
</AlertWithCloseButton>
<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
</DsHeading>
@@ -207,6 +213,6 @@ export const WithCloseButton: Story = {
});
const buttonsAfter = canvas.getAllByTitle("Lukk Alert");
expect(buttonsAfter.length).toBe(2);
expect(buttonsAfter.length).toBe(4);
},
};
@@ -1,7 +1,7 @@
import cl from "clsx";
import format from "date-fns/format";
import isSameMonth from "date-fns/isSameMonth";
import isSameYear from "date-fns/isSameYear";
import isSameYear from "date-fns/isSameYear";
import setYear from "date-fns/setYear";
import React, { useEffect, useRef } from "react";
import { useDayPicker } from "react-day-picker";
@@ -19,12 +19,14 @@ interface MonthType {
const disableMonth = (month: Date, fromDate?: Date, toDate?: Date) => {
if (fromDate && toDate) {
return (isSameMonth(month, fromDate) && isSameYear(month, fromDate))
|| (isSameMonth(month, toDate) && isSameYear(month, toDate))
return (
(isSameMonth(month, fromDate) && isSameYear(month, fromDate)) ||
(isSameMonth(month, toDate) && isSameYear(month, toDate))
);
} else if (fromDate) {
return isSameMonth(month, fromDate) && isSameYear(month, fromDate)
return isSameMonth(month, fromDate) && isSameYear(month, fromDate);
} else if (toDate) {
return isSameMonth(month, toDate) && isSameYear(month, toDate)
return isSameMonth(month, toDate) && isSameYear(month, toDate);
}
return false;
};
@@ -28,5 +28,5 @@ export const List = forwardRef(({ className, children, ...rest }, ref) => (
)) as ListType;
List.Item = ListItem;
List.displayName = "Dropdown.Menu.List";
export default List;
@@ -1,26 +1,18 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Meta } from "@storybook/react";
import { Meta, StoryFn, StoryObj } from "@storybook/react";
import React, { useState, useId, useMemo } from "react";
import { userEvent, within } from "@storybook/testing-library";
import { Chips, UNSAFE_Combobox, TextField } from "../../index";
import { Chips, UNSAFE_Combobox, ComboboxProps, TextField } from "../../index";
import { expect, jest } from "@storybook/jest";
export default {
title: "ds-react/Combobox",
component: UNSAFE_Combobox,
argTypes: {
isListOpen: {
control: {
type: "boolean",
},
},
isLoading: {
control: {
type: "boolean",
},
},
},
} as Meta;
decorators: [(story) => <div style={{ width: "300px" }}>{story()}</div>],
} satisfies Meta<typeof UNSAFE_Combobox>;
type StoryObject = StoryObj<typeof UNSAFE_Combobox>;
type StoryFunction = StoryFn<typeof UNSAFE_Combobox>;
const options = [
"banana",
@@ -38,55 +30,39 @@ const options = [
"grape fruit",
];
const initialSelectedOptions = ["passion fruit", "grape fruit"];
const DemoContainer = ({
dataTheme,
children,
}: {
children: any;
dataTheme: "dark" | "light";
}) => (
<div data-theme={dataTheme} style={{ width: "300px" }}>
{children}
</div>
);
export const Default = (props) => {
export const Default: StoryFunction = (props) => {
const id = useId();
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={props.options}
label="Hva er dine favorittfrukter?"
/* everything under here is optional? */
shouldAutocomplete={props.shouldAutoComplete}
size="medium"
id={id}
/>
</DemoContainer>
);
return <UNSAFE_Combobox {...props} id={id} />;
};
Default.args = {
options,
shouldAutoComplete: true,
label: "Hva er dine favorittfrukter?",
shouldAutocomplete: true,
isLoading: false,
};
Default.argTypes = {
isListOpen: {
control: { type: "boolean" },
},
size: {
options: ["medium", "small"],
defaultValue: "medium",
control: { type: "radio" },
},
};
export function MultiSelect(props) {
export const MultiSelect: StoryFunction = (props) => {
const id = useId();
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
id={id}
label="Komboboks - velg flere"
options={props.options}
isMultiSelect={props.isMultiSelect}
size={props.size}
/>
</DemoContainer>
<UNSAFE_Combobox
id={id}
label="Komboboks - velg flere"
options={props.options}
isMultiSelect={props.isMultiSelect}
size={props.size}
/>
);
}
};
MultiSelect.args = {
options,
@@ -94,41 +70,37 @@ MultiSelect.args = {
size: "medium",
};
export function WithAddNewOptions(props) {
export const WithAddNewOptions: StoryFunction = (props) => {
const id = useId();
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
id={id}
label="Komboboks med mulighet for å legge til nye verdier"
options={props.options}
allowNewValues={props.allowNewValues}
shouldAutocomplete={props.shouldAutoComplete}
/>
</DemoContainer>
<UNSAFE_Combobox
id={id}
label="Komboboks med mulighet for å legge til nye verdier"
options={props.options}
allowNewValues={props.allowNewValues}
shouldAutocomplete={props.shouldAutocomplete}
/>
);
}
};
WithAddNewOptions.args = {
options,
allowNewValues: true,
shouldAutoComplete: true,
shouldAutocomplete: true,
};
export function MultiSelectWithAddNewOptions(props) {
export const MultiSelectWithAddNewOptions: StoryFunction = (props) => {
const id = useId();
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
id={id}
isMultiSelect={props.isMultiSelect}
label="Multiselect komboboks med mulighet for å legge til nye verdier"
options={props.options}
allowNewValues={props.allowNewValues}
/>
</DemoContainer>
<UNSAFE_Combobox
id={id}
isMultiSelect={props.isMultiSelect}
label="Multiselect komboboks med mulighet for å legge til nye verdier"
options={props.options}
allowNewValues={props.allowNewValues}
/>
);
}
};
MultiSelectWithAddNewOptions.args = {
allowNewValues: true,
@@ -137,19 +109,20 @@ MultiSelectWithAddNewOptions.args = {
shouldAutocomplete: false,
};
export const MultiSelectWithExternalChips = (props) => {
const [selectedOptions, setSelectedOptions] = useState<string[]>(
props.selectedOptions
);
export const MultiSelectWithExternalChips: StoryFn<{
controlled: boolean;
options: ComboboxProps["options"];
}> = (props) => {
const [selectedOptions, setSelectedOptions] = useState<string[]>([]);
const [value, setValue] = useState("");
const id = useId();
const toggleSelected = (option) =>
const toggleSelected = (option: string) =>
selectedOptions.includes(option)
? setSelectedOptions(selectedOptions.filter((opt) => opt !== option))
: setSelectedOptions([...selectedOptions, option]);
return (
<DemoContainer dataTheme={props.darkMode}>
<>
{selectedOptions && (
<Chips>
{selectedOptions.map((option) => (
@@ -164,84 +137,85 @@ export const MultiSelectWithExternalChips = (props) => {
</Chips>
)}
<UNSAFE_Combobox
options={options}
options={props.options}
selectedOptions={selectedOptions}
onToggleSelected={(option: string) => toggleSelected(option)}
isListOpen={props.isListOpen}
onToggleSelected={(option) => toggleSelected(option)}
isMultiSelect
value={props.controlled ? value : undefined}
onChange={(event) =>
props.controlled ? setValue(event.currentTarget.value) : undefined
props.controlled
? setValue(event?.currentTarget.value || "")
: undefined
}
label="Komboboks"
size="medium"
error={props.error && "error here"}
id={id}
shouldShowSelectedOptions={false}
/>
</DemoContainer>
</>
);
};
MultiSelectWithExternalChips.args = {
controlled: false,
options,
selectedOptions: [],
};
export function Loading(props) {
export const Loading: StoryFunction = (props) => {
const id = useId();
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
id={id}
label="Komboboks (laster)"
options={[]}
selectedOptions={[]}
isListOpen={props.isListOpen}
isLoading={props.isLoading}
/>
</DemoContainer>
<UNSAFE_Combobox
id={id}
label="Komboboks (laster)"
options={[]}
selectedOptions={[]}
isListOpen={props.isListOpen}
isLoading={props.isLoading}
/>
);
}
};
Loading.args = {
isLoading: true,
isListOpen: true,
};
export function ComboboxWithNoHits(props) {
export const ComboboxWithNoHits: StoryFunction = (props) => {
const id = useId();
const [value, setValue] = useState(props.value);
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
id={id}
label="Komboboks (uten søketreff)"
options={props.options}
value={value}
onChange={(event) => setValue(event.currentTarget.value)}
isListOpen={true}
/>
</DemoContainer>
<UNSAFE_Combobox
id={id}
label="Komboboks (uten søketreff)"
options={props.options}
value={value}
onChange={(event) => setValue(event?.currentTarget.value)}
isListOpen={true}
/>
);
}
};
ComboboxWithNoHits.args = {
options,
value: "Orange",
};
export const Controlled = (props) => {
export const Controlled: StoryFn<{
value: string;
options: string[];
initialSelectedOptions: string[];
}> = (props) => {
const id = useId();
const [value, setValue] = useState(props.value);
const [selectedOptions, setSelectedOptions] = useState(props.selectedOptions);
const [selectedOptions, setSelectedOptions] = useState(
props.initialSelectedOptions
);
const filteredOptions = useMemo(
() => props.options.filter((option) => option.includes(value)),
[props.options, value]
);
const onToggleSelected = (option, isSelected) => {
const onToggleSelected = (option: string, isSelected: boolean) => {
if (isSelected) {
setSelectedOptions([...selectedOptions, option]);
} else {
@@ -250,7 +224,7 @@ export const Controlled = (props) => {
};
return (
<DemoContainer dataTheme={props.darkMode}>
<>
<TextField
label="Overstyr value"
onChange={(event) => setValue(event.target.value)}
@@ -263,23 +237,23 @@ export const Controlled = (props) => {
filteredOptions={filteredOptions}
isMultiSelect
options={props.options}
onChange={(event) => setValue(event.target.value)}
onChange={(event) => setValue(event?.target.value || "")}
onToggleSelected={onToggleSelected}
selectedOptions={selectedOptions}
value={value}
/>
</DemoContainer>
</>
);
};
Controlled.args = {
value: "apple",
options,
selectedOptions: initialSelectedOptions,
initialSelectedOptions: ["passion fruit", "grape fruit"],
};
export const ComboboxSizes = (props) => (
<DemoContainer dataTheme={props.darkMode}>
export const ComboboxSizes = () => (
<>
<UNSAFE_Combobox
label="Hva er dine favorittfrukter?"
description="Medium single-select"
@@ -309,36 +283,29 @@ export const ComboboxSizes = (props) => (
size="small"
allowNewValues
/>
</DemoContainer>
</>
);
ComboboxSizes.args = {
options,
};
export const WithError = {
export const WithError: StoryObject = {
args: {
error: "Du må velge en favorittfrukt.",
isLoading: true,
},
render: (props) => {
const [hasSelectedValue, setHasSelectedValue] = useState(false);
const [isLoading, setIsLoading] = useState(false);
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
filteredOptions={isLoading ? [] : undefined}
options={options}
label="Hva er dine favorittfrukter?"
error={!hasSelectedValue && props.error}
isLoading={isLoading}
onChange={() => {
setIsLoading(true);
setTimeout(() => setIsLoading(false), 2000);
}}
onToggleSelected={(_, isSelected) => setHasSelectedValue(isSelected)}
/>
</DemoContainer>
<UNSAFE_Combobox
filteredOptions={isLoading ? [] : undefined}
options={options}
label="Hva er dine favorittfrukter?"
error={!hasSelectedValue && props.error}
isLoading={isLoading}
onChange={() => {
setIsLoading(true);
setTimeout(() => setIsLoading(false), 2000);
}}
onToggleSelected={(_, isSelected) => setHasSelectedValue(isSelected)}
/>
);
},
};
@@ -347,15 +314,10 @@ function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export const CancelInputTest = {
render: (props) => {
export const CancelInputTest: StoryObject = {
render: () => {
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
/>
</DemoContainer>
<UNSAFE_Combobox options={options} label="Hva er dine favorittfrukter?" />
);
},
play: async ({ canvasElement }) => {
@@ -378,16 +340,14 @@ export const CancelInputTest = {
},
};
export const RemoveSelectedMultiSelectTest = {
render: (props) => {
export const RemoveSelectedMultiSelectTest: StoryObject = {
render: () => {
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
/>
</DemoContainer>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
/>
);
},
play: async ({ canvasElement }) => {
@@ -436,16 +396,14 @@ export const RemoveSelectedMultiSelectTest = {
},
};
export const AddWhenAddNewDisabledTest = {
render: (props) => {
export const AddWhenAddNewDisabledTest: StoryObject = {
render: () => {
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
/>
</DemoContainer>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
/>
);
},
play: async ({ canvasElement }) => {
@@ -471,7 +429,11 @@ export const AddWhenAddNewDisabledTest = {
},
};
export const TestThatCallbacksOnlyFireWhenExpected = {
export const TestThatCallbacksOnlyFireWhenExpected: StoryObj<{
onChange: ReturnType<typeof jest.fn>;
onClear: ReturnType<typeof jest.fn>;
onToggleSelected: ReturnType<typeof jest.fn>;
}> = {
args: {
onChange: jest.fn(),
onClear: jest.fn(),
@@ -479,13 +441,11 @@ export const TestThatCallbacksOnlyFireWhenExpected = {
},
render: (props) => {
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
{...props}
/>
</DemoContainer>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
{...props}
/>
);
},
play: async ({ canvasElement, args }) => {
@@ -510,16 +470,10 @@ export const TestThatCallbacksOnlyFireWhenExpected = {
},
};
export const TestHoverAndFocusSwitching = {
render: (props) => {
export const TestHoverAndFocusSwitching: StoryObject = {
render: () => {
return (
<DemoContainer dataTheme={props.darkMode}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
{...props}
/>
</DemoContainer>
<UNSAFE_Combobox options={options} label="Hva er dine favorittfrukter?" />
);
},
play: async ({ canvasElement }) => {
+11 -24
View File
@@ -8,14 +8,7 @@ import React, {
useRef,
useState,
} from "react";
import {
BodyShort,
ErrorMessage,
Label,
mergeRefs,
omit,
useEventListener,
} from "../..";
import { BodyShort, ErrorMessage, Label, mergeRefs, omit } from "../..";
import { FormFieldProps, useFormField } from "../useFormField";
import SearchButton, { SearchButtonType } from "./SearchButton";
@@ -135,7 +128,6 @@ export const Search = forwardRef<HTMLInputElement, SearchProps>(
const searchRef = useRef<HTMLInputElement | null>(null);
const mergedRef = useMemo(() => mergeRefs([searchRef, ref]), [ref]);
const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
@@ -156,27 +148,22 @@ export const Search = forwardRef<HTMLInputElement, SearchProps>(
[handleChange, onClear]
);
useEventListener(
"keydown",
useCallback(
(e) => {
if (e.key === "Escape") {
e.preventDefault();
handleClear({ trigger: "Escape", event: e });
}
},
[handleClear]
),
wrapperRef
);
const handleClick = () => {
onSearchClick?.(`${value ?? internalValue}`);
};
return (
<div
ref={setWrapperRef}
onKeyDown={(e) => {
if (e.key !== "Escape") {
return;
}
searchRef.current?.value &&
searchRef.current?.value !== "" &&
e.preventDefault();
handleClear({ trigger: "Escape", event: e });
}}
className={cl(
className,
"navds-form-field",
@@ -16,10 +16,10 @@ enim id.`;
export const Default = {
render: (props: { poster: boolean; colorOverride: boolean }) => {
const style = props.colorOverride
? ({
? {
"--ac-guide-panel-illustration-bg": "var(--a-purple-200)",
"--ac-guide-panel-border": "var(--a-purple-400)",
} as React.CSSProperties)
}
: {};
return (
+1
View File
@@ -35,3 +35,4 @@ export * from "./util";
export * from "./layout/stack";
export * from "./layout/grid";
export * from "./layout/content-container";
export * from "./layout/responsive";
+7 -2
View File
@@ -26,11 +26,15 @@ export interface HGridProps extends HTMLAttributes<HTMLDivElement> {
* gap={{ sm: "2", md: "2", lg: "6", xl: "6"}}
*/
gap?: ResponsiveProp<SpacingScale>;
/**
* Vertical alignment of children. Elements will by default stretch to the height of parent-element.
*/
align?: "start" | "center" | "end";
}
/**
* Horizontal Grid Primitive with dynamic columns and gap based on breakpoints.
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/hgrid)
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/hgrid)
* @see 🏷️ {@link HGridProps}
*
* @example
@@ -53,9 +57,10 @@ export interface HGridProps extends HTMLAttributes<HTMLDivElement> {
* </HGrid>
*/
export const HGrid = forwardRef<HTMLDivElement, HGridProps>(
({ className, columns, gap, style, ...rest }, ref) => {
({ className, columns, gap, style, align, ...rest }, ref) => {
const styles: React.CSSProperties = {
...style,
"--__ac-hgrid-align": align,
...getResponsiveProps(`hgrid`, "gap", "spacing", gap),
...getResponsiveValue(`hgrid`, "columns", formatGrid(columns)),
};
@@ -1,5 +1,6 @@
import React from "react";
import { HGrid } from ".";
import { VStack } from "../stack";
const columnsVariants = {
Number: "columnNumber",
@@ -86,12 +87,31 @@ export const DynamicColumns = {
),
};
function Placeholder({ text }) {
export const AlignItems = {
render: () => (
<VStack gap="8">
<HGrid gap="4" columns={2} align="start">
<Placeholder text="start" height="8rem" />
<Placeholder text="auto" height="auto" />
</HGrid>
<HGrid gap="4" columns={2} align="center">
<Placeholder text="center" height="8rem" />
<Placeholder text="auto" height="auto" />
</HGrid>
<HGrid gap="4" columns={2} align="end">
<Placeholder text="end" height="8rem" />
<Placeholder text="auto" height="auto" />
</HGrid>
</VStack>
),
};
function Placeholder({ text, height }: { text: string; height?: string }) {
return (
<div
style={{
background: "var(--a-deepblue-900)",
height: "5rem",
height: height ?? "5rem",
width: "auto",
color: "white",
}}
@@ -0,0 +1,96 @@
import cl from "clsx";
import React, { forwardRef, HTMLAttributes } from "react";
import { BreakpointsAlias } from "../utilities/css";
export interface ResponsiveProps extends HTMLAttributes<HTMLDivElement> {
children: React.ReactNode;
/**
* @example
* above='md'
*/
above?: Exclude<BreakpointsAlias, "xs">;
/**
* @example
* below='md'
*/
below?: Exclude<BreakpointsAlias, "xs">;
/**
* Overrides html-tag
* @default "div"
*/
as?: "div" | "span";
}
const Responsive = forwardRef<
HTMLDivElement,
ResponsiveProps & { variant: "show" | "hide" }
>(
(
{ as: Component = "div", className, above, below, variant, ...rest },
ref
) => {
const aboveProp = variant === "show" ? above : below;
const belowProp = variant === "show" ? below : above;
return (
<Component
{...rest}
ref={ref}
className={cl("navds-responsive", className, {
[`navds-responsive__above--${aboveProp}`]: aboveProp,
[`navds-responsive__below--${belowProp}`]: belowProp,
})}
/>
);
}
);
/**
* Responsive view Primitive to show/hide elements based on breakpoints
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/hide)
* @see 🏷️ {@link ResponsiveProps}
*
* @example
* <HGrid columns={{ xs: 1, md: 2 }} gap="4">
* <div/>
* <Hide below="md">
* // Only visible above "md"
* </Hide>
* </HGrid>
* @example
* <HGrid columns={{ xs: 1, md: 2 }} gap="4">
* <div/>
* <Hide above="md">
* // Only visible below "md"
* </Hide>
* </HGrid>
*/
export const Hide = forwardRef<HTMLDivElement, ResponsiveProps>(
(props, ref) => <Responsive {...props} ref={ref} variant="hide" />
);
/**
* Responsive view Primitive to show/hide elements based on breakpoints
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/show)
* @see 🏷️ {@link ResponsiveProps}
*
* @example
* <HGrid columns={{ xs: 1, md: 2 }} gap="4">
* <div/>
* <Show below="md">
* // Only visible below "md"
* </Show>
* </HGrid>
* @example
* <HGrid columns={{ xs: 1, md: 2 }} gap="4">
* <div/>
* <Show above="md">
* // Only visible above "md"
* </Show>
* </HGrid>
*/
export const Show = forwardRef<HTMLDivElement, ResponsiveProps>(
(props, ref) => <Responsive {...props} ref={ref} variant="show" />
);
@@ -0,0 +1,45 @@
import React from "react";
import type { Meta } from "@storybook/react";
import { Hide } from ".";
import { Tag } from "../../tag";
import { VStack } from "../stack";
export default {
title: "ds-react/Responsive/Hide",
component: Hide,
} satisfies Meta<typeof Hide>;
export const Default = {
render: () => (
<VStack gap="12">
<VStack gap="2" align="center">
<Hide above="xl">
<Tag variant="neutral">Visible below xl</Tag>
</Hide>
<Hide above="lg">
<Tag variant="neutral">Visible below lg</Tag>
</Hide>
<Hide above="md">
<Tag variant="neutral">Visible below md</Tag>
</Hide>
<Hide above="sm">
<Tag variant="neutral">Visible below sm</Tag>
</Hide>
</VStack>
<VStack gap="2" align="center">
<Hide below="xl">
<Tag variant="alt3">Visible above xl</Tag>
</Hide>
<Hide below="lg">
<Tag variant="alt3">Visible above lg</Tag>
</Hide>
<Hide below="md">
<Tag variant="alt3">Visible above md</Tag>
</Hide>
<Hide below="sm">
<Tag variant="alt3">Visible above sm</Tag>
</Hide>
</VStack>
</VStack>
),
};
@@ -0,0 +1 @@
export { Show, Hide, type ResponsiveProps } from "./Responsive";
@@ -0,0 +1,45 @@
import React from "react";
import type { Meta } from "@storybook/react";
import { Show } from ".";
import { Tag } from "../../tag";
import { VStack } from "../stack";
export default {
title: "ds-react/Responsive/Show",
component: Show,
} satisfies Meta<typeof Show>;
export const Default = {
render: () => (
<VStack gap="12">
<VStack gap="2" align="center">
<Show above="xl">
<Tag variant="neutral">Visible above xl</Tag>
</Show>
<Show above="lg">
<Tag variant="neutral">Visible above lg</Tag>
</Show>
<Show above="md">
<Tag variant="neutral">Visible above md</Tag>
</Show>
<Show above="sm">
<Tag variant="neutral">Visible above sm</Tag>
</Show>
</VStack>
<VStack gap="2" align="center">
<Show below="xl">
<Tag variant="alt3">Visible below xl</Tag>
</Show>
<Show below="lg">
<Tag variant="alt3">Visible below lg</Tag>
</Show>
<Show below="md">
<Tag variant="alt3">Visible below md</Tag>
</Show>
<Show below="sm">
<Tag variant="alt3">Visible below sm</Tag>
</Show>
</VStack>
</VStack>
),
};
@@ -7,7 +7,7 @@ export type HStackProps = Omit<StackProps, "direction">;
/**
* Layout-primitive for horizontal flexbox
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/Stack)
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/hstack)
* @see 🏷️ {@link HStackProps}
* @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
*
@@ -3,7 +3,7 @@ import React from "react";
/**
* Layout-primitive for auto-spacing between elements
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/Stack)
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/hstack)
*
* @example
* <HStack gap="8">
@@ -52,14 +52,14 @@ export const Stack: OverridableComponent<StackProps, HTMLDivElement> =
},
ref
) => {
const style = {
const style: React.CSSProperties = {
..._style,
"--__ac-stack-direction": direction,
"--__ac-stack-align": align,
"--__ac-stack-justify": justify,
"--__ac-stack-wrap": wrap ? "wrap" : "nowrap",
...getResponsiveProps(`stack`, "gap", "spacing", gap),
} as React.CSSProperties;
};
return (
<Component
@@ -7,7 +7,7 @@ export type VStackProps = Omit<StackProps, "direction" | "wrap">;
/**
* Layout-primitive for vetical flexbox
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/Stack)
* @see [📝 Documentation](https://aksel.nav.no/komponenter/primitives/vstack)
* @see 🏷️ {@link VStackProps}
* @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
*
+1
View File
@@ -69,4 +69,5 @@ export const ListItem = forwardRef<HTMLLIElement, ListItemProps>(
}
);
ListItem.displayName = "List.Item";
export default ListItem;
+1 -1
View File
@@ -192,6 +192,7 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
const component = (
<dialog
{...rest}
ref={mergedRef}
className={cl("navds-modal", className, {
"navds-modal--polyfilled": needPolyfill,
@@ -213,7 +214,6 @@ export const Modal = forwardRef<HTMLDialogElement, ModalProps>(
? ariaLabelId
: ariaLabelledby
}
{...rest}
>
<ModalContext.Provider
value={{
@@ -16,7 +16,7 @@ export const WithUseRef = () => {
const ref2 = useRef<HTMLDialogElement>(null);
return (
<>
<div>
<Button onClick={() => ref.current?.showModal()}>Open Modal</Button>
<Modal
open={ref.current ? undefined : true /* initially open */}
@@ -80,7 +80,7 @@ export const WithUseRef = () => {
<Button variant="tertiary">Tertiary</Button>
</Modal.Footer>
</Modal>
</>
</div>
);
};
WithUseRef.storyName = "With useRef";
@@ -184,6 +184,7 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
useCallback(
(e: FocusEvent) => {
if (
e.target instanceof HTMLElement &&
![anchorEl, refs?.floating?.current].some((element) =>
element?.contains(e.target as Node)
)
+9
View File
@@ -0,0 +1,9 @@
// eslint-disable-next-line react/no-typos
import "react";
declare module "react" {
interface CSSProperties {
[key: `--ac-${string}`]: string | undefined;
[key: `--__ac-${string}`]: string | undefined;
}
}
+17 -3
View File
@@ -15,6 +15,11 @@ export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
* When not inferring width from children, you must specify width
*/
width?: number | string;
/**
* Overrides html-tag
* @default "div"
*/
as?: "div" | "span";
}
/**
@@ -28,11 +33,20 @@ export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
*/
export const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(
(
{ className, children, height, width, style, variant = "text", ...rest },
{
className,
children,
height,
width,
style,
variant = "text",
as: As = "div",
...rest
},
ref
) => {
return (
<div
<As
{...rest}
ref={ref}
className={cl(
@@ -49,7 +63,7 @@ export const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(
aria-hidden
>
{children}
</div>
</As>
);
}
);
@@ -102,7 +102,7 @@ export const NativeText = {
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur
voluptas sint dolore omnis quia consequatur beatae vero cum officia
debitis. Quidem debitis omnis reprehenderit nobis rerum. Nulla,
magnam? Saepe, eveniet? Test
magnam? Saepe, eveniet?
</Skeleton>
</h1>
<Skeleton>
@@ -110,9 +110,20 @@ export const NativeText = {
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur
voluptas sint dolore omnis quia consequatur beatae vero cum officia
debitis. Quidem debitis omnis reprehenderit nobis rerum. Nulla,
magnam? Saepe, eveniet? Test
magnam? Saepe, eveniet?
</p>
</Skeleton>
</div>
),
};
export const InlineText = {
render: () => (
<BodyLong>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequuntur
voluptas sint dolore <Skeleton as="span">omnis quia consequatur</Skeleton>{" "}
beatae vero cum officia debitis. Quidem debitis omnis reprehenderit nobis
rerum. Nulla, magnam? Saepe, eveniet?
</BodyLong>
),
};
@@ -14,7 +14,7 @@ export default {
const rowsPerPage = 10;
const queryString = (obj) =>
const queryString = (obj: Record<string, number | string | undefined>) =>
Object.keys(obj)
.filter((key) => obj[key] !== undefined)
.map((key) => key + "=" + obj[key])
@@ -22,11 +22,15 @@ const queryString = (obj) =>
const updateData = async (url: string) => {
const newUrl = new URL(`https://www.example.com/${url}`);
const comparator = (a, b, orderBy) => {
if (b[orderBy] < a[orderBy]) {
const comparator = (
a: Record<string, string | number | null>,
b: Record<string, string | number | null>,
orderBy: string
) => {
if ((b[orderBy] ?? "") < (a[orderBy] ?? "")) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
if ((b[orderBy] ?? "") > (a[orderBy] ?? "")) {
return 1;
}
return 0;
@@ -74,7 +78,14 @@ export const Async = () => {
const { results: people, count } = data;
const columns = [
type ColumnsType = {
key: keyof (typeof people)[0];
name: string;
width: number;
sortable?: boolean;
value?: (person: (typeof people)[0]) => string | undefined;
};
const columns: ColumnsType[] = [
{ key: "name", name: "Name", width: 154 },
{ key: "height", name: "Height", width: 108 },
{ key: "mass", name: "Mass", width: 95 },
@@ -105,7 +116,8 @@ export const Async = () => {
sort={sort}
onSortChange={(sortKey) =>
setSort(
sort?.orderBy === sortKey && sort.direction === "descending"
!sortKey ||
(sort?.orderBy === sortKey && sort.direction === "descending")
? undefined
: {
orderBy: sortKey,
@@ -144,7 +156,7 @@ export const Async = () => {
whiteSpace: "nowrap",
textOverflow: "ellipsis",
}}
title={person[key]}
title={person[key]?.toString()}
key={key}
>
{value ? value(person) : person[key]}
+9
View File
@@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.build.json",
"compilerOptions": {
"outDir": "./cjs",
"module": "commonjs",
"noImplicitAny": false
},
"include": ["./src"]
}
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "./tsconfig.json",
"extends": "./tsconfig.build.json",
"compilerOptions": {
"outDir": "./esm",
"module": "esnext",
+3 -5
View File
@@ -1,9 +1,7 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./cjs",
"module": "commonjs",
"noImplicitAny": false
},
"include": ["./src"]
"noImplicitAny": false,
"resolveJsonModule": true
}
}
+10
View File
@@ -1,5 +1,15 @@
# @navikt/ds-tailwind
## 5.4.0
## 5.3.5
## 5.3.4
## 5.3.3
## 5.3.2
## 5.3.1
## 5.3.0
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "5.3.1",
"version": "5.4.0",
"description": "Tailwind config based on @navikt/ds-tokens",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -22,7 +22,7 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^5.3.1",
"@navikt/ds-tokens": "^5.4.0",
"@types/jest": "^29.0.0",
"color": "4.2.3",
"jest": "^29.0.0",
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-tokens
## 5.4.0
### Patch Changes
- Tokens: `data-theme="light"` vil nå tilbakestille theming ([#2238](https://github.com/navikt/aksel/pull/2238))
## 5.3.5
## 5.3.4
## 5.3.3
## 5.3.2
## 5.3.1
## 5.3.0
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "5.3.1",
"version": "5.4.0",
"description": "Design-tokens for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
+58
View File
@@ -1,5 +1,63 @@
# Changelog
## 5.4.0
### @navikt/ds-react
- Primitives: Nye komponenter `Show` og `Hide` er lagt til. ([#2222](https://github.com/navikt/aksel/pull/2222))
<!---->
- Search: Kjører nå bare preventDefault ved Escape når `input` inneholder tekst ([#2245](https://github.com/navikt/aksel/pull/2245))
### @navikt/ds-tokens
- Tokens: `data-theme="light"` vil nå tilbakestille theming ([#2238](https://github.com/navikt/aksel/pull/2238))
### @navikt/ds-css
- Primitives: Nye komponenter `Show` og `Hide` er lagt til. ([#2222](https://github.com/navikt/aksel/pull/2222))
<!---->
- ErrorSummary: Har nå 8px border-radius ([#2256](https://github.com/navikt/aksel/pull/2256))
## 5.3.5
### @navikt/ds-react
- :bug: Popover: sjekk at det er et HTML-element som får fokus ([#2258](https://github.com/navikt/aksel/pull/2258))
## 5.3.4
### @navikt/aksel-icons
- :bug: SVG import map er nå riktig path ([#2250](https://github.com/navikt/aksel/pull/2250))
### @navikt/ds-css
- Alert: 12px -> 8px gap mellom tekst og ikon ved `size="small"` ([#2240](https://github.com/navikt/aksel/pull/2240))
## 5.3.3
### @navikt/ds-react
- HGrid: Har nå `align`-prop for bedre kontroll over child-elementer ([#2242](https://github.com/navikt/aksel/pull/2242))
### @navikt/ds-css
- HGrid: Har nå `align`-prop for bedre kontroll over child-elementer ([#2242](https://github.com/navikt/aksel/pull/2242))
## 5.3.2
### @navikt/ds-react
- Skeleton: Lagt til as-prop for inline brk av Skeleton med span ([#2239](https://github.com/navikt/aksel/pull/2239))
### @navikt/ds-css
- Skeleton: Lagt til as-prop for inline brk av Skeleton med span ([#2239](https://github.com/navikt/aksel/pull/2239))
## 5.3.1
### @navikt/ds-react
+5 -5
View File
@@ -15,11 +15,11 @@
"website"
],
"dependencies": {
"@navikt/aksel-icons": "^5.3.1",
"@navikt/ds-css": "^5.3.1",
"@navikt/ds-react": "^5.3.1",
"@navikt/ds-tailwind": "^5.3.1",
"@navikt/ds-tokens": "^5.3.1"
"@navikt/aksel-icons": "^5.4.0",
"@navikt/ds-css": "^5.4.0",
"@navikt/ds-react": "^5.4.0",
"@navikt/ds-tailwind": "^5.4.0",
"@navikt/ds-tokens": "^5.4.0"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.2.3"
@@ -11,12 +11,12 @@ import {
Bilde,
CodeExamples,
DoDont,
Kode,
LevelTwoHeading,
logNav,
PropsSeksjon,
RelatertInnhold,
SideModul,
Snippet,
Tabell,
TastaturModul,
Tips,
@@ -38,7 +38,7 @@ const serializers = {
bilde: ({ node }) => <Bilde node={node} />,
alert: ({ node }) => <Alert node={node} />,
expansioncard: ({ node }) => <ExpansionCard node={node} />,
kode: ({ node }) => <Kode node={node} />,
kode: ({ node }) => <Snippet node={node} />,
tabell_v2: ({ node }) => <Tabell node={node} />,
accordion: ({ node }) => <Accordion node={node} />,
props_seksjon: ({ node }) => <PropsSeksjon node={node} />,
-1
View File
@@ -7,7 +7,6 @@ export * from "./sanity-modules/code";
export * from "./sanity-modules/code-examples";
export { default as DoDont } from "./sanity-modules/DoDont";
export { default as IntroKomponent } from "./sanity-modules/IntroSeksjon";
export { default as Kode } from "./sanity-modules/Kode";
export { default as PropsSeksjon } from "./sanity-modules/props/PropsSeksjon";
export { default as PropTable } from "./sanity-modules/props/PropTabell";
export { default as SideModul } from "./sanity-modules/SideModul";
@@ -25,8 +25,8 @@ export const Error = () => {
<div className="flex flex-wrap gap-2 px-4 pb-4 md:px-10">
{Object.keys(searchOptions)
.slice(0, Object.keys(searchOptions).length - 1)
.map((x) => (
<Skeleton variant="rounded" height="1.75rem">
.map((x, i) => (
<Skeleton variant="rounded" height="1.75rem" key={i}>
{searchOptions[x].display}
</Skeleton>
))}
@@ -1,13 +0,0 @@
import { Snippet } from "@/components";
import { withErrorBoundary } from "@/error-boundary";
import { CodeSnippetT } from "@/types";
const Kode = ({ node }: { node: CodeSnippetT }) => {
if (!node || !node.code) {
return null;
}
return <Snippet node={node} className="last:mb-0" />;
};
export default withErrorBoundary(Kode, "Kode");
@@ -34,7 +34,7 @@ const TokenTable = ({ node }: { node: TokenTableT }) => {
))}
</AkselTable>
{(open || !showMore) && (
<div className="border-border-subtle bg-surface-default relative -mt-8 w-full rounded-b-lg border border-t-0 p-2 pr-14">
<div className="border-border-subtle bg-surface-default relative -mt-9 w-full rounded-b-lg border border-t-0 p-2 pr-14">
<CopyButton
copyText={Object.entries(tokens).reduce(
(prev, cur) =>
@@ -0,0 +1,46 @@
import { getKey } from "@/sb-util";
import type { Meta, StoryObj } from "@storybook/react";
import CodeExample from "./Examples";
const meta = {
title: "Sanity-modules/CodeExample",
component: CodeExample,
tags: ["autodocs"],
} satisfies Meta<typeof CodeExample>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Designsystem: Story = {
args: {
node: {
title: "button",
dir: {
title: "button",
filer: [
{
_key: getKey(),
description: null,
innhold:
'import { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button variant="primary">Primary</Button>\n <Button variant="secondary">Secondary</Button>\n <Button variant="tertiary">Tertiary</Button>\n <Button variant="danger">Danger</Button>\n </div>\n );\n};',
navn: "default",
},
{
_key: getKey(),
description: "Testdescription",
innhold:
'import { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button variant="primary-neutral">Primary</Button>\n <Button variant="secondary-neutral">Secondary</Button>\n <Button variant="tertiary-neutral">Tertiary</Button>\n </div>\n );\n};',
navn: "neutral",
},
{
_key: getKey(),
description: null,
innhold:
'import { PencilIcon } from "@navikt/aksel-icons";\nimport { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button size="small" variant="primary" icon={<PencilIcon aria-hidden />}>\n Primary\n </Button>\n <Button size="small" variant="secondary">\n Secondary\n </Button>\n <Button size="small" variant="tertiary">\n Tertiary\n </Button>\n <Button size="small" variant="danger">\n Danger\n </Button>\n </div>\n );\n};',
navn: "small",
},
],
},
},
},
};
@@ -1,6 +1,6 @@
import { capitalize, Snippet } from "@/components";
import { withErrorBoundary } from "@/error-boundary";
import { CodeExapmplesT } from "@/types";
import { CodeExamplesT } from "@/types";
import {
ExternalLinkIcon,
LaptopIcon,
@@ -15,7 +15,7 @@ import { CodeSandbox } from "./CodeSandbox";
const iframePadding = 192;
const iframeId = "example-iframe";
const ComponentExamples = ({ node }: { node: CodeExapmplesT }) => {
const ComponentExamples = ({ node }: { node: CodeExamplesT }) => {
const [activeExample, setActiveExample] = useState(null);
const [frameState, setFrameState] = useState(300);
const [unloaded, setUnloaded] = useState(true);
@@ -208,7 +208,7 @@ const ComponentExamples = ({ node }: { node: CodeExapmplesT }) => {
<Snippet
node={{
code: { code: fil.innhold.trim(), language: "jsx" },
code: { code: fil.innhold.trim(), language: "tsx" },
}}
/>
</>
@@ -0,0 +1,66 @@
import type { Meta, StoryObj } from "@storybook/react";
import Snippet from "./Snippet";
const meta = {
title: "Sanity-modules/CodeSnippet",
component: Snippet,
tags: ["autodocs"],
} satisfies Meta<typeof Snippet>;
export default meta;
type Story = StoryObj<typeof meta>;
export const JSX: Story = {
args: {
node: {
code: {
code: 'import { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button variant="primary">Primary</Button>\n <Button variant="secondary">Secondary</Button>\n <Button variant="tertiary">Tertiary</Button>\n <Button variant="danger">Danger</Button>\n </div>\n );\n};',
language: "jsx",
},
},
},
};
export const Bash: Story = {
args: {
node: {
code: {
code: "yarn install @navikt/ds-react @navikt/ds-css\nnpm add @navikt/ds-react @navikt/ds-css",
language: "bash",
},
},
},
};
export const Terminal: Story = {
args: {
node: {
code: {
code: "npx cowsay moo",
language: "terminal",
},
},
},
};
export const JS: Story = {
args: {
node: {
code: {
code: "const numbers = [1, 2, 3, 4];\n\nnumbers.map(x => console.log(x))",
language: "js",
},
},
},
};
export const HTML: Story = {
args: {
node: {
code: {
code: "<button>Click me!</button>",
language: "html",
},
},
},
};
@@ -1,19 +1,13 @@
import { withErrorBoundary } from "@/error-boundary";
import cl from "clsx";
import Highlight, { defaultProps, Language } from "prism-react-renderer";
import { Highlight, Language } from "prism-react-renderer";
import React from "react";
import { CodeSnippetT } from "@/types";
import { CopyButton } from "@navikt/ds-react";
import { CopyButton, Label } from "@navikt/ds-react";
import { ChevronRightIcon } from "@navikt/aksel-icons";
import theme from "./theme";
const CodeSnippet = ({
node: { code },
className,
...props
}: {
node: CodeSnippetT;
className?: string;
style?: any;
}) => {
const CodeSnippet = ({ node: { code, title } }: { node: CodeSnippetT }) => {
if (!code || !code.code) {
return null;
}
@@ -24,49 +18,75 @@ const CodeSnippet = ({
case "js":
language = "javascript";
break;
case "html":
language = "markup";
case "jsx":
language = "tsx";
break;
case "terminal":
language = "bash";
case "scss":
language = "css";
break;
case "less":
language = "css";
break;
default:
break;
}
const terminalStyling = (lang) => lang === "bash" || lang === "terminal";
const formatTitle = (input) => (input === "bash" ? "Terminal" : input);
return (
<>
<div
className={cl(className, "relative mb-8 grid rounded-lg bg-[#0f172a]")}
{...props}
>
<div className="absolute right-4 top-2 z-10 rounded-lg bg-[#0f172a] p-1 group-[.aksel-artikkel]/aksel:hidden">
<CopyButton data-theme="dark" size="small" copyText={code.code} />
<section
aria-label="Kode"
className="aksel-codesnippet bg-surface-inverted relative mb-7 grid rounded-lg last:mb-0"
>
<div className="text-text-on-inverted text-medium relative flex leading-6">
<div className="mt-2 flex flex-none items-center border-b border-b-gray-200 border-t-transparent px-4 py-1.5 text-gray-100">
{!title ? (
<Label as="span" className="uppercase">
{formatTitle(language)}
</Label>
) : (
<Label as="span">{title}</Label>
)}
</div>
<Highlight
code={code.code}
language={language}
{...defaultProps}
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="text-text-on-inverted min-h-14 relative m-0 max-h-96 overflow-x-auto overflow-y-auto rounded-lg bg-[#0f172a] p-4 font-mono group-[.aksel-artikkel]/aksel:mr-0">
<div className="mt-2 flex h-10 flex-auto rounded-tl bg-gray-100/10 shadow-inner" />
<CopyButton
data-theme="dark"
size="small"
copyText={code.code}
className="absolute right-2 top-3"
/>
</div>
<Highlight code={code.code} language={language} theme={theme}>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="text-medium m-0 flex overflow-auto rounded-lg leading-6">
<code className="max-h-80 min-w-full flex-none p-4 pb-0">
{tokens.map((line, i) => (
<div
<span
key={i}
{...getLineProps({ line, key: i })}
className="text-medium whitespace-pre break-words"
className={cl(
"last-of-type:pb-4",
terminalStyling(language) ? "flex items-center" : "block"
)}
>
{terminalStyling(language) && (
<ChevronRightIcon
aria-hidden
className="mr-2 h-5 w-auto flex-none overflow-visible text-pink-400"
/>
)}
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
</span>
))}
</pre>
)}
</Highlight>
</div>
</>
</code>
</pre>
)}
</Highlight>
</section>
);
};
@@ -1,8 +1,5 @@
import dynamic from "next/dynamic";
export const Snippet = dynamic(() => import("./Snippet"), {
loading: () => (
<div className="mb-8 block min-h-32 w-full rounded-md bg-gray-900" />
),
ssr: false,
});
@@ -0,0 +1,111 @@
import { PrismTheme } from "prism-react-renderer";
export const JetwaveDark: PrismTheme = {
plain: {
color: "#f8fafc",
backgroundColor: "#011627",
},
styles: [
{
types: ["prolog"],
style: {
color: "#000080",
},
},
{
types: ["comment"],
style: {
color: "var(--a-gray-300)",
},
},
{
types: ["builtin", "changed", "keyword", "interpolation-punctuation"],
style: {
color: "#569CD6",
},
},
{
types: ["number", "inserted"],
style: {
color: "var(--a-gray-50)",
},
},
{
types: ["constant"],
style: {
color: "#f8fafc",
},
},
{
types: ["attr-name", "variable"],
style: {
color: "#9CDCFE",
},
},
{
types: ["deleted", "string", "attr-value", "template-punctuation"],
style: {
color: "#cbd5e1",
},
},
{
types: ["selector"],
style: {
color: "#D7BA7D",
},
},
{
types: ["tag"],
style: {
color: "var(--a-green-200)",
},
},
{
types: ["tag"],
languages: ["jsx"],
style: {
color: "var(--a-blue-200)",
},
},
{
types: ["tag"],
languages: ["markup"],
style: {
color: "var(--a-blue-200)",
},
},
{
types: ["punctuation", "operator"],
style: {
color: "#D4D4D4",
},
},
{
types: ["punctuation"],
languages: ["markup"],
style: {
color: "#808080",
},
},
{
types: ["function"],
style: {
color: "#7dd3fc",
},
},
{
types: ["class-name"],
style: {
color: "var(--a-green-200)",
},
},
{
types: ["char"],
style: {
color: "#D16969",
},
},
],
};
export default JetwaveDark;
@@ -33,7 +33,9 @@ const List = ({ prop, parent }: { prop: any; parent: string }) => {
<span>{prop.type ? <>{Highlighter({ type: prop.type })}</> : ""}</span>
</dt>
{prop.description && (
<dd className="font-sans text-base">{prop.description}</dd>
<dd className="whitespace-pre-wrap font-sans text-base">
{prop.description}
</dd>
)}
{prop.name === "ref" && prop.type.includes("Ref<") && (
<dd className="font-sans text-base">
@@ -151,7 +151,7 @@ export function TableOfContentsv2({
<nav
aria-labelledby="toc-heading"
id="toc-scroll"
className="max-h-[80vh] overflow-y-auto"
className="max-h-[80vh] w-full overflow-y-auto"
>
<ul>
{toc.map((link) => {
@@ -1,33 +1,89 @@
import { ComponentType } from "react";
import styles from "./examples.module.css";
import {
LaptopIcon,
MobileIcon,
MobileSmallIcon,
MonitorIcon,
TabletIcon,
} from "@navikt/aksel-icons";
import { HStack } from "@navikt/ds-react";
import cl from "clsx";
import { ComponentType, useEffect, useState } from "react";
import styles from "./examples.module.css";
export const withDsExample = (
Component: ComponentType,
/**
* Static: Used for dynamic-height examples like ExpansionCard
*/
variant?: "full" | "inverted" | "static" | "subtle"
{
variant,
showBreakpoints,
}: {
variant?: "full" | "inverted" | "static" | "subtle";
showBreakpoints?: boolean;
} = {}
) => {
const DsHOC = (props: any) => (
<div
className={cl(styles.examples, {
"bg-gray-900": variant === "inverted",
"bg-bg-subtle": variant === "subtle",
[styles.containerStatic]: variant === "static",
[styles.container]: variant !== "static",
})}
>
const DsHOC = (props: any) => {
const [width, setWidth] = useState<number>();
useEffect(() => {
const updateWidth = () => {
setWidth(window.innerWidth);
};
window.addEventListener("resize", updateWidth);
updateWidth();
return () => {
window.removeEventListener("resize", updateWidth);
};
}, []);
const BreakpointText = () => {
let breakpoint = "";
let Icon = LaptopIcon;
if (width < 480) {
Icon = MobileSmallIcon;
breakpoint = "xs";
} else if (width < 768) {
Icon = MobileIcon;
breakpoint = "sm";
} else if (width < 1024) {
Icon = TabletIcon;
breakpoint = "md";
} else if (width < 1280) {
Icon = LaptopIcon;
breakpoint = "lg";
} else {
Icon = MonitorIcon;
breakpoint = "xl";
}
return (
<HStack gap="1" className="absolute left-2 top-1" align="center">
<Icon aria-hidden fontSize="1.5rem" /> {`${breakpoint}`}
</HStack>
);
};
return (
<div
id="ds-example"
className={cl({
"w-full": variant === "full",
className={cl(styles.examples, {
"bg-gray-900": variant === "inverted",
"bg-bg-subtle": variant === "subtle",
[styles.containerStatic]: variant === "static",
[styles.container]: variant !== "static",
})}
>
<Component {...props} />
{showBreakpoints && <BreakpointText />}
<div
id="ds-example"
className={cl({
"w-full": variant === "full",
})}
>
<Component {...props} />
</div>
</div>
</div>
);
);
};
if (Component.displayName) {
DsHOC.displayName = `DsExample${Component.displayName}`;
@@ -1,6 +1,7 @@
import * as Icons from "@navikt/aksel-icons";
import meta from "@navikt/aksel-icons/metadata";
import { Button, CopyButton, Heading, Tooltip } from "@navikt/ds-react";
import { Button, Heading } from "@navikt/ds-react";
import Snippet from "components/sanity-modules/code/Snippet";
import { SuggestionBlock } from "components/website-modules/suggestionblock";
import {
AmplitudeEvents,
@@ -8,7 +9,6 @@ import {
} from "components/website-modules/utils/amplitude";
import Link from "next/link";
import { useRouter } from "next/router";
import Highlight, { defaultProps } from "prism-react-renderer";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import ReactDOMServer from "react-dom/server";
@@ -126,113 +126,37 @@ export const IconSidebar = ({
>
Last ned
</Button>
<div data-prism-theme="light">
<Heading level="3" size="small" className="mb-2 mt-6">
Kode
</Heading>
<div className="ring-border-subtle rounded-lg ring-1">
<div className="border-b-border-subtle text-medium flex items-center justify-between border-b px-3 py-1">
<span>Import</span>
<Tooltip content="Kopier React-import">
<CopyButton
size="small"
copyText={`import {
${name}Icon
} from '@navikt/aksel-icons';`}
/>
</Tooltip>
</div>
<Highlight
code={`import {
${name}Icon
} from '@navikt/aksel-icons';`}
language="tsx"
{...defaultProps}
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="relative m-0 overflow-x-auto overflow-y-auto rounded-b-lg p-3 font-mono">
{tokens.map((line, i) => (
<div
key={i}
{...getLineProps({ line, key: i })}
className="text-medium whitespace-pre break-words"
>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</div>
<div className="ring-border-subtle mt-3 rounded-lg ring-1">
<div className="border-b-border-subtle text-medium flex items-center justify-between border-b px-3 py-1">
<span>React</span>
<Tooltip content="Kopier React-snippet">
<CopyButton
size="small"
copyText={`<${name}Icon title="a11y-title" />`}
/>
</Tooltip>
</div>
<Highlight
code={`<${name}Icon title="a11y-title" fontSize="1.5rem" />`}
language="tsx"
{...defaultProps}
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="relative m-0 max-w-[80vw] overflow-x-auto overflow-y-auto rounded-b-lg p-3 font-mono lg:max-w-sm">
{tokens.map((line, i) => (
<div
key={i}
{...getLineProps({ line, key: i })}
className="text-medium whitespace-pre break-words"
>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</div>
<div className="ring-border-subtle mt-3 rounded-lg ring-1">
<div className="border-b-border-subtle text-medium flex items-center justify-between border-b px-3 py-1">
<span>SVG</span>
<Tooltip content="Kopier SVG-kode">
<CopyButton
size="small"
copyText={ReactDOMServer.renderToString(<SelectedIcon />)}
/>
</Tooltip>
</div>
<Highlight
code={ReactDOMServer.renderToString(<SelectedIcon />)}
language="tsx"
{...defaultProps}
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="w-text relative m-0 max-w-[80vw] overflow-x-auto overflow-y-auto rounded-b-lg p-3 font-mono lg:w-auto lg:max-w-sm">
{tokens.map((line, i) => (
<div
key={i}
{...getLineProps({ line, key: i })}
className="text-medium whitespace-pre break-words"
>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
))}
</pre>
)}
</Highlight>
</div>
<div className="mt-6 max-w-md">
<Snippet
node={{
title: "Import",
code: {
code: `import { ${name}Icon } from '@navikt/aksel-icons';`,
language: "jsx",
},
}}
/>
<Snippet
node={{
title: "React",
code: {
code: `<${name}Icon title="a11y-title" fontSize="1.5rem" />`,
language: "jsx",
},
}}
/>
<Snippet
node={{
title: "SVG",
code: {
code: ReactDOMServer.renderToString(<SelectedIcon />),
language: "jsx",
},
}}
/>
<div>
<SuggestionBlock variant="ikon" reference={name} />
</div>
+2
View File
@@ -12,6 +12,8 @@ test.describe("Axe a11y", () => {
.exclude("iframe")
.exclude("#aksel-expansioncard")
.exclude("#toc-scroll")
.exclude("#toc-scroll")
.exclude(".aksel-codesnippet")
.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});
+9 -11
View File
@@ -28,17 +28,16 @@
"watch:tw": "yarn tailwindcss -i ./styles/index.css -o ./dist/tw.css --watch"
},
"dependencies": {
"@amplitude/analytics-browser": "^2.0.0",
"@amplitude/analytics-browser": "^2.2.3",
"@sanity/block-content-to-react": "^3.0.0",
"@sanity/client": "^6.4.6",
"@sanity/code-input": "4.1.1",
"@sanity/color-input": "^3.1.0",
"@sanity/icons": "2.4.1",
"@sanity/image-url": "1.0.2",
"@sanity/preview-kit": "^2.3.0",
"@sanity/table": "1.0.1",
"@sanity/ui": "^1.7.4",
"@sanity/vision": "3.15.1",
"@sanity/ui": "^1.7.11",
"@sanity/vision": "3.16.2",
"@svgr/webpack": "^5.5.0",
"boring-avatars": "1.10.1",
"clsx": "^1.2.1",
@@ -48,16 +47,15 @@
"lodash": "^4.17.21",
"next": "^13.2.1",
"next-logger": "^3.0.2",
"next-sanity": "^5.2.7",
"next-sanity": "^5.4.6",
"pino": "^8.14.1",
"prism-react-renderer": "^1.3.0",
"prismjs": "^1.27.0",
"prism-react-renderer": "^2.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-responsive-masonry": "^2.1.7",
"sanity": "3.15.1",
"sanity": "3.16.2",
"sanity-plugin-asset-source-unsplash": "^1.1.0",
"sanity-plugin-media": "^2.0.5",
"sanity-plugin-media": "^2.2.2",
"sharp": "0.31.3",
"sitemap": "^7.0.0",
"styled-components": "^5.2",
@@ -71,8 +69,8 @@
"@next/bundle-analyzer": "^12.1.0",
"@next/eslint-plugin-next": "^12.2.0",
"@playwright/test": "1.35.1",
"@sanity/block-tools": "^3.15.1",
"@sanity/schema": "^3.15.1",
"@sanity/block-tools": "^3.16.2",
"@sanity/schema": "^3.16.2",
"@testing-library/jest-dom": "^5.16.0",
"@testing-library/react": "^13.3.0",
"@types/jest": "^29.0.0",
@@ -33,7 +33,7 @@ const Example = () => {
);
};
export default withDsExample(Example, "static");
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -32,7 +32,7 @@ const Example = () => {
);
};
export default withDsExample(Example, "static");
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -32,7 +32,7 @@ const Example = () => {
);
};
export default withDsExample(Example, "static");
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -51,7 +51,7 @@ const Example = () => {
);
};
export default withDsExample(Example, "static");
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -32,7 +32,7 @@ const Example = () => {
);
};
export default withDsExample(Example, "static");
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -25,7 +25,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -9,18 +9,18 @@ const Example = () => {
<VStack gap="4">
<div>
<Descriptor>Default</Descriptor>
<BodyLong color="default">{lorem}</BodyLong>
<BodyLong textColor="default">{lorem}</BodyLong>
</div>
<Divider />
<div>
<Descriptor>Subtle</Descriptor>
<BodyLong color="subtle">{lorem}</BodyLong>
<BodyLong textColor="subtle">{lorem}</BodyLong>
</div>
</VStack>
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -26,7 +26,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -22,7 +22,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -5,7 +5,7 @@ const Example = () => {
return <BodyLong as="span">Dette er nå en span!</BodyLong>;
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -26,7 +26,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -17,7 +17,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -13,7 +13,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -17,7 +17,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -24,7 +24,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -8,18 +8,18 @@ const Example = () => {
<VStack gap="4">
<div>
<Descriptor>Default</Descriptor>
<BodyShort color="default">{lorem}</BodyShort>
<BodyShort textColor="default">{lorem}</BodyShort>
</div>
<Divider />
<div>
<Descriptor>Subtle</Descriptor>
<BodyShort color="subtle">{lorem}</BodyShort>
<BodyShort textColor="subtle">{lorem}</BodyShort>
</div>
</VStack>
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
@@ -25,7 +25,7 @@ const Example = () => {
);
};
export default withDsExample(Example);
export default withDsExample(Example, { variant: "static" });
/* Storybook story */
export const Demo = {
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff. Show more