Compare commits

..
Author SHA1 Message Date
Ken 8397677049 perf: Skip observing style-changes 2026-11-03 14:31:18 +01:00
Ken 2bbf17e8b0 perf(DataGrid.Table): Optimize table rebuild 2026-11-02 16:23:44 +01:00
78 changed files with 936 additions and 1009 deletions

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
---
"@navikt/ds-react": patch
"@navikt/aksel-icons": patch
---
ESM: Mark ESM output as side-effect free, so bundlers like webpack, Turbopack and esbuild can tree-shake unused components and icons.
+5
View File
@@ -0,0 +1,5 @@
---
"@navikt/ds-react": patch
---
Date utilities: Import date-fns functions and locales from their own paths, so unbundled Node imports (SSR, Vitest/Jest) no longer load every date-fns locale.
+5
View File
@@ -0,0 +1,5 @@
---
"@navikt/ds-react": patch
---
DataGrid.Table: Keyboard navigation no longer rebuilds the internal grid map on every arrow key press, improving responsiveness in large tables.
+1 -7
View File
@@ -61,14 +61,8 @@ runs:
SANITY_AUTH_TOKEN: ${{ inputs.sanity_deploy_studio }}
shell: bash
- name: Generate RSS feed
run: yarn workspace website update:rss
env:
SANITY_READ_NO_DRAFTS: ${{ inputs.sanity_read_no_drafts_token }}
shell: bash
- name: Build Next.js website
run: yarn workspace website build:with-playroom
run: yarn build:next
env:
SANITY_READ: ${{ inputs.sanity_read_token }}
SANITY_READ_NO_DRAFTS: ${{ inputs.sanity_read_no_drafts_token }}
+2
View File
@@ -19,6 +19,7 @@ updates:
applies-to: version-updates
patterns:
- "@next/eslint-plugin-next"
- "@next/bundle-analyzer"
- "next"
sanity:
applies-to: version-updates
@@ -52,6 +53,7 @@ updates:
applies-to: security-updates
patterns:
- "@next/eslint-plugin-next"
- "@next/bundle-analyzer"
- "next"
sanity-security:
applies-to: security-updates
-10
View File
@@ -1,15 +1,5 @@
# @navikt/aksel-icons
## 8.22.0
### Minor Changes
- Icons: New icons `Gift`, `ArrowsPointingIn` and `ArrowsPointingOut`. ([#5484](https://github.com/navikt/aksel/pull/5484))
### Patch Changes
- ESM: Mark ESM output as side-effect free, so bundlers like webpack, Turbopack and esbuild can tree-shake unused components and icons. ([#5472](https://github.com/navikt/aksel/pull/5472))
## 8.21.0
### Minor Changes
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.0001 13.2501C10.4142 13.2501 10.7501 13.5859 10.7501 14.0001V18.0001C10.75 18.4142 10.4142 18.75 10.0001 18.7501C9.58586 18.7501 9.25009 18.4142 9.25006 18.0001V15.8106L5.03033 20.0303C4.73746 20.3232 4.26268 20.3232 3.96978 20.0303C3.67689 19.7374 3.67689 19.2627 3.96978 18.9698L8.18951 14.7501H6.00006C5.58586 14.7501 5.25009 14.4142 5.25006 14.0001C5.25006 13.5858 5.58584 13.2501 6.00006 13.2501H10.0001ZM18.0001 13.2501C18.4142 13.2501 18.7501 13.5859 18.7501 14.0001C18.75 14.4142 18.4142 14.75 18.0001 14.7501H15.8106L20.0303 18.9698C20.3232 19.2627 20.3232 19.7375 20.0303 20.0303C19.7375 20.3232 19.2627 20.3232 18.9698 20.0303L14.7501 15.8106V18.0001C14.75 18.4142 14.4142 18.75 14.0001 18.7501C13.5859 18.7501 13.2501 18.4142 13.2501 18.0001V14.0001C13.2501 13.8011 13.3291 13.6104 13.4698 13.4698C13.6104 13.3291 13.8011 13.2501 14.0001 13.2501H18.0001ZM3.96978 3.96978C4.26268 3.67689 4.73744 3.67689 5.03033 3.96978L9.25006 8.18951V6.00005C9.25006 5.58584 9.58584 5.25005 10.0001 5.25005C10.4142 5.25008 10.7501 5.58586 10.7501 6.00005V10.0001C10.75 10.4142 10.4142 10.75 10.0001 10.7501H6.00006C5.58586 10.7501 5.25009 10.4142 5.25006 10.0001C5.25006 9.58584 5.58584 9.25005 6.00006 9.25005H8.18951L3.96978 5.03033C3.67689 4.73743 3.67689 4.26267 3.96978 3.96978ZM18.9698 3.96978C19.2627 3.67689 19.7374 3.67689 20.0303 3.96978C20.3232 4.26268 20.3232 4.73745 20.0303 5.03033L15.8106 9.25005H18.0001C18.4142 9.25008 18.7501 9.58586 18.7501 10.0001C18.75 10.4142 18.4142 10.75 18.0001 10.7501H14.0001C13.5859 10.7501 13.2501 10.4142 13.2501 10.0001V6.00005C13.2501 5.58584 13.5858 5.25005 14.0001 5.25005C14.4142 5.25008 14.7501 5.58586 14.7501 6.00005V8.18951L18.9698 3.96978Z" fill="#202733"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

@@ -1,12 +0,0 @@
name: ArrowsPointingIn
category: Arrows
sub_category: Arrow
keywords:
- arrows
- piler
- fullscreen
- fullskjerm
- lukk
- close
variant: Stroke
created_at: 31.10.2026
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.96973 13.9697C9.26262 13.6768 9.73738 13.6768 10.0303 13.9697C10.3232 14.2626 10.3232 14.7374 10.0303 15.0303L5.81055 19.25H8C8.41421 19.25 8.75 19.5858 8.75 20C8.75 20.4142 8.41421 20.75 8 20.75H4C3.80109 20.75 3.61038 20.6709 3.46973 20.5303C3.32907 20.3896 3.25 20.1989 3.25 20V16C3.25 15.5858 3.58579 15.25 4 15.25C4.41421 15.25 4.75 15.5858 4.75 16V18.1895L8.96973 13.9697ZM13.9697 13.9697C14.2626 13.6768 14.7374 13.6768 15.0303 13.9697L19.25 18.1895V16C19.25 15.5858 19.5858 15.25 20 15.25C20.4142 15.25 20.75 15.5858 20.75 16V20C20.75 20.1989 20.6709 20.3896 20.5303 20.5303C20.3896 20.6709 20.1989 20.75 20 20.75H16C15.5858 20.75 15.25 20.4142 15.25 20C15.25 19.5858 15.5858 19.25 16 19.25H18.1895L13.9697 15.0303C13.6768 14.7374 13.6768 14.2626 13.9697 13.9697ZM8 3.25C8.41421 3.25 8.75 3.58579 8.75 4C8.75 4.41421 8.41421 4.75 8 4.75H5.81055L10.0303 8.96973C10.3232 9.26262 10.3232 9.73738 10.0303 10.0303C9.73738 10.3232 9.26262 10.3232 8.96973 10.0303L4.75 5.81055V8C4.75 8.41421 4.41421 8.75 4 8.75C3.58579 8.75 3.25 8.41421 3.25 8V4C3.25 3.58579 3.58579 3.25 4 3.25H8ZM20 3.25C20.4142 3.25 20.75 3.58579 20.75 4V8C20.75 8.41421 20.4142 8.75 20 8.75C19.5858 8.75 19.25 8.41421 19.25 8V5.81055L15.0303 10.0303C14.7374 10.3232 14.2626 10.3232 13.9697 10.0303C13.6768 9.73738 13.6768 9.26262 13.9697 8.96973L18.1895 4.75H16C15.5858 4.75 15.25 4.41421 15.25 4C15.25 3.58579 15.5858 3.25 16 3.25H20Z" fill="#202733"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1,12 +0,0 @@
name: ArrowsPointingOut
category: Arrows
sub_category: Arrow
keywords:
- arrows
- piler
- fullscreen
- fullskjerm
- open
- åpne
variant: Stroke
created_at: 31.10.2026
@@ -6,7 +6,5 @@ keywords:
- søkeresultater
- tabell
- trakt
- fjern
- slett
variant: Stroke
created_at: 26.10.2026
@@ -6,7 +6,5 @@ keywords:
- søkeresultater
- tabell
- trakt
- fjern
- slett
variant: Fill
created_at: 26.10.2026
-3
View File
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 3.25C15.5188 3.25 16.75 4.48122 16.75 6C16.75 6.45058 16.6394 6.87468 16.4473 7.25H19C19.9665 7.25 20.75 8.0335 20.75 9V11C20.75 11.6977 20.3407 12.298 19.75 12.5791V19C19.75 19.9665 18.9665 20.75 18 20.75H6C5.0335 20.75 4.25 19.9665 4.25 19V12.5791C3.65928 12.298 3.25 11.6977 3.25 11V9C3.25 8.0335 4.0335 7.25 5 7.25H7.55273C7.36065 6.87468 7.25 6.45058 7.25 6C7.25 4.48122 8.48122 3.25 10 3.25C10.789 3.25 11.4985 3.58399 12 4.11621C12.5015 3.58399 13.211 3.25 14 3.25ZM5.75 19C5.75 19.1381 5.86193 19.25 6 19.25H11.25V12.75H5.75V19ZM12.75 19.25H18C18.1381 19.25 18.25 19.1381 18.25 19V12.75H12.75V19.25ZM5 8.75C4.86193 8.75 4.75 8.86193 4.75 9V11C4.75 11.1381 4.86193 11.25 5 11.25H11.25V8.75H5ZM12.75 11.25H19C19.1381 11.25 19.25 11.1381 19.25 11V9C19.25 8.86193 19.1381 8.75 19 8.75H12.75V11.25ZM10 4.75C9.30964 4.75 8.75 5.30964 8.75 6C8.75 6.69036 9.30964 7.25 10 7.25H11.25V6C11.25 5.30964 10.6904 4.75 10 4.75ZM14 4.75C13.3096 4.75 12.75 5.30964 12.75 6V7.25H14C14.6904 7.25 15.25 6.69036 15.25 6C15.25 5.30964 14.6904 4.75 14 4.75Z" fill="#202733"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-8
View File
@@ -1,8 +0,0 @@
name: Gift
category: Home
sub_category: Toys
keywords:
- gave
- presang
variant: Stroke
created_at: 31.10.2026
-3
View File
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.56055 13.2197C4.70421 13.2397 4.85088 13.25 5 13.25H11C11.1381 13.25 11.25 13.3619 11.25 13.5V20.5C11.25 20.6381 11.1381 20.75 11 20.75H6C5.0335 20.75 4.25 19.9665 4.25 19V13.4775C4.25 13.3162 4.40077 13.1975 4.56055 13.2197ZM19.4395 13.2197C19.5992 13.1975 19.75 13.3162 19.75 13.4775V19C19.75 19.9665 18.9665 20.75 18 20.75H13C12.8619 20.75 12.75 20.6381 12.75 20.5V13.5C12.75 13.3619 12.8619 13.25 13 13.25H19C19.1491 13.25 19.2958 13.2397 19.4395 13.2197ZM14 3.25C15.5188 3.25 16.75 4.48122 16.75 6C16.75 6.45058 16.6394 6.87468 16.4473 7.25H19C19.9665 7.25 20.75 8.0335 20.75 9V10C20.75 10.9665 19.9665 11.75 19 11.75H13C12.8619 11.75 12.75 11.6381 12.75 11.5V7.25H14C14.6904 7.25 15.25 6.69036 15.25 6C15.25 5.30964 14.6904 4.75 14 4.75C13.3096 4.75 12.75 5.30964 12.75 6V7.24707H11.25V6C11.25 5.30964 10.6904 4.75 10 4.75C9.30964 4.75 8.75 5.30964 8.75 6C8.75 6.69036 9.30964 7.25 10 7.25H11.25V11.5C11.25 11.6381 11.1381 11.75 11 11.75H5C4.0335 11.75 3.25 10.9665 3.25 10V9C3.25 8.0335 4.0335 7.25 5 7.25H7.55273C7.36065 6.87468 7.25 6.45058 7.25 6C7.25 4.48122 8.48122 3.25 10 3.25C10.789 3.25 11.4985 3.58399 12 4.11621C12.5015 3.58399 13.211 3.25 14 3.25Z" fill="#202733"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

-8
View File
@@ -1,8 +0,0 @@
name: GiftFill
category: Home
sub_category: Toys
keywords:
- gave
- presang
variant: Fill
created_at: 31.10.2026
+1 -1
View File
@@ -2,6 +2,6 @@ name: Keyboard
category: Interface
sub_category: Devices
keywords:
- Tastatur
- Keyboard
variant: Stroke
created_at: 26.10.2026
+1 -1
View File
@@ -2,6 +2,6 @@ name: KeyboardFill
category: Interface
sub_category: Devices
keywords:
- Tastatur
- KeyboardFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableCellsMerge
category: Interface
sub_category: Table
keywords:
- celle
- slå sammen
- tabell
- datagrid
- TableCellsMerge
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableCellsMergeFill
category: Interface
sub_category: Table
keywords:
- celle
- slå sammen
- tabell
- datagrid
- TableCellsMergeFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableCellsSplit
category: Interface
sub_category: Table
keywords:
- celle
- splitt
- tabell
- datagrid
- TableCellsSplit
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableCellsSplitFill
category: Interface
sub_category: Table
keywords:
- celle
- splitt
- tabell
- datagrid
- TableCellsSplitFill
variant: Fill
created_at: 26.10.2026
+1 -4
View File
@@ -2,9 +2,6 @@ name: TableCross
category: Interface
sub_category: Table
keywords:
- tabell
- datagrid
- fjern
- slett
- TableCross
variant: Stroke
created_at: 26.10.2026
+1 -4
View File
@@ -2,9 +2,6 @@ name: TableCrossFill
category: Interface
sub_category: Table
keywords:
- tabell
- datagrid
- fjern
- slett
- TableCrossFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableDeleteColumn
category: Interface
sub_category: Table
keywords:
- slett kolonne
- tabell
- datagrid
- fjern
- TableDeleteColumn
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableDeleteColumnFill
category: Interface
sub_category: Table
keywords:
- slett kolonne
- tabell
- datagrid
- fjern
- TableDeleteColumnFill
variant: Fill
created_at: 26.10.2026
+1 -4
View File
@@ -2,9 +2,6 @@ name: TableDeleteRow
category: Interface
sub_category: Table
keywords:
- slett rad
- tabell
- datagrid
- fjern
- TableDeleteRow
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableDeleteRowFill
category: Interface
sub_category: Table
keywords:
- slett rad
- tabell
- datagrid
- fjern
- TableDeleteRowFill
variant: Fill
created_at: 26.10.2026
+1 -2
View File
@@ -2,7 +2,6 @@ name: TableGrid
category: Interface
sub_category: Table
keywords:
- tabell
- datagrid
- TableGrid
variant: Stroke
created_at: 26.10.2026
+1 -2
View File
@@ -2,7 +2,6 @@ name: TableGridFill
category: Interface
sub_category: Table
keywords:
- tabell
- datagrid
- TableGridFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertColumnLeft
category: Interface
sub_category: Table
keywords:
- ny kolonne
- venstre
- tabell
- datagrid
- TableInsertColumnLeft
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertColumnLeftFill
category: Interface
sub_category: Table
keywords:
- ny kolonne
- venstre
- tabell
- datagrid
- TableInsertColumnLeftFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertColumnRight
category: Interface
sub_category: Table
keywords:
- ny kolonne
- høyre
- tabell
- datagrid
- TableInsertColumnRight
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertColumnRightFill
category: Interface
sub_category: Table
keywords:
- ny kolonne
- høyre
- tabell
- datagrid
- TableInsertColumnRightFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertRowAbove
category: Interface
sub_category: Table
keywords:
- ny rad
- over
- tabell
- datagrid
- TableInsertRowAbove
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertRowAboveFill
category: Interface
sub_category: Table
keywords:
- ny rad
- over
- tabell
- datagrid
- TableInsertRowAboveFill
variant: Fill
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertRowBelow
category: Interface
sub_category: Table
keywords:
- ny rad
- under
- tabell
- datagrid
- TableInsertRowBelow
variant: Stroke
created_at: 26.10.2026
@@ -2,9 +2,6 @@ name: TableInsertRowBelowFill
category: Interface
sub_category: Table
keywords:
- ny rad
- under
- tabell
- datagrid
- TableInsertRowBelowFill
variant: Fill
created_at: 26.10.2026
+1 -4
View File
@@ -2,9 +2,6 @@ name: TablePlus
category: Interface
sub_category: Table
keywords:
- tabell
- legg til
- ny
- datagrid
- TablePlus
variant: Stroke
created_at: 26.10.2026
+1 -4
View File
@@ -2,9 +2,6 @@ name: TablePlusFill
category: Interface
sub_category: Table
keywords:
- tabell
- legg til
- ny
- datagrid
- TablePlusFill
variant: Fill
created_at: 26.10.2026
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-icons",
"version": "8.22.0",
"version": "8.21.0",
"author": "Aksel | Nav",
"homepage": "https://aksel.nav.no/ikoner",
"repository": {
@@ -91,6 +91,6 @@
"tsx": "^4.23.15",
"typescript": "6.0.3",
"unified": "11.0.5",
"vitest": "5.0.5"
"vitest": "4.1.11"
}
}
-2
View File
@@ -1,7 +1,5 @@
# @navikt/aksel-stylelint
## 8.22.0
## 8.21.0
## 8.20.1
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-stylelint",
"version": "8.22.0",
"version": "8.21.0",
"type": "module",
"engines": {
"node": ">=18.12.0"
@@ -43,13 +43,13 @@
"dev": "yarn watch:lint"
},
"devDependencies": {
"@navikt/ds-css": "^8.22.0",
"@navikt/ds-tokens": "^8.22.0",
"@navikt/ds-css": "^8.21.0",
"@navikt/ds-tokens": "^8.21.0",
"concurrently": "10.0.6",
"postcss-selector-parser": "^7.1.7",
"postcss-value-parser": "^4.2.0",
"stylelint": "^17.15.0",
"stylelint-test-rule-node": "^1.3.0",
"stylelint-test-rule-node": "^1.2.0",
"tsx": "^4.23.15",
"typescript": "6.0.3"
}
-2
View File
@@ -1,7 +1,5 @@
# @navikt/aksel
## 8.22.0
## 8.21.0
## 8.20.1
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel",
"version": "8.22.0",
"version": "8.21.0",
"description": "Aksel command line interface. Codemods and other utilities for Aksel users.",
"author": "Aksel | Nav designsystem team",
"license": "MIT",
@@ -58,7 +58,7 @@
"@types/lodash": "4.17.25",
"rimraf": "6.1.3",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"sideEffects": false,
"engines": {
-2
View File
@@ -1,7 +1,5 @@
# @navikt/ds-css
## 8.22.0
## 8.21.0
### Minor Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "8.22.0",
"version": "8.21.0",
"description": "CSS for Nav Designsystem",
"author": "Aksel | Nav designsystem team",
"keywords": [
@@ -32,7 +32,7 @@
"css:get-version": "node config/get-version.js"
},
"devDependencies": {
"@navikt/ds-tokens": "^8.22.0",
"@navikt/ds-tokens": "^8.21.0",
"browserslist": "^4.28.7",
"esbuild": "^0.28.2",
"fast-glob": "3.3.3",
-18
View File
@@ -1,23 +1,5 @@
# @navikt/ds-react
## 8.22.0
### Patch Changes
- Combobox: The list is no longer focusable ([#5490](https://github.com/navikt/aksel/pull/5490))
- Popover: Closed popovers no longer calculate their position on mount. This makes pages with many Dropdowns or HelpTexts render faster. ([#5474](https://github.com/navikt/aksel/pull/5474))
- ESM: Mark ESM output as side-effect free, so bundlers like webpack, Turbopack and esbuild can tree-shake unused components and icons. ([#5472](https://github.com/navikt/aksel/pull/5472))
- MonthPicker: Arrow-key navigation no longer freezes the page when no later or earlier month is enabled. Keyboard search now respects `fromDate`/`toDate` with both caption types and looks at most 100 years ahead or back. ([#5477](https://github.com/navikt/aksel/pull/5477))
- Date utilities: Import date-fns functions and locales from their own paths, so unbundled Node imports (SSR, Vitest/Jest) no longer load every date-fns locale. ([#5476](https://github.com/navikt/aksel/pull/5476))
- Updated dependencies [[`16da3ce`](https://github.com/navikt/aksel/commit/16da3ce770041acc41589fcdd087717fab027126), [`b69c5fc`](https://github.com/navikt/aksel/commit/b69c5fca305f28ad99b48dd74e4f736fe4257d48)]:
- @navikt/aksel-icons@8.22.0
- @navikt/ds-tokens@8.22.0
## 8.21.0
### Minor Changes
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "8.22.0",
"version": "8.21.0",
"description": "React components from the Norwegian Labour and Welfare Administration.",
"author": "Aksel, a team part of the Norwegian Labour and Welfare Administration.",
"license": "MIT",
@@ -788,8 +788,8 @@
"dependencies": {
"@floating-ui/react": "0.27.20",
"@floating-ui/react-dom": "^2.1.9",
"@navikt/aksel-icons": "^8.22.0",
"@navikt/ds-tokens": "^8.22.0",
"@navikt/aksel-icons": "^8.21.0",
"@navikt/ds-tokens": "^8.21.0",
"date-fns": "^4.0.0",
"react-day-picker": "10.0.2"
},
@@ -806,7 +806,7 @@
"copyfiles": "^2.4.1",
"cross-env": "^10.1.0",
"jscodeshift": "17.4.0",
"jsdom": "30.1.3",
"jsdom": "29.1.1",
"react": "19.3.1",
"react-dom": "19.3.1",
"rimraf": "6.1.3",
@@ -814,7 +814,7 @@
"tsc-alias": "1.9.7",
"tsx": "^4.23.15",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"peerDependencies": {
"@types/react": "^17.0.30 || ^18 || ^19",
@@ -5,7 +5,9 @@ import { type GridCache, buildTableGridMap } from "../helpers/table-grid-nav";
/**
* Manages the table grid cache and observes DOM changes that require grid rebuilding.
* Watches for structural changes (rows/cells added/removed) and attribute changes
* (colspan, rowspan, hidden, style) that affect grid layout and focusability.
* (colspan, rowspan, hidden) that affect grid layout.
* Inline `style` is intentionally not observed: focus navigation writes
* scroll-margin on every move, and the grid never reads styles.
*/
function useGridCache(tableRef: HTMLTableElement | null, enabled: boolean) {
const gridCacheRef = useRef<GridCache>({
@@ -34,7 +36,7 @@ function useGridCache(tableRef: HTMLTableElement | null, enabled: boolean) {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["colspan", "rowspan", "hidden", "style"],
attributeFilter: ["colspan", "rowspan", "hidden"],
});
return () => {
@@ -343,21 +343,18 @@ export const EnterNotSubmittingForm: StoryObj<{
args: {
onSubmit: fn(),
},
render: ({ onSubmit }) => (
<form
onSubmit={(event) => {
event.preventDefault();
onSubmit(event);
}}
>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
allowNewValues
/>
</form>
),
render: ({ onSubmit }) => {
return (
<form action="https://www.aksel.nav.no" method="get" onSubmit={onSubmit}>
<UNSAFE_Combobox
options={options}
label="Hva er dine favorittfrukter?"
isMultiSelect
allowNewValues
/>
</form>
);
},
play: async ({ canvasElement, args }) => {
args.onSubmit.mockClear();
const canvas = within(canvasElement);
@@ -115,7 +115,6 @@ const FilteredOptions = () => {
ref={setFilteredOptionsRef}
// biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: The <ul> element acts as a listbox in the combobox.
role="listbox"
tabIndex={-1}
className="aksel-combobox__list-options"
>
{isValueNew && !maxSelected.isLimitReached && allowNewValues && (
@@ -1,6 +1,6 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import React, { useState } from "react";
import { afterEach, describe, expect, test, vi } from "vitest";
import { describe, expect, test } from "vitest";
import { Button } from "../../button";
import { Modal } from "../index";
@@ -18,10 +18,6 @@ const Test = () => {
};
describe("Modal", () => {
afterEach(() => {
vi.restoreAllMocks();
});
test("should be visible", async () => {
render(<Test />);
expect(await screen.findByText("Foobar")).toBeVisible();
@@ -33,37 +29,25 @@ describe("Modal", () => {
expect(screen.getByText("Foobar")).not.toBeVisible();
});
test.each([false, true])(
"should toggle scroll lock (scrollbar-gutter support: %s)",
async (supportsScrollbarGutter) => {
vi.spyOn(CSS, "supports").mockReturnValue(supportsScrollbarGutter);
render(<Test />);
test("should toggle scroll lock", async () => {
render(<Test />);
const lockedElement = supportsScrollbarGutter
? document.body
: document.documentElement;
await waitFor(() => {
expect(document.documentElement.style.overflowX).toBe("hidden");
});
await waitFor(() => {
expect(document.documentElement.style.overflowY).toBe("hidden");
});
await waitFor(() => {
expect(document.documentElement.style.scrollBehavior).toBe("unset");
});
await waitFor(() => {
expect(document.documentElement.style.scrollbarGutter).toBe("stable");
});
await waitFor(() => {
expect(lockedElement.style.overflowX).toBe("hidden");
});
await waitFor(() => {
expect(lockedElement.style.overflowY).toBe("hidden");
});
await waitFor(() => {
expect(document.documentElement.style.scrollBehavior).toBe(
supportsScrollbarGutter ? "" : "unset",
);
});
await waitFor(() => {
expect(document.documentElement.style.scrollbarGutter).toBe("stable");
});
fireEvent.click(screen.getByText("Close"));
await waitFor(() => {
expect(document.documentElement.style.cssText).toBe("");
expect(lockedElement.style.overflowX).toBe("");
expect(lockedElement.style.overflowY).toBe("");
});
},
);
fireEvent.click(screen.getByText("Close"));
await waitFor(() => {
expect(document.documentElement.style.cssText).toBe("");
});
});
});
@@ -83,25 +83,6 @@ export const DisabledMonths = () => (
/>
);
/**
* Only June is enabled. ArrowRight/ArrowLeft on June keeps focus on June instead
* of searching forever. Keyboard search stops at the
* fromDate/toDate years, or after 100 years when no bounds are set.
*/
export const KeyboardNoEnabledMonth = () => (
<div>
<p>Focus June and press ArrowRight or ArrowLeft. Focus stays on June.</p>
<MonthPicker.Standalone
defaultSelected={new Date(year, 5, 1)}
disabled={[
(date) => !(date.getFullYear() === year && date.getMonth() === 5),
]}
fromDate={new Date(year, 0, 1)}
toDate={new Date(year, 11, 1)}
/>
</div>
);
export const Standalone = () => {
return <MonthPicker.Standalone defaultSelected={new Date(`Jan 1 ${year}`)} />;
};
@@ -1,108 +0,0 @@
import { isSameMonth } from "date-fns/isSameMonth";
import { describe, expect, test, vi } from "vitest";
import { nextEnabled } from "./MonthPicker.util";
const months = Array.from({ length: 12 }, (_, i) => new Date(2024, i, 1));
const june2024 = new Date(2024, 5, 1);
/* Disables every month except `enabled`. Throws instead of hanging if the search becomes unbounded. */
const onlyEnabled = (...enabled: Date[]) => {
let calls = 0;
return (date: Date) => {
calls += 1;
if (calls > 5000) {
throw new Error("Month search did not terminate");
}
return !enabled.some((month) => isSameMonth(month, date));
};
};
const search = (
key: string,
disabled: (date: Date) => boolean,
options: { dropdownCaption?: boolean; fromDate?: Date; toDate?: Date } = {},
) => {
const setYearState = vi.fn();
const result = nextEnabled(
months,
key,
[disabled],
june2024,
setYearState,
june2024,
options.dropdownCaption ?? false,
options.fromDate,
options.toDate,
);
return { result, setYearState };
};
describe("nextEnabled", () => {
test.each(["ArrowRight", "ArrowLeft", "ArrowDown", "ArrowUp"])(
"keeps focus when no month is enabled in direction (%s, no bounds)",
(key) => {
const { result, setYearState } = search(key, onlyEnabled(june2024));
expect(result).toEqual(june2024);
expect(setYearState).not.toHaveBeenCalled();
},
);
test.each([false, true])(
"stops at fromDate/toDate years (dropdownCaption: %s)",
(dropdownCaption) => {
const bounds = {
dropdownCaption,
fromDate: new Date(2023, 0, 1),
toDate: new Date(2025, 11, 1),
};
const disabled = onlyEnabled(
june2024,
new Date(2022, 5, 1),
new Date(2026, 5, 1),
);
for (const key of ["ArrowRight", "ArrowLeft"]) {
const { result, setYearState } = search(key, disabled, bounds);
expect(result).toEqual(june2024);
expect(setYearState).not.toHaveBeenCalled();
}
},
);
test("skips disabled months/years and moves to the next enabled year", () => {
const target = new Date(2027, 2, 1);
const { result, setYearState } = search(
"ArrowRight",
onlyEnabled(june2024, target),
);
expect(result).toEqual(target);
expect(setYearState).toHaveBeenCalledTimes(1);
expect(setYearState.mock.calls[0][0].getFullYear()).toBe(2027);
});
test("finds previous enabled month within bounds", () => {
const target = new Date(2023, 10, 1);
const { result, setYearState } = search(
"ArrowLeft",
onlyEnabled(june2024, target),
{ fromDate: new Date(2023, 0, 1) },
);
expect(result).toEqual(target);
expect(setYearState.mock.calls[0][0].getFullYear()).toBe(2023);
});
test("searches at most 100 years without bounds", () => {
const within = new Date(2124, 0, 1);
expect(search("ArrowRight", onlyEnabled(june2024, within)).result).toEqual(
within,
);
const beyond = new Date(2125, 0, 1);
expect(search("ArrowRight", onlyEnabled(june2024, beyond)).result).toEqual(
june2024,
);
});
});
@@ -56,14 +56,14 @@ export const nextEnabled = (
}
}
if (key === "ArrowRight") {
const nextMonth = searchEnabledMonth(
1,
const nextMonth = loopForward(
currentIndex,
months,
disabled,
yearState,
setYearState,
disabled,
false,
dropdownCaption,
fromDate,
toDate,
);
@@ -72,14 +72,14 @@ export const nextEnabled = (
}
}
if (key === "ArrowLeft") {
const prevMonth = searchEnabledMonth(
-1,
currentIndex,
const prevMonth = loopBack(
currentIndex - 1,
months,
disabled,
yearState,
setYearState,
false,
dropdownCaption,
fromDate,
toDate,
);
@@ -98,14 +98,14 @@ export const nextEnabled = (
return setYear(months[currentIndex + 4], yearState.getFullYear());
}
const fallbackNext = searchEnabledMonth(
1,
const fallbackNext = loopForward(
currentIndex,
months,
disabled,
yearState,
setYearState,
disabled,
true,
dropdownCaption,
fromDate,
toDate,
);
@@ -127,14 +127,14 @@ export const nextEnabled = (
)
)
return setYear(months[currentIndex - 4], Number(yearState.getFullYear()));
const fallbackPrev = searchEnabledMonth(
-1,
const fallbackPrev = loopBack(
currentIndex,
months,
disabled,
yearState,
setYearState,
true,
dropdownCaption,
fromDate,
toDate,
);
@@ -144,59 +144,90 @@ export const nextEnabled = (
return currentMonth;
};
/**
* Keyboard search for an enabled month never crosses fromDate/toDate years and
* gives up after this many years when no bounds are set, so a matcher that
* disables every remaining month cannot hang the page.
*/
const MAX_SEARCH_YEARS = 100;
const searchEnabledMonth = (
direction: 1 | -1,
const loopBack = (
currentIndex: number,
months: Date[],
disabled: Matcher[],
yearState: Date,
setYearState: (date: Date) => void,
rowCheck: boolean,
dropdownCaption: boolean,
fromDate?: Date,
toDate?: Date,
): { index: number; year: number } | undefined => {
const currentYear = yearState.getFullYear();
if (Number.isNaN(currentYear)) {
return;
}
const boundYear =
direction === 1 ? toDate?.getFullYear() : fromDate?.getFullYear();
const horizonYear = currentYear + direction * MAX_SEARCH_YEARS;
const lastYear = !boundYear
? horizonYear
: direction === 1
? Math.min(boundYear, horizonYear)
: Math.max(boundYear, horizonYear);
let nextYear = currentYear;
let monthIndex = currentIndex;
while (true) {
monthIndex += direction;
if (monthIndex < 0 || monthIndex > 11) {
if (nextYear === lastYear || (nextYear - lastYear) * direction > 0) {
let currentYear = setYear(yearState, Number(yearState.getFullYear()));
for (let i = currentIndex; i >= -1; i--) {
if (i === -1) {
if (
isOutOfRange(
dropdownCaption,
setYear(currentYear, Number(currentYear.getFullYear() - 1)),
fromDate,
toDate,
)
)
return;
}
nextYear += direction;
monthIndex = direction === 1 ? 0 : 11;
currentYear = setYear(currentYear, Number(currentYear.getFullYear() - 1));
setYearState(currentYear);
i = 11;
}
const month = months[i];
const isDisabled = !isMatch(
setYear(month, Number(currentYear.getFullYear())),
disabled,
);
if (rowCheck) {
if (isDisabled && getRow(i) !== getRow(currentIndex)) {
return { index: i, year: Number(currentYear.getFullYear()) };
}
} else {
if (isDisabled) {
return { index: i, year: Number(currentYear.getFullYear()) };
}
}
}
};
const isEnabled = !isMatch(setYear(months[monthIndex], nextYear), disabled);
if (
isEnabled &&
(!rowCheck || getRow(monthIndex) !== getRow(currentIndex))
) {
if (nextYear !== currentYear) {
setYearState(setYear(yearState, nextYear));
const loopForward = (
currentIndex: number,
months: Date[],
yearState: Date,
setYearState: (date: Date) => void,
disabled: Matcher[],
rowCheck: boolean,
dropdownCaption: boolean,
fromDate?: Date,
toDate?: Date,
): { index: number; year: number } | undefined => {
let currentYear = setYear(yearState, Number(yearState.getFullYear()));
for (let i = currentIndex + 1; i < months.length + 1; i++) {
if (i === 12) {
if (
isOutOfRange(
dropdownCaption,
setYear(currentYear, Number(currentYear.getFullYear() + 1)),
fromDate,
toDate,
)
)
return;
currentYear = setYear(currentYear, Number(currentYear.getFullYear() + 1));
setYearState(currentYear);
i = 0;
}
const month = months[i];
const isDisabled = !isMatch(
setYear(month, Number(currentYear.getFullYear())),
disabled,
);
if (rowCheck) {
if (isDisabled && getRow(i) !== getRow(currentIndex)) {
return { index: i, year: Number(currentYear.getFullYear()) };
}
} else {
if (isDisabled) {
return { index: i, year: Number(currentYear.getFullYear()) };
}
return { index: monthIndex, year: nextYear };
}
}
};
@@ -207,6 +238,25 @@ const getRow = (index: number): number => {
return 3;
};
const isOutOfRange = (
dropdownCaption: boolean,
year: Date,
fromDate?: Date,
toDate?: Date,
): boolean => {
if (
dropdownCaption &&
fromDate &&
toDate &&
(year.getFullYear() < fromDate?.getFullYear() ||
year.getFullYear() > toDate?.getFullYear())
) {
return true;
}
return false;
};
const nextOnRow = (
currentIndex: number,
months: Date[],
@@ -123,13 +123,9 @@ const PopoverRoot = forwardRef<HTMLDivElement, PopoverProps>(
],
});
/**
* Only give Floating UI a reference while open. Otherwise every closed instance
* computes (and commits) a position
*/
useClientLayoutEffect(() => {
refs.setReference(open ? anchorEl : null);
}, [anchorEl, open, refs]);
refs.setReference(anchorEl);
}, [anchorEl, refs]);
const floatingRef = useMergeRefs(refs.setFloating, ref);
@@ -1,6 +1,6 @@
import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import { describe, test } from "vitest";
import { bench, describe } from "vitest";
import { HStack, VStack } from "../stack";
import { Box } from "./Box";
@@ -15,86 +15,82 @@ import { Box } from "./Box";
*/
describe("Box – single element", () => {
test("render throughput", async ({ bench }) => {
await bench("bare (no props)", () => {
renderToStaticMarkup(<Box>Hei</Box>);
}).run();
bench("bare (no props)", () => {
renderToStaticMarkup(<Box>Hei</Box>);
});
await bench("styling props only (background/border/radius/shadow)", () => {
renderToStaticMarkup(
<Box
background="neutral-soft"
borderColor="neutral-subtle"
borderWidth="1"
borderRadius="12"
shadow="dialog"
>
Hei
</Box>,
);
}).run();
bench("styling props only (background/border/radius/shadow)", () => {
renderToStaticMarkup(
<Box
background="neutral-soft"
borderColor="neutral-subtle"
borderWidth="1"
borderRadius="12"
shadow="dialog"
>
Hei
</Box>,
);
});
await bench("single responsive/primitive prop (padding)", () => {
renderToStaticMarkup(<Box padding="space-16">Hei</Box>);
}).run();
bench("single responsive/primitive prop (padding)", () => {
renderToStaticMarkup(<Box padding="space-16">Hei</Box>);
});
await bench("many primitive props (padding/margin/width/position/inset)", () => {
renderToStaticMarkup(
<Box
padding="space-16"
margin="space-8"
width="200px"
maxWidth="400px"
position="relative"
inset="space-4"
>
Hei
</Box>,
);
}).run();
bench("many primitive props (padding/margin/width/position/inset)", () => {
renderToStaticMarkup(
<Box
padding="space-16"
margin="space-8"
width="200px"
maxWidth="400px"
position="relative"
inset="space-4"
>
Hei
</Box>,
);
});
await bench("responsive object prop (padding per breakpoint)", () => {
renderToStaticMarkup(
<Box
padding={{
xs: "space-8",
sm: "space-12",
md: "space-16",
lg: "space-20",
xl: "space-24",
}}
>
Hei
</Box>,
);
}).run();
bench("responsive object prop (padding per breakpoint)", () => {
renderToStaticMarkup(
<Box
padding={{
xs: "space-8",
sm: "space-12",
md: "space-16",
lg: "space-20",
xl: "space-24",
}}
>
Hei
</Box>,
);
});
await bench("asChild (Slot merge path)", () => {
renderToStaticMarkup(
<Box padding="space-16" asChild>
<section>Hei</section>
</Box>,
);
}).run();
bench("asChild (Slot merge path)", () => {
renderToStaticMarkup(
<Box padding="space-16" asChild>
<section>Hei</section>
</Box>,
);
});
});
describe("Box – realistic tree (24 children)", () => {
const children = Array.from({ length: 24 }, (_, i) => i);
test("render throughput", async ({ bench }) => {
await bench("VStack > Box grid of cards", () => {
renderToStaticMarkup(
<VStack gap="space-16">
{children.map((i) => (
<HStack key={i} gap="space-8" align="center">
<Box padding="space-16" background="neutral-soft" borderRadius="8">
Card {i}
</Box>
</HStack>
))}
</VStack>,
);
}).run();
bench("VStack > Box grid of cards", () => {
renderToStaticMarkup(
<VStack gap="space-16">
{children.map((i) => (
<HStack key={i} gap="space-8" align="center">
<Box padding="space-16" background="neutral-soft" borderRadius="8">
Card {i}
</Box>
</HStack>
))}
</VStack>,
);
});
});
@@ -8,9 +8,6 @@ interface ListboxInputSlotProps {
virtuallyFocusedOptionId: string;
}
/**
* Remember that role=combobox requires aria-expanded
*/
const ListboxInputSlot = ({
children,
virtuallyFocusedOptionId,
@@ -1,6 +1,6 @@
import { renderHook } from "@testing-library/react";
import React from "react";
import { describe, test } from "vitest";
import { bench, describe } from "vitest";
import { Provider } from "../../provider";
import { get } from "./get";
import { useI18n } from "./i18n.hooks";
@@ -8,16 +8,14 @@ import type { ComponentTranslation } from "./i18n.types";
import { nb } from "./locales";
describe("translate function throughput", () => {
test("translation lookups", async ({ bench }) => {
const { result } = renderHook(() => useI18n("FileUpload"));
const { result } = renderHook(() => useI18n("FileUpload"));
await bench("simple key lookup (no replacements)", () => {
result.current("item.uploading");
}).run();
bench("simple key lookup (no replacements)", () => {
result.current("item.uploading");
});
await bench("key lookup with replacements", () => {
result.current("item.uploading", { name: "Test", count: 5 } as never);
}).run();
bench("key lookup with replacements", () => {
result.current("item.uploading", { name: "Test", count: 5 } as never);
});
});
@@ -25,13 +23,10 @@ describe("translate with local overrides", () => {
const local = {
item: { uploading: "Hello {name}, you have {count} files" },
};
const { result } = renderHook(() => useI18n("FileUpload", local));
test("local override lookup", async ({ bench }) => {
const { result } = renderHook(() => useI18n("FileUpload", local));
await bench("local override with replacements", () => {
result.current("item.uploading", { name: "Test", count: 5 });
}).run();
bench("local override with replacements", () => {
result.current("item.uploading", { name: "Test", count: 5 });
});
});
@@ -43,21 +38,18 @@ describe("translate with multiple context objects", () => {
{children}
</Provider>
);
const { result } = renderHook(() => useI18n("FileUpload"), { wrapper });
test("context lookups", async ({ bench }) => {
const { result } = renderHook(() => useI18n("FileUpload"), { wrapper });
bench("hit in first context object", () => {
result.current("dropzone.button");
});
await bench("hit in first context object", () => {
result.current("dropzone.button");
}).run();
bench("hit in second context object", () => {
result.current("item.uploading");
});
await bench("hit in second context object", () => {
result.current("item.uploading");
}).run();
await bench("fallback to locale default", () => {
result.current("item.downloading");
}).run();
bench("fallback to locale default", () => {
result.current("item.downloading");
});
});
@@ -69,21 +61,19 @@ describe("get() function throughput", () => {
nb.FileUpload,
];
test("translation lookup", async ({ bench }) => {
await bench("shallow key hit in first object", () => {
get("item.uploading", objects);
}).run();
bench("shallow key hit in first object", () => {
get("item.uploading", objects);
});
await bench("key hit in second object (skip first)", () => {
get("item.downloading", objects);
}).run();
bench("key hit in second object (skip first)", () => {
get("item.downloading", objects);
});
await bench("deep fallback to last object", () => {
get("dropzone.button", objects);
}).run();
bench("deep fallback to last object", () => {
get("dropzone.button", objects);
});
await bench("long key dot notation parsing", () => {
get("dropzone.dragAndDropMultiple", [nb.FileUpload]);
}).run();
bench("long key dot notation parsing", () => {
get("dropzone.dragAndDropMultiple", [nb.FileUpload]);
});
});
@@ -6,7 +6,6 @@ export default defineConfig({
globals: true,
setupFiles: "./tests/setup.ts",
environment: "jsdom",
pool: "vmThreads",
typecheck: {
enabled: true,
},
-2
View File
@@ -1,7 +1,5 @@
# @navikt/ds-tailwind
## 8.22.0
## 8.21.0
## 8.20.1
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "8.22.0",
"version": "8.21.0",
"description": "Tailwind config based on @navikt/ds-tokens",
"author": "Aksel | Nav designsystem team",
"keywords": [
@@ -28,12 +28,12 @@
},
"homepage": "https://aksel.nav.no/grunnleggende/kode/tailwind/",
"devDependencies": {
"@navikt/ds-tokens": "^8.22.0",
"@navikt/ds-tokens": "^8.21.0",
"@types/node": "^24.10.9",
"tailwindcss": "^4.3.3",
"tailwindcss": "^3.3.3",
"tsx": "^4.23.15",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"publishConfig": {
"access": "public",
-2
View File
@@ -1,7 +1,5 @@
# @navikt/ds-tokens
## 8.22.0
## 8.21.0
## 8.20.1
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "8.22.0",
"version": "8.21.0",
"description": "Design-tokens for Nav designsystem",
"author": "Aksel | Nav designsystem team",
"keywords": [
@@ -34,7 +34,7 @@
},
"homepage": "https://aksel.nav.no/grunnleggende/styling/design-tokens/",
"devDependencies": {
"@figma/plugin-typings": "^1.142.0",
"@figma/plugin-typings": "^1.131.0",
"@types/lodash": "4.17.25",
"colorjs.io": "^0.7.1",
"esbuild": "^0.28.2",
@@ -43,7 +43,7 @@
"style-dictionary": "^5.5.5",
"tsx": "^4.23.15",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"publishConfig": {
"access": "public",
-20
View File
@@ -1,25 +1,5 @@
# Changelog
## 8.22.0
### @navikt/aksel-icons
- Icons: New icons `Gift`, `ArrowsPointingIn` and `ArrowsPointingOut`. ([#5484](https://github.com/navikt/aksel/pull/5484))
* ESM: Mark ESM output as side-effect free, so bundlers like webpack, Turbopack and esbuild can tree-shake unused components and icons. ([#5472](https://github.com/navikt/aksel/pull/5472))
### @navikt/ds-react
- Combobox: The list is no longer focusable ([#5490](https://github.com/navikt/aksel/pull/5490))
- Popover: Closed popovers no longer calculate their position on mount. This makes pages with many Dropdowns or HelpTexts render faster. ([#5474](https://github.com/navikt/aksel/pull/5474))
- ESM: Mark ESM output as side-effect free, so bundlers like webpack, Turbopack and esbuild can tree-shake unused components and icons. ([#5472](https://github.com/navikt/aksel/pull/5472))
- MonthPicker: Arrow-key navigation no longer freezes the page when no later or earlier month is enabled. Keyboard search now respects `fromDate`/`toDate` with both caption types and looks at most 100 years ahead or back. ([#5477](https://github.com/navikt/aksel/pull/5477))
- Date utilities: Import date-fns functions and locales from their own paths, so unbundled Node imports (SSR, Vitest/Jest) no longer load every date-fns locale. ([#5476](https://github.com/navikt/aksel/pull/5476))
## 8.21.0
### @navikt/aksel-icons
-8
View File
@@ -37,14 +37,6 @@ yarn build:next
yarn serve:next
```
`yarn build:next` genererer ikke RSS-feeden og bygger ikke Playroom. Kjør dette for å bygge alt:
```bash
yarn workspace website update:rss
yarn workspace website build:with-playroom
yarn serve:next
```
**Rettigheter**
Sanity-datasettet er privat, noe som betyr du må ha tilgang til Sanity-applikasjonen og følgende tokens:
+6 -6
View File
@@ -11,11 +11,11 @@
"sanity:update": "yarn workspace website update:sanity"
},
"dependencies": {
"@navikt/aksel": "^8.22.0",
"@navikt/aksel-icons": "^8.22.0",
"@navikt/ds-css": "^8.22.0",
"@navikt/ds-react": "^8.22.0",
"@navikt/ds-tailwind": "^8.22.0",
"@navikt/ds-tokens": "^8.22.0"
"@navikt/aksel": "^8.21.0",
"@navikt/aksel-icons": "^8.21.0",
"@navikt/ds-css": "^8.21.0",
"@navikt/ds-react": "^8.21.0",
"@navikt/ds-tailwind": "^8.21.0",
"@navikt/ds-tokens": "^8.21.0"
}
}
+1 -1
View File
@@ -46,7 +46,7 @@
"@types/react": "19.2.14",
"tsx": "^4.23.15",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"exports": {
"./schema": {
@@ -1,7 +1,7 @@
"use client";
import { useEffect, useMemo, useRef, useState } from "react";
import { Masonry } from "react-responsive-masonry";
import Masonry from "react-responsive-masonry";
import { Box, HGrid, Heading } from "@navikt/ds-react";
import { useMedia } from "@/app/_ui/utils/hooks/useMedia";
import Card, { type ArticleT } from "./FrontpageMasonryCard";
+3 -1
View File
@@ -1,3 +1,4 @@
import BundleAnalyzer from "@next/bundle-analyzer";
import type { NextConfig } from "next";
import { sanity } from "next-sanity/live/cache-life";
import path from "node:path";
@@ -172,4 +173,5 @@ const nextConfig: NextConfig = {
serverExternalPackages: ["@navikt/next-logger", "next-logger", "pino"],
};
module.exports = nextConfig;
module.exports =
process.env.ANALYZE === "true" ? BundleAnalyzer()(nextConfig) : nextConfig;
+8 -9
View File
@@ -6,8 +6,7 @@
"author": "Aksel | Nav designsystem team",
"scripts": {
"dev": "next | pino-pretty --messageKey=message",
"build": "yarn next build && yarn cp:assets",
"build:with-playroom": "concurrently \"yarn workspace aksel-playroom build:playroom\" \"yarn next build\" && yarn cp:assets:with-playroom",
"build": "concurrently \"yarn workspace aksel-playroom build:playroom\" \"yarn next build\" \"yarn update:rss\" && yarn cp:assets",
"start": "cd .next/standalone/aksel.nav.no/website && PORT=3000 HOSTNAME=0.0.0.0 node server.js",
"e2e:dev": "yarn generate-testpaths && playwright test --ui",
"e2e:docker": "yarn generate-testpaths && playwright test",
@@ -18,7 +17,7 @@
"update:changelog": "yarn tsx --env-file-if-exists=.env ./scripts/changelog",
"update:stats": "yarn tsx --env-file-if-exists=.env ./scripts/update-stats/update-stats",
"update:sanity": "yarn update:metadata && yarn update:eksempler && yarn update:changelog && yarn update:stats",
"analyze": "next analyze",
"analyze": "cross-env ANALYZE=true yarn build",
"test": "vitest run -c config/vitest.config.ts",
"test:watch": "vitest watch -c config/vitest.config.ts",
"playwright": "playwright test",
@@ -27,8 +26,7 @@
"cp:playroom": "copyfiles -E -u 5 '../../apps/playroom/dist/sandbox/**' public/",
"cp:static": "copyfiles -E -u 1 '.next/static/**' .next/standalone/aksel.nav.no/website/.next/",
"cp:public": "copyfiles -E 'public/**' .next/standalone/aksel.nav.no/website/",
"cp:assets": "yarn cp:public && yarn cp:static",
"cp:assets:with-playroom": "yarn cp:playroom && yarn cp:assets"
"cp:assets": "yarn cp:playroom && yarn cp:public && yarn cp:static"
},
"dependencies": {
"@navikt/analytics-types": "0.0.9",
@@ -50,13 +48,13 @@
"next-logger": "^5.0.2",
"next-sanity": "13.2.3",
"next-themes": "^0.4.6",
"pino": "^10.4.0",
"pino": "^10.3.1",
"prism-react-renderer": "^2.0.0",
"react": "19.3.1",
"react-dom": "19.3.1",
"react-hook-form": "^7.90.0",
"react-markdown": "^9.0.1",
"react-responsive-masonry": "2.9.0",
"react-responsive-masonry": "2.7.2",
"react-snowfall": "^2.4.0",
"remark-gfm": "^4.0.0",
"rxjs": "^7.8.2",
@@ -74,6 +72,7 @@
"@babel/parser": "^7.27.5",
"@babel/traverse": "^7.27.4",
"@google-cloud/bigquery": "^9.5.0",
"@next/bundle-analyzer": "16.4.3",
"@next/eslint-plugin-next": "16.4.3",
"@playwright/test": "1.61.1",
"@portabletext/block-tools": "^6.0.0",
@@ -91,7 +90,7 @@
"concurrently": "10.0.6",
"copyfiles": "^2.4.1",
"cross-env": "^10.1.0",
"jsdom": "30.1.3",
"jsdom": "29.1.1",
"json5": "2.2.3",
"pino-pretty": "^13.1.3",
"rss": "^1.2.2",
@@ -99,6 +98,6 @@
"sitemapper": "^4.1.6",
"tsx": "^4.23.15",
"typescript": "6.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
}
}
+4 -4
View File
@@ -11,15 +11,15 @@
"preview": "vite preview"
},
"dependencies": {
"@navikt/aksel-icons": "^8.22.0",
"@navikt/ds-css": "^8.22.0",
"@navikt/ds-react": "^8.22.0",
"@navikt/aksel-icons": "^8.21.0",
"@navikt/ds-css": "^8.21.0",
"@navikt/ds-react": "^8.21.0",
"fuse.js": "7.4.2",
"react": "19.3.1",
"react-dom": "19.3.1"
},
"devDependencies": {
"@figma/plugin-typings": "^1.142.0",
"@figma/plugin-typings": "^1.131.0",
"@rollup/pluginutils": "^5.4.0",
"@svgr/core": "^8.1.0",
"@types/node": "^24.10.9",
+4 -4
View File
@@ -19,9 +19,9 @@
"devDependencies": {
"@modelcontextprotocol/inspector": "^2.11.0",
"@modelcontextprotocol/sdk": "^1.32.0",
"@navikt/aksel": "^8.22.0",
"@navikt/aksel-icons": "^8.22.0",
"@navikt/ds-tokens": "^8.22.0",
"@navikt/aksel": "^8.21.0",
"@navikt/aksel-icons": "^8.21.0",
"@navikt/ds-tokens": "^8.21.0",
"@sanity/client": "7.27.0",
"@types/express": "^5.0.3",
"@types/node": "^24.10.9",
@@ -31,7 +31,7 @@
"prom-client": "^15.1.3",
"tsdown": "^0.23.0",
"typescript": "6.0.3",
"vitest": "5.0.5",
"vitest": "4.1.11",
"zod": "^4.6.5"
}
}
+3 -3
View File
@@ -20,9 +20,9 @@
"typescript": "6.0.3"
},
"dependencies": {
"@navikt/aksel-icons": "^8.22.0",
"@navikt/ds-css": "^8.22.0",
"@navikt/ds-react": "^8.22.0",
"@navikt/aksel-icons": "^8.21.0",
"@navikt/ds-css": "^8.21.0",
"@navikt/ds-react": "^8.21.0",
"react": "19.3.1"
}
}
+6 -6
View File
@@ -92,10 +92,10 @@
"@types/node": "^24.10.9",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@vitest/browser": "5.0.5",
"@vitest/browser-playwright": "5.0.5",
"@vitest/coverage-v8": "5.0.5",
"@vitest/eslint-plugin": "1.6.28",
"@vitest/browser": "4.1.11",
"@vitest/browser-playwright": "4.1.11",
"@vitest/coverage-v8": "4.1.11",
"@vitest/eslint-plugin": "1.6.27",
"chromatic": "18.0.1",
"cross-env": "^10.1.0",
"eslint": "^9.39.2",
@@ -106,7 +106,7 @@
"eslint-plugin-storybook": "^10.6.3",
"eslint-plugin-testing-library": "^7.16.0",
"fast-glob": "3.3.3",
"globals": "^17.13.0",
"globals": "^17.7.0",
"husky": "^9.1.7",
"lint-staged": "17.6.0",
"playwright": "1.61.1",
@@ -124,7 +124,7 @@
"typescript-language-server": "6.0.0",
"vite": "^8.3.5",
"vite-plugin-turbosnap": "^1.0.3",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"packageManager": "yarn@4.18.0"
}
+1 -1
View File
@@ -14,7 +14,7 @@
"flat": "6.0.1",
"mlly": "1.8.2",
"tar": "^7.5.22",
"vitest": "5.0.5"
"vitest": "4.1.11"
},
"scripts": {
"run:analyze-npm-action": "yarn clean && concurrently \"yarn pack-remote && tsx ./src/runners/analyze-package.ts --remote --out trunk-results.json\" \"yarn pack-local && tsx ./src/runners/analyze-package.ts --out branch-results.json\"",
+598 -383
View File
File diff suppressed because it is too large. Load diff