Compare commits

...
Author SHA1 Message Date
Ken 82656da435 📝 Added comments 2026-04-27 09:57:48 +02:00
Ken ab9932ed8f 📝 Added comments 2026-04-27 09:55:47 +02:00
Ken 180ca25861 ⚡ Add cached parser for optimization 2026-04-24 13:38:51 +02:00
Ken cbac535fcb 📝 Add docs 2026-04-24 13:10:18 +02:00
Ken 296049b8c7 [DataTable] Optimize recursive parsing 2026-04-24 13:00:21 +02:00
Ken 073d811b3f [DataTable] Now supports branch selection 2026-04-24 12:45:15 +02:00
Ken da1374e833 [DataTable] Updated selection 2026-04-24 12:22:41 +02:00
Ken c0080e6729 [DataTable] Added play-test story 2026-04-24 12:20:59 +02:00
Ken dd1bc5241b [DataTable] Move prop-drilled value to context 2026-04-24 11:43:01 +02:00
Halvor Haugan 816f0fcaab DataTable: autoWidth prop 2026-04-24 10:14:20 +02:00
github-actions[bot] 9d9a5b9afe Version Packages (#4832)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-24 09:49:13 +02:00
Ken 90194d7d95 💄 Dialog now bottom-aligns on smaller breakpoint (#4831) 2026-04-24 09:44:13 +02:00
Ken 26b0bd2595 [LLM] Added llm route for codemod configs, optimized json strings in markdown 2026-04-23 22:46:41 +02:00
Ken 58f74b9a8f [DataTable] Expanded, loading and empty-state rows now have correct colSpan 2026-04-23 16:47:01 +02:00
Ken cf3b550e80 [LLM] Reduce thinking verbosity with instructions 2026-04-23 16:32:15 +02:00
Ken c8deba5677 [DataTable] Refactor expansionContext 2026-04-23 16:29:58 +02:00
Ken 16ffbc0209 [DataTable] Removed unused context-data 2026-04-23 16:15:05 +02:00
Ken 90caff2e7f [DataTable] Inline row-parsing in expandable row hook 2026-04-23 16:11:15 +02:00
Ken cd3afbfcaa [DataTable] Fix pagination demo 2026-04-23 16:07:44 +02:00
Ken 4d91935a3a [DataTable] Re-use parsed rowIds 2026-04-23 16:05:49 +02:00
Ken d92ffe5cc7 [LLM] Re add lines about thinking process and verbosity 2026-04-23 16:01:47 +02:00
Ken 2970c20d00 [LLM] Specify test instructions 2026-04-23 15:53:30 +02:00
Ken f48a6b9cc2 [LLM] Updated coped instructions 2026-04-23 15:37:24 +02:00
Ken 95dba94df4 [LLM] Added scoped instructions 2026-04-23 15:33:11 +02:00
Ken c5413d65c9 [LLM] Update root instruction 2026-04-23 15:09:10 +02:00
Ken 5884628710 [DataTable] Optimize item parsing with map 2026-04-23 14:30:42 +02:00
Ken c33cdad6e5 [DataTable] Refactor contract between rendring rows and sub-rows 2026-04-23 14:06:29 +02:00
Ken f7fdd35ff0 [DataTable] Still render rows without nesting 2026-04-23 12:51:09 +02:00
Ken 9a0f5dbf45 [DataTable] Remove old use of expansioncontext for nested rows 2026-04-23 12:20:30 +02:00
Ken fd0de677ad [DataTable] Refactor nested use of context 2026-04-23 12:15:02 +02:00
Ken bb709aeb35 [DataTable] Use new items context to render nested rows 2026-04-23 12:09:09 +02:00
Ken cac3c38cff [DataTable] ⚡ Optimize item parsing 2026-04-23 11:27:45 +02:00
Ken d4063849a8 [DataTable] ⚡ Memorize parsing 2026-04-23 10:15:44 +02:00
Ken fccf5bafdb [DataTable] Add global index counter when traversing rows 2026-04-23 10:04:49 +02:00
Ken df075c7ec8 🐛 Sync yarn.lock 2026-04-22 21:36:51 +02:00
Ken 0672fc6cee [LLM] Updated categories in LLM.md 2026-04-22 21:13:41 +02:00
Ken 088d65a63b [LLM] Added tailwind config route 2026-04-22 21:01:56 +02:00
Ken 11dc6bf0c6 [DataTable] WIP nested item hook 2026-04-22 20:45:46 +02:00
Ken 7f127ad5b0 [DataTable] 🎉 Added nested row handling --no-verify 2026-04-22 20:26:13 +02:00
Halvor Haugan 5885a70c41 DataTable: Remove code that was not supposed to be pushed 2026-04-22 15:12:47 +02:00
Halvor Haugan 7e23ed71e7 DataTable: Add support for col resize with Home and End 2026-04-22 15:01:21 +02:00
Ken 9205952283 [DataTable] Added check for exandable data in nested rows 2026-04-22 13:08:42 +02:00
Ken f70bb419e8 [DataTable] Added separate toggles for nested and master-detail pattern 2026-04-22 12:49:48 +02:00
Ken b22c98d215 [DataTable] Added more nested rows stories 2026-04-22 12:32:03 +02:00
Halvor Haugan 1efadf3df3 DataTable: Fix SR issue related to col resizing 2026-04-22 11:49:55 +02:00
Halvor Haugan bc69e8cfbd DataTable: Avoid setting onClick on <tr> if not needed 2026-04-22 11:47:55 +02:00
Halvor Haugan 8198d53ecc DataTable: Adjust when column header gets hover/active background 2026-04-22 09:59:27 +02:00
Ken cb03a70eb2 [DataTable] Added styling for ensted rows 2026-04-21 15:34:54 +02:00
Ken cdad58bdbb [DataTable] Added subrows 2026-04-21 15:34:54 +02:00
Ken e3830c70c2 [DataTable] Added getSubRows prop 2026-04-21 15:34:54 +02:00
Ken 607259ee75 🏷️ Typo 2026-04-21 15:34:53 +02:00
Halvor Haugan 55e41f44ad DataTable: Auto-size column to fit content on double click 2026-04-21 15:28:05 +02:00
Halvor Haugan 443754ebc3 DataTable: Fix type error 2026-04-21 13:05:11 +02:00
Halvor Haugan a49b9925a6 DataTable: role=slider on resize handle for improved (?) a11y 2026-04-21 12:43:20 +02:00
Halvor Haugan dbf498264a Storybook: improved types in main and preview config (#4828) 2026-04-21 11:55:06 +02:00
Halvor Haugan 081f6b14b4 Sync react versions 2026-04-21 09:40:48 +02:00
Halvor Haugan e28d875d46 createMainChangelog: Order changelogs deterministically (#4827) 2026-04-21 09:36:11 +02:00
dependabot[bot]andKen 99393696ee Bump next from 16.2.0 to 16.2.3 in /aksel.nav.no/website in the npm_and_yarn group across 1 directory (#4796)
* ⬆️ Bump next

Bumps the npm_and_yarn group with 1 update in the /aksel.nav.no/website directory: [next](https://github.com/vercel/next.js).


Updates `next` from 16.2.0 to 16.2.3
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.2.0...v16.2.3)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.2.3
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* ⬆️ Update nextjs

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-21 09:34:19 +02:00
Halvor Haugan 255131b4bd Modal: Separate story for small size (#4826) 2026-04-21 09:33:52 +02:00
ec7beb2b37 Bump react-dom from 19.2.4 to 19.2.5 in the react group across 1 directory (#4819)
* Bump react-dom from 19.2.4 to 19.2.5 in the react group

Bumps the react group with 1 update: [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom).


Updates `react-dom` from 19.2.4 to 19.2.5
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.5/packages/react-dom)

---
updated-dependencies:
- dependency-name: react-dom
  dependency-version: 19.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: react
...

Signed-off-by: dependabot[bot] <support@github.com>

* 📝 Update react and react-dom

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-21 09:29:02 +02:00
dependabot[bot]andKen 396f2641d7 Bump swr from 2.4.0 to 2.4.1 (#4822)
* Bump swr from 2.4.0 to 2.4.1

Bumps [swr](https://github.com/vercel/swr) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/vercel/swr/releases)
- [Commits](https://github.com/vercel/swr/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: swr
  dependency-version: 2.4.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* 🎉 Sync SWR versions

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-20 19:11:57 +02:00
c94f87e6dc [Markdown] Added Markdown routes for each page, ikon-page and design-tokens (#4814)
* 🎉 Added unpacked enums

* 🎉 Updated queries

* ⬆️ yarn update

* 🎉 Added markdown-docs for each page

* 🎉 Added regular link interception

* 🎉 Added design-token route

* 🎉 Added icon-documentation

* 🎉 Add static paths to root llm.md

* Update aksel.nav.no/website/scripts/update-props.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update aksel.nav.no/website/sanity/interface/queries.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 📝 Fix naming

* Update aksel.nav.no/website/sanity/interface/queries.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* ♻️ Small refactors to config and comments

* 🐛 Update types after enum addition

* 🏷️ Update query-types

* Update aksel.nav.no/website/app/api/markdown/routes/design-tokens.ts

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 📝 Use -

* 🐛 Resolve em-dash

* 📝 Updated token formatting

* 📝 Updated docs

* 🏷️ Rename enum -> unpackedTypes

* 🏷️ Rename enum -> unpackedTypes

* 📝 Update schema

* Update aksel.nav.no/website/app/api/markdown/llm.config.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update aksel.nav.no/website/app/api/markdown/routes/grunnleggende.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update aksel.nav.no/website/app/api/markdown/routes/design-tokens.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update aksel.nav.no/website/app/api/markdown/routes/design-tokens.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 🐛 Fix typo

* 🔒 Security updates

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-20 19:11:37 +02:00
dependabot[bot]andKen 1c2a43dba8 Bump the vitest group across 1 directory with 4 updates (#4821)
* Bump the vitest group with 4 updates

Bumps the vitest group with 4 updates: [@vitest/browser](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser), [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/browser` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/browser)

Updates `@vitest/browser-playwright` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/browser-playwright)

Updates `@vitest/coverage-v8` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/coverage-v8)

Updates `vitest` from 4.1.0 to 4.1.4
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.4/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/browser"
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: "@vitest/browser-playwright"
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
- dependency-name: vitest
  dependency-version: 4.1.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>

* ⬆️ Update vitest

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-20 14:16:59 +02:00
dependabot[bot] 697d1a2793 Bump the storybook group with 9 updates (#4820)
Bumps the storybook group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-a11y](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/a11y) | `10.2.10` | `10.3.5` |
| [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs) | `10.2.10` | `10.3.5` |
| [@storybook/addon-themes](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/themes) | `10.2.10` | `10.3.5` |
| [@storybook/addon-vitest](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/vitest) | `10.2.10` | `10.3.5` |
| [@storybook/nextjs-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/nextjs) | `10.2.10` | `10.3.5` |
| [@storybook/react-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite) | `10.2.10` | `10.3.5` |
| [eslint-plugin-storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/eslint-plugin) | `10.2.10` | `10.3.5` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core) | `10.2.10` | `10.3.5` |
| [storybook-addon-pseudo-states](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/pseudo-states) | `10.3.0` | `10.3.5` |


Updates `@storybook/addon-a11y` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/addons/a11y)

Updates `@storybook/addon-docs` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/addons/docs)

Updates `@storybook/addon-themes` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/addons/themes)

Updates `@storybook/addon-vitest` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/addons/vitest)

Updates `@storybook/nextjs-vite` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/frameworks/nextjs)

Updates `@storybook/react-vite` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/frameworks/react-vite)

Updates `eslint-plugin-storybook` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/lib/eslint-plugin)

Updates `storybook` from 10.2.10 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/core)

Updates `storybook-addon-pseudo-states` from 10.3.0 to 10.3.5
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v10.3.5/code/addons/pseudo-states)

---
updated-dependencies:
- dependency-name: "@storybook/addon-a11y"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/addon-docs"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/addon-themes"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/addon-vitest"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/nextjs-vite"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/react-vite"
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: eslint-plugin-storybook
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: storybook
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: storybook-addon-pseudo-states
  dependency-version: 10.3.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-20 14:14:43 +02:00
KenandCopilot d36ee0fcd7 [Sanity/Ai] Unpack enum-props so that markdown-docs can have better docs for AI (#4812)
* 🎉 Added unpacked enums

* 🎉 Updated queries

* ⬆️ yarn update

* Update aksel.nav.no/website/scripts/update-props.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update aksel.nav.no/website/sanity/interface/queries.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 📝 Fix naming

* Update aksel.nav.no/website/sanity/interface/queries.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 🐛 Update types after enum addition

* 📝 Updated docs

* 🏷️ Rename enum -> unpackedTypes

* 🏷️ Rename enum -> unpackedTypes

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-20 14:06:58 +02:00
github-actions[bot] 13cb816166 Version Packages (#4824)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-20 13:28:26 +02:00
KenandHalvor Haugan f66236c371 [Modal] 🐛 Changing Modal-size had no effect before (#4823)
* 🐛 Changing Modal-size had no effect before

* 📝 Add default jsdoc

* Update .changeset/chilly-llamas-show.md

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-20 13:18:54 +02:00
Halvor Haugan 11463cebc3 DataTable: Disable keyboard nav when trying to resize col with arrow keys 2026-04-20 12:50:53 +02:00
Halvor Haugan 5f3c6541fd DataTable: Remove default padding on sort-button and cells 2026-04-20 12:48:22 +02:00
github-actions[bot] 756c9578eb Version Packages (#4789)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-20 11:14:15 +02:00
Halvor Haugan 2eab5b9564 DatePicker: Highlight days between start and hovered day (#4801) 2026-04-20 09:53:52 +02:00
Ken c037bc4733 📝 Add todos 2026-04-19 12:48:29 +02:00
Halvor HauganandCopilot 794bf825a5 [Docs] Adjust CONTRIBUTING.md in aksel-icons (#4817)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-17 16:42:56 +02:00
Ken 33b8b279a6 Revert -> Website: Test LLM llm uA 2026-04-17 16:36:56 +02:00
Ken 5c8c77503c Website: Test LLM llm uA 2026-04-17 16:16:03 +02:00
Ken 55b48252a9 [Timeline] When row has focus, focus first or last period based on arrow-keys (#4816)
* 🎉 Added fallbacks when row is active

* 🐛 Fix typo
2026-04-17 15:57:11 +02:00
Ken df8fb7e3e9 [DataTable] Avoid selecting rows that are disabled 2026-04-17 14:54:18 +02:00
Ken c096f46beb 🐛 Fix typo-sizing, header-padding for infocard and alerts (#4815)
* 🐛 Fix typo-sizing, header-padding for infocard and alerts

* 🔥 Removed comments

* 📝 Update changeset

* 💄 Optical align infocard header

* ♻️ Use size directly

* 📝 Updated comments
2026-04-17 13:43:59 +02:00
KenandHalvor Haugan f491aaec70 [Timeline] Enhance keyboard navigation, optimize pin interactions, period-scaling (#4809)
* 🐛 Add onClick handler for Pin

* ⚡ Added keyboard-nav between rows

* ⚡ Refactor keyboard-handler

* 🎉 Added pins to keyboard-nav

* ⚡ Added early returns

* ⚡ Optimize re-renders

* 💄 Hide icons on smallest periods

* 💄 Update icon sizing based on width

* 🧪 Timeline nav tests

* 📝 Changeset

* ⚰️ Clean up unused state, avoid navigating when inside popovers

* 🐛 Avoid preventDefault on event if no focus is done

* 🐛 Return focus to element that opened popover

* Update @navikt/core/react/src/timeline/hooks/TimelineKeyboardNavProvider.tsx

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* ♻️ Refactor ref-handling

* Update @navikt/core/react/src/timeline/hooks/TimelineKeyboardNavProvider.tsx

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* ⚡ Updated memorization

* ⚡ Move util outside of component

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-17 13:43:31 +02:00
Anniken GranbergandCopilot Autofix powered by AI 139805d5b4 ExpandableRow: Top border disappeared on selected rows when row above was collapsed (#4810)
* ExpandableRow: Fix selected row top border not showing when row above was collapsed

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* more spesific css selector

* Wrote wrong classname 🤦‍♀️

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-17 10:13:35 +02:00
Halvor HauganandKen eceeb3855a ⬆️ Upgrade Sanity to 5.20 (and related packages) (#4813)
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-17 08:58:50 +02:00
Halvor Haugan 67ee836fb6 Sync vite versions 2026-04-16 17:29:13 +02:00
391018ed29 Typescript 6.0.2 update: Fix type and build issues (#4786)
* Bump typescript from 5.9.3 to 6.0.2

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.9.3...v6.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* ⬆️ Sync typescript version across repo

* 🐛 Fix build-errors

* 🐛 Fix type-errors in daypicker, ignore tsbuildinfo

* 🐛 Resolve CLI type-errors

* 🐛 Fix TS 6.0 issues

* 🐛 Fix codemod issues

* ⚡ Utility for extracting strings and literals

* 🔥 Removed comments

* Apply suggestions from code review

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* ♻️ Review updates

* ⬆️ Update ts for playroom

* ⬆️ yarn update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-16 16:17:28 +02:00
Ken 12a584f9ab [DataTable] Resolve context issue 2 2026-04-16 13:37:08 +02:00
Halvor Haugan f57ef4323d [website] Update examples of InternalHeader and Timeline (#4805) 2026-04-16 12:47:46 +02:00
Ken f73546039b [DataTable] Resolve context issue 2026-04-16 11:40:35 +02:00
Ken 563aa6530a [DataTable] Resolve context issue 2026-04-16 11:38:58 +02:00
Ken 9726f26c53 [DataTable] Add missing prop to context 2026-04-16 10:37:58 +02:00
Ken 25cc71c6e0 [DataTable] Allow rendring data with loading state enabled, instead making body inert 2026-04-16 10:18:07 +02:00
Ken 2f70ea3101 [DataTable] Avoid triggering onRowClick on cells with actions 2026-04-16 09:53:08 +02:00
Ken 476804b90c [DataTable] Move onRowClick to Row itself trough context 2026-04-16 09:38:03 +02:00
Ken c7d2a8a3aa [DataTable] Auto refactors 2 bogaloo 2026-04-16 09:23:01 +02:00
Ken e0b2bee5f0 [DataTable] Auto refactors 2026-04-16 09:18:31 +02:00
Ken 36fa158dc8 [DataTable] Added Expandable Rows and onRowClick 2026-04-15 16:09:42 +02:00
d23551b7da sporing-dev.js script + potentially useful tracking events (#4800)
* use the sporing-dev tracking script in dev, no longer use data-host-url

* ➕ add taxonomy package + use it

* fix: expose PRODUCTION env var to client via nextConfig.env

Agent-Logs-Url: https://github.com/navikt/aksel/sessions/08c505b1-b087-431b-bd30-41b9956c320d

Co-authored-by: JulianNymark <819074+JulianNymark@users.noreply.github.com>

* Update aksel.nav.no/website/app/_ui/code-block/CodeBlock.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add missing \"use client\" to components using umamiTrack

* fix: keep WebsiteExpansionCard as server component, extract onToggle tracking to thin client wrapper

* do not track actual search strings

* fix: send placement as lenkegruppe and actual link text as lenketekst in UmamiLink

* 🐛 Resolve render-issues

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: JulianNymark <819074+JulianNymark@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-15 13:56:32 +02:00
Anniken Granberg 3f0efd7dc4 DataTable/dnd: add label 2026-04-15 13:16:38 +02:00
Ken 63f5aaf2f4 🐛 Make sure text-variant for Skeleton has properly rounded edges (#4808) 2026-04-15 12:49:34 +02:00
Anniken Granberg ee95122ec1 DataTable: fix types 2026-04-15 10:29:07 +02:00
Anniken Granberg e8f90be978 DataTable: Add label to columnDefinition and changed item type for dnd 2026-04-15 10:26:51 +02:00
Ken 2c0ee8d2ca [DataTable] Added onRowClick 2026-04-14 15:57:11 +02:00
Ken 8d708b1ef8 [DataTable] Auto version feature addons
[DataTable] Refactor loading state and body rendring.

[DataTable] Added emptyState prop

[DataTable] Removed render-prop for custom filterMenu

[DataTable] Updated stickyColumns jsdoc

[DataTable] Added loading states

[DataTable] Added loading label, better handling of colspan in loading/empty-state
2026-04-14 14:36:33 +02:00
Ken 3e4c2deced [DataTable] Added shift click sort support 2026-04-14 13:33:31 +02:00
Ken 0101acd2e0 [DataTable] Added sorting API to table auto 2026-04-14 12:55:28 +02:00
Halvor Haugan 14dc7b3775 Update vscode settings (#4804) 2026-04-14 11:16:06 +02:00
Ken 64d07ad527 🧪 Improve test-suite for storybook 2026-04-14 10:25:48 +02:00
Ken 99f04a8129 [DataTable] Refactor DataTableContextProvider 2026-04-14 10:25:48 +02:00
Ken 75c62c4e92 [DataTable] Refactor getRowIds use 2026-04-14 10:25:48 +02:00
Ken 0055a744c1 [DataTable] Move table ref-state to hook 2026-04-14 10:25:48 +02:00
Halvor Haugan e6c5b9b868 ⬆️ Upgrade Vite to 7.3.2 / 8.0.5 2026-04-14 09:35:20 +02:00
dependabot[bot] a245d0dbfb ⬆️ Bump vite from 7.3.1 to 7.3.2 (#4802)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.1 to 7.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-14 09:27:22 +02:00
Anniken Granberg e09bbdc0fe DataTable / dnd: Added announcer, changed some props, better (?) labels 2026-04-14 09:19:26 +02:00
Ken 873724d1f4 [DataTable] Fix filler-cell taking space when not needed, added fixed layout stories 2026-04-13 16:13:33 +02:00
Halvor HauganandKen 004d0fc547 DatePicker: Reset range when selecting a new day, upgrade react-day-picker (#4799)
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2026-04-13 16:07:40 +02:00
Ken cc37a94093 [DataTable] Fix resizable handle overflow and clipping 2026-04-13 15:00:59 +02:00
Ken 46bc3c92b3 [DataTable] Fix border overflow when sticky 2026-04-13 14:40:37 +02:00
Ken 7782b83105 Patch Axios to v1.15 (#4798)
* Path CVE 10 axios error. Axios 1.15 patch

* 🔥 Removed preApproved for axios
2026-04-13 11:32:26 +02:00
Ken 5f79eeade6 [DataTable] Added header sticking with column sticking 2026-04-13 09:51:17 +02:00
Ken 471635d518 [DataTable] Added column sticking 2026-04-11 17:21:09 +02:00
Anniken Granberg b4a1dd72db DataTable/dnd: Accessibility, renaming, cancel event, rewrite 2026-04-10 14:50:28 +02:00
Halvor Haugan a714e05c56 [website] Fix typo in LegacyTokenTable (#4795) 2026-04-10 14:41:28 +02:00
Ken 9daea7aa21 [DataTable] Forward row and col-span 2026-04-10 14:27:05 +02:00
Ken 0303d825fa [DataTable] Split column header and generic TH-cell 2026-04-10 14:06:29 +02:00
Ken c6ac943c88 [DataTable] added sticky column prop 2026-04-10 14:06:29 +02:00
Ken 0551a90951 [DataTable] Fix CSS for genetic cell 2026-04-10 14:06:29 +02:00
fbfd1656e2 ⬆️ Bump eslint-plugin-react-hooks from 5.2.0 to 7.0.1 (#4447)
* ⬆️ Bump eslint-plugin-react-hooks from 5.2.0 to 7.0.1

Bumps [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) from 5.2.0 to 7.0.1.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/HEAD/packages/eslint-plugin-react-hooks)

---
updated-dependencies:
- dependency-name: eslint-plugin-react-hooks
  dependency-version: 7.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* 🐛 update config

* 🏷️ Lint-updates

* eslint-disable combobox.stories, ErrorSummary, Dropzone

* Add disable comments in modal.stories.tsx

* Add eslint-disable comment in LinkAnchor

* eslint-disable in generic-error-page.tsx

* disable ref rule and ignore remaining lint errors

* inline

* fix yarn.lock

* CRLF -> LF

* New attempt at fixing lockfile

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Ken <ken.aleksander@gmail.com>
Co-authored-by: Halvor Haugan <halvor.haugan@nav.no>
Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-10 13:07:28 +02:00
Ken 4b674930c5 🐛 Resolve test-errors after data-table update 2026-04-10 13:02:50 +02:00
Ken 2128e94a1b 🎉 Added formatting to pre-push command 2026-04-10 13:00:55 +02:00
Ken f381a3b9c7 🎉 Added pre-push command to run tests before pushing to main 2026-04-10 12:59:00 +02:00
Ken dec64b021f [DataTable] TdCell uses genetic cell 2026-04-10 12:51:54 +02:00
Ken af95682d22 [DataTable] Generic cell boilerplate 2026-04-10 12:45:33 +02:00
Ken cf0f7c3b79 [DataTable] JSDoc update 2026-04-10 12:30:26 +02:00
Ken 1d19f27008 [DataTable] JSDoc update 2026-04-10 12:21:02 +02:00
Ken 52b4dcd7b6 [DataTable] Rename selection disabled props 2026-04-10 12:18:49 +02:00
Ken 3822bf50fa [DataTable] Removed unused labels for checkbox and radio 2026-04-10 12:01:06 +02:00
Ken 99ce4399fa [DataTable] optimize selection hook 2026-04-10 11:55:09 +02:00
Ken 3d693351fe [Actions] Matrix resolver for container cleanup 2026-04-10 11:40:22 +02:00
Ken 93872c5573 Revert: [Actions] allow chaning number of deleted images from ghp 2026-04-10 10:33:21 +02:00
Ken 2f0a99e744 [Actions] allow chaning number of deleted images from ghp 2026-04-10 10:29:32 +02:00
Ken af5e83d613 [DataTable] Improved selecting + pagination logic, added todos 2026-04-10 10:25:40 +02:00
Ken 6b64f271cf [Timeline] ♿ Improved JAWS support with click-handler for period-popups (#4793)
* ♿ Improved JAWS support with click-handler for period-popups

* 🐛 Allow mouse-events to toggle clickable-period popup
2026-04-10 09:31:09 +02:00
Halvor Haugan 1ea580482e [website] Show clear button on sidebar filter input 2026-04-09 14:38:13 +02:00
Halvor Haugan cf9c5ef2c4 InlineMessage: Improve screen reader experience (#4792) 2026-04-09 12:21:31 +02:00
Ken 9f15a817a0 🐛 Revert locale update from backup 2026-04-09 11:45:51 +02:00
dependabot[bot] e9067600fc Bump lodash-es from 4.17.23 to 4.18.1 (#4791)
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-version: 4.18.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 11:34:37 +02:00
Halvor Haugan 363a6061bd CheckboxGroup: Set aria-invalid on error (#4790) 2026-04-09 09:39:42 +02:00
dependabot[bot] 37bad55c75 Bump mlly from 1.8.0 to 1.8.2 (#4787)
Bumps [mlly](https://github.com/unjs/mlly) from 1.8.0 to 1.8.2.
- [Release notes](https://github.com/unjs/mlly/releases)
- [Changelog](https://github.com/unjs/mlly/blob/main/CHANGELOG.md)
- [Commits](https://github.com/unjs/mlly/compare/v1.8.0...v1.8.2)

---
updated-dependencies:
- dependency-name: mlly
  dependency-version: 1.8.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-09 09:21:59 +02:00
Anniken Granberg acdcd29f70 DataTable/Dnd: Add buttons for rearranging items, deactivate active handler on outside click, disble dragging on active handle 2026-04-08 16:42:35 +02:00
Ken 45d87ce21d [DataTable] 🐛 Add data-type to column-definition 2026-04-08 15:31:19 +02:00
Ken bfe01c316a [DataTable] 🐛 Selection-state css 2026-04-08 15:05:01 +02:00
Ken 8f6286d081 [DataTable] 🐛 handle type-errors 2026-04-08 14:56:43 +02:00
Ken a5240353b8 [DataTable] Added datatable stories 2026-04-08 14:53:10 +02:00
Ken b9612e348e [DataTable] Extracted selected cell width as a constant 2026-04-08 14:53:09 +02:00
Ken 60624d4a8a [DataTable] Optimize checked and disabled lookup 2026-04-08 14:53:09 +02:00
Ken 072b24d46e [DataTable] Handle single-select and disabled keys better 2026-04-08 14:53:09 +02:00
Ken 28b5dea3d3 [DataTable] Update CSS to show disabled state in standalone mode 2026-04-08 14:53:08 +02:00
Halvor Haugan 741a270eed ⬆️ Upgrade Biome to 2.4.10 (#4788) 2026-04-08 14:05:28 +02:00
Halvor Haugan 3c128e12a5 RadioGroup: Set role=radiogroup, and set aria-invalid on error (#4773) 2026-04-08 13:38:47 +02:00
Ken 658b44fa46 [DataTable] Add accessible labels to selection inputs 2026-04-08 13:31:44 +02:00
Ken 4c4cd1ef02 [DataTable] Remove 'all' from selection type API 2026-04-08 13:31:44 +02:00
Ken 9ee70a881a [DataTable] Unique names for radio 2026-04-08 13:31:43 +02:00
Ken e20f669c79 [DataTable] Derive selected state from context 2026-04-08 13:31:43 +02:00
Halvor Haugan 4d5639a31b Box: Fix typo in JSDoc 2026-04-08 13:06:17 +02:00
Halvor Haugan 6e3421189f [website] Remove the word "statisk" from InfoCard examples 2026-04-08 12:56:04 +02:00
Ken 77fc4fdefc [DataTable] Fix type-error 2026-04-08 11:49:10 +02:00
Halvor Haugan 50688d5b07 ⬆️ Upgrade lodash 2026-04-08 11:42:37 +02:00
Ken 4e49f74470 [DataTable] Update Selectionstate to be rendered within tablerows 2026-04-08 11:38:41 +02:00
dependabot[bot] 8d9e46a528 Bump @vitest/eslint-plugin from 1.6.9 to 1.6.14 in the vitest group (#4785)
Bumps the vitest group with 1 update: [@vitest/eslint-plugin](https://github.com/vitest-dev/eslint-plugin-vitest).


Updates `@vitest/eslint-plugin` from 1.6.9 to 1.6.14
- [Release notes](https://github.com/vitest-dev/eslint-plugin-vitest/releases)
- [Commits](https://github.com/vitest-dev/eslint-plugin-vitest/compare/v1.6.9...v1.6.14)

---
updated-dependencies:
- dependency-name: "@vitest/eslint-plugin"
  dependency-version: 1.6.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 11:34:00 +02:00
Halvor Haugan db94a7eb4c Upgrade deps in examples/astro 2026-04-08 11:30:28 +02:00
Halvor Haugan c4dcc61dfb Merge branch 'main' of github.com:navikt/aksel 2026-04-08 11:18:41 +02:00
Halvor Haugan 12a4b6af33 Delete lock files in examples, and exclude package.jsons in Dependabot 2026-04-08 11:18:08 +02:00
Ken 167c474668 🐛 Update CSP header for umami (#4784) 2026-04-08 11:18:04 +02:00
Halvor Haugan 522285238b Empty lock files in examples to prevent Dependabot touching them 2026-04-08 10:02:25 +02:00
Ken ac8cba2cf4 [DataTable] Fixed checkbox alignment 2026-04-08 09:10:17 +02:00
Halvor HauganandKen d1c7d72a0d 🚨 Linting: Use Biome to find import cycles instead of eslint (#4768)
Co-authored-by: Ken <ken.aleksander@gmail.com>
2026-04-07 16:16:28 +02:00
Ken bb6726b1ee ⬅️ Revert release-packages workflow name update to avoid NPM packages release issues 2026-04-07 16:15:38 +02:00
github-actions[bot] c0a7be2008 Version Packages (#4782)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-07 15:59:40 +02:00
KenandHalvor Haugan a3743a6b37 [Workflows] 🧹 Better naming, grouping and texts (#4767)
* 📝 Update workflows with better naming, texts and permissions

* 📝 Name updates

* 🎉 Clean up images used for testing

* 🔥 Removed unused deploy tag

* Update .github/workflows/build-validation.yml

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* Update .github/workflows/build-validation.yml

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 📝 Clean up permissions

* Update .github/workflows/deploy-prod-gcp.yml

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 📝 Sync sanity texts

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-07 14:57:03 +02:00
Ken 47d74be1a0 🐛 Sync datepicker input button with input itself (#4781)
* 🐛 Sync datepicker input button with input itself

* 🔥 removed non needed width and height definition
2026-04-07 14:56:19 +02:00
Ken bff180ad42 [DataTable] 🐛 Remove row-selection from not-yet-implemented simple kitchen-sink demo 2026-04-07 13:39:58 +02:00
Ken 14bcb500d0 [DataTable] Add selection mode to kitchen-sink demo 2026-04-07 13:33:51 +02:00
Ken 9014bf0073 [DataTable] Added selection css for testign 2026-04-07 13:19:06 +02:00
93465781c1 [Checkbox, Radio] Inline inputs for use internally in DataTable (#4760)
* 🎉 Added checkbox-item component

* 🔥 Removed hardcoded sr-only classname

* 🎉 unpack props for better destructuring

* 🎉 Working standalone radio and checkbox inputs

* 🎉 Use standalone inputs in table

* 📝 Changeset

* Update @navikt/core/react/src/form/radio/radio-input/RadioInput.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update @navikt/core/react/src/form/checkbox/checkbox-input/CheckboxInput.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* 🐛 Forward className

* 🐛 Story value fix

* Update @navikt/core/css/src/form/radio-checkbox.css

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 📝 JSDOC update

* 🐛 Hide margin when empty SR-text

* 📝 added hidelegend story

* 🔥 removed css-var declarations on root css

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-04-07 12:48:47 +02:00
Halvor Haugan f7393f7515 Button: Use correct text color when inherited data-color is "neutral" (#4772) 2026-04-07 11:52:52 +02:00
dependabot[bot]andKen 890db16c2a Bump yaml from 1.10.2 to 1.10.3 (#4777)
Bumps [yaml](https://github.com/eemeli/yaml) from 1.10.2 to 1.10.3.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v1.10.2...v1.10.3)

---
updated-dependencies:
- dependency-name: yaml
  dependency-version: 1.10.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2026-04-07 10:09:16 +02:00
dependabot[bot] 08e3457314 Bump path-to-regexp from 0.1.12 to 0.1.13 (#4779)
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 0.1.12 to 0.1.13.
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-version: 0.1.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 09:46:30 +02:00
dependabot[bot] 8cd871403c Bump picomatch from 2.3.1 to 2.3.2 (#4776)
Bumps [picomatch](https://github.com/micromatch/picomatch) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-07 09:30:56 +02:00
Anniken Granberg b6e3c7dc2e DataTable: fix errors 2026-03-27 17:18:22 +01:00
Anniken Granberg 956e1c10c7 DataTable: Allow onClick on drag handlerr 2026-03-27 17:14:49 +01:00
Anniken Granberg 08020c7aff DataTable: fix error 2026-03-27 16:08:19 +01:00
Anniken Granberg ba547bbad7 DataTable: Make item overlay same width as item 2026-03-27 15:24:52 +01:00
Halvor Haugan fd2bbd3de0 Update ActionMenu shortcuts example (#4774) 2026-03-27 14:20:47 +01:00
Ken f23f6855ad [DataTable] TokenFilter chips WIP 2026-03-27 14:00:09 +01:00
Ken a06dcabfc7 [DataTable] TokenFilter input layout 2026-03-27 14:00:09 +01:00
Ken e804a857af [DataTable] KitchenSink with tokenfilter 2026-03-27 14:00:09 +01:00
Ken 70c255aebc [DataTable] Story cleanup 2026-03-27 14:00:08 +01:00
Halvor Haugan fe21575a8d Update changeset format in PR template 2026-03-27 13:29:37 +01:00
github-actions[bot] f5d0a158d1 Version Packages (#4759)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-27 13:20:27 +01:00
Ken b359130706 [DataTable] layout-story updates 2026-03-27 11:34:02 +01:00
Ken d76d3cc30b [DataTable] Update pagination and toolbar view 2026-03-27 09:52:48 +01:00
Ken 112f5f97db 📝 Disable autocomplete in tokenfilter 2026-03-27 09:52:48 +01:00
Ken 4811920686 🔒 Disable scripts when running yarn install for sercurity (#4766) 2026-03-27 09:45:18 +01:00
Halvor Haugan c894748316 Run in-sync-versions.ts in CI instead of pre-commit (#4769) 2026-03-27 08:56:23 +01:00
Halvor Haugan 6d5ef574cd Sync vitest versions (#4770) 2026-03-27 08:56:09 +01:00
Ken 5a911b469e [DataTable] Removed actionbar, updated toolbar 2026-03-26 20:59:14 +01:00
Ken 192db60c20 [DataTable] TokenFilter + listbox updates 2026-03-26 20:32:58 +01:00
Ken c041bcd8ca ⬆️ nextjs (#4771) 2026-03-26 16:55:21 +01:00
Ken 86f86d3760 [InternalHeader] 🎉 Added 'isActive'-prop to InternalHeaderButton. (#4761)
* 🎉 Added 'isActive'-prop to InternalHeaderButton.

* 🐛 Use actual links in story view

* review updates: aria-current, forced-colors and taller line

* 🐛 Allow user to override aria-current
2026-03-26 15:36:21 +01:00
Ken c2e123d403 🔊 Clean up boot command output 2026-03-26 15:22:50 +01:00
Ken 58a413d98d 🐛 revert story test enabling for flaky tests 2026-03-26 14:49:57 +01:00
Ken 4bb0edddad 🧹 Misc test and comment cleanup 2026-03-26 13:39:54 +01:00
Anniken Granberg df8979ff50 DataTable: try to fix dependecy cicle linting fail 2026-03-26 13:18:09 +01:00
Ken 7771731b0f 🔊 Add deployment permissions to show deployments when publishing 2026-03-26 12:29:30 +01:00
Halvor Haugan 6fdf8f1782 Change clean script to use glob from node (#4763) 2026-03-26 12:21:29 +01:00
Anniken Granberg 5d61d5269a DataTable: comment 2026-03-23 18:26:17 +01:00
Anniken Granberg 33a5d8a85c DataTable: comments 2026-03-23 18:22:41 +01:00
Anniken Granberg 42a8c75184 DataTable: new native dnd component 2026-03-23 18:22:41 +01:00
Anniken Granberg 9cefd6e73d DataTable: rename files 2026-03-23 18:22:41 +01:00
Anniken Granberg 097a506a19 DataTable: Rename, removed data in front 2026-03-23 18:22:41 +01:00
dependabot[bot] 46dcee3636 Bump the vitest group with 4 updates (#4753)
Bumps the vitest group with 4 updates: [@vitest/browser](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser), [@vitest/browser-playwright](https://github.com/vitest-dev/vitest/tree/HEAD/packages/browser-playwright), [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@vitest/browser` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/browser)

Updates `@vitest/browser-playwright` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/browser-playwright)

Updates `@vitest/coverage-v8` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/coverage-v8)

Updates `vitest` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest)

---
updated-dependencies:
- dependency-name: "@vitest/browser"
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: vitest
- dependency-name: "@vitest/browser-playwright"
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: vitest
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: vitest
- dependency-name: vitest
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: vitest
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 14:20:26 +01:00
Halvor Haugan 72a9131aee DatePicker, MonthPicker: Make open button more prominent (#4751) 2026-03-23 14:05:17 +01:00
dependabot[bot] 4a9d358d0a Bump vite-tsconfig-paths from 6.1.0 to 6.1.1 (#4758)
Bumps [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v6.1.0...v6.1.1)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-version: 6.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 13:59:54 +01:00
Halvor Haugan 14f1491cce Dependabot: Try excluding lockfiles in examples dir (#4756) 2026-03-23 13:27:53 +01:00
Halvor Haugan ad9978fb93 lint-staged: make biome ignore attempts to lint ignored files 2026-03-23 10:44:49 +01:00
dependabot[bot] 04c4414de5 Bump lint-staged from 16.2.7 to 16.4.0 (#4754)
Bumps [lint-staged](https://github.com/lint-staged/lint-staged) from 16.2.7 to 16.4.0.
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v16.2.7...v16.4.0)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-version: 16.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 10:24:40 +01:00
dependabot[bot] fa7ae4ec6f Bump esbuild from 0.27.3 to 0.27.4 (#4755)
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.27.3 to 0.27.4.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.3...v0.27.4)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.27.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-23 09:48:33 +01:00
Anniken Granberg 94c6e5cf79 [Website] Add aria-current attribute to navigation links for improved… (#4750)
* [Website] Add aria-current attribute to navigation links for improved accessibility

* Use const value and use true instead of page
2026-03-23 09:48:24 +01:00
Halvor Haugan 0e8e4fc4a2 ⬆️ Bump flatted to 3.4.2 2026-03-23 09:47:21 +01:00
dependabot[bot]andHalvor Haugan ecef57a167 Bump next from 16.1.6 to 16.1.7 in /aksel.nav.no/website in the npm_and_yarn group across 1 directory (#4752)
* Bump next

Bumps the npm_and_yarn group with 1 update in the /aksel.nav.no/website directory: [next](https://github.com/vercel/next.js).


Updates `next` from 16.1.6 to 16.1.7
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.1.6...v16.1.7)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.1.7
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>

* lockfile

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Halvor Haugan <halvor.haugan@nav.no>
2026-03-23 09:44:51 +01:00
Ken 666616232d [LLM] Added grunnleggende and templates LLM-docs 2026-03-21 20:54:04 +01:00
Ken b607e20964 [LLM] Set up templates and grunnleggende 2026-03-21 20:32:00 +01:00
Ken a093c9385a [DataTable] Selection API refactor 2026-03-21 19:41:04 +01:00
Ken 9889b16500 [DataTable] Added more flexibility to row id creation 2026-03-21 19:41:03 +01:00
Halvor Haugan 1273dcd586 ⬆️ Upgrade deps in /examples 2026-03-20 19:33:18 +01:00
Halvor Haugan 2342b687ce Biome/eslint adjustments (#4749) 2026-03-20 15:35:29 +01:00
github-actions[bot] cf5d3e98c5 Version Packages (#4718)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-20 15:01:04 +01:00
Halvor Haugan b990be4ee8 Chromatic: update externals value (#4748) 2026-03-20 13:12:11 +01:00
KenandHalvor Haugan c3b06bdc80 [Dialog] Links are now a valid focusable target when tabbing (#4747)
* 🧪 set up failing story test

* Dialog: Fixed issue where tabbing would not work when focusable element was a link

* Update .changeset/rare-seas-trade.md

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-03-20 12:48:46 +01:00
dependabot[bot] 82c00e2591 Bump flatted from 3.3.3 to 3.4.1 (#4746)
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.3 to 3.4.1.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.1)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 12:09:46 +01:00
Ken 5756986070 GlobalAlert, LocalAlert: Content outline changed from 4px to 2px. (#4745) 2026-03-20 11:34:32 +01:00
Ken 738813046f [InfoCard] InfoCardMessage sub-component (#4717)
* 🎉 Added new sub-component for InfoCard: InfoCard.Message

* 📝 Jsdocs

* Apply suggestion from @KenAJoh

* 📝 Update jsdoc

* 💄 Refactor composition

* ♻️ Review updates

* 📝 Jsdocs

* ♻️ Remove data-size attrb from message-component

* 📝 examples
2026-03-20 11:29:42 +01:00
dependabot[bot] e942e77281 Bump undici from 6.23.0 to 6.24.0 (#4743)
Bumps [undici](https://github.com/nodejs/undici) from 6.23.0 to 6.24.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.23.0...v6.24.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.24.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-20 09:58:42 +01:00
Ken e422ab4292 [LLM] Formatting cleanup 2026-03-20 09:30:56 +01:00
Ken b7f826a2a7 [LLM] Formatting cleanup for better token usage 2026-03-19 13:54:11 +01:00
Ken 71dc4693a1 [LLM] Now prints all react-component documentation 2026-03-19 13:32:21 +01:00
Ken 4bb3ef19fc [LLM] Added llm.md route on root for testing (currently disabled) 2026-03-19 13:05:37 +01:00
Halvor Haugan c44f921b4c Fieldset: Adjust examples (#4742) 2026-03-19 12:23:58 +01:00
Ken d585c16164 [DataTable] Selection select all reset 2026-03-19 12:19:11 +01:00
Ken 91a5243c2c [DataTable] Selection hook initial setup 2026-03-19 09:50:19 +01:00
Ken 3322acde59 [DataTable] Working table with items 2026-03-18 16:11:59 +01:00
Ken 71dba0d15c [DataTable] Table with item-prop WIP 2026-03-18 15:37:50 +01:00
KenandHalvor Haugan 232ed45694 💄 Disabled token adjusted to 0.45 (#4734)
* 💄 Disabled token adjusted to 0.45

* Update .changeset/tidy-coats-hope.md

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-03-18 14:52:48 +01:00
Ken 84261202ce 🐛 Fixed mailto validation in sanity link schema 2026-03-18 14:24:59 +01:00
Ken 44c39ee6b8 [DataTable]: Selected demo cleanup 2026-03-18 14:03:59 +01:00
Ken 856afc3f78 [DataTable]: Selected state registry 2026-03-18 13:13:23 +01:00
Ken b7a6b3131e [DataTable]: Working selection states 2026-03-18 10:28:39 +01:00
Ken 8b5980b794 [DataTable]: Initial selected row config 2026-03-18 10:28:39 +01:00
Anniken Granberg 7b4a47d31b DataTable: dnd native skeleton 2026-03-18 08:52:29 +01:00
Anniken Granberg dc88ccbece DataTable: Move old dnd kit 2026-03-18 08:36:41 +01:00
Halvor Haugan aa4d610a50 Fieldset: variant:static on address examples 2026-03-17 15:54:14 +01:00
Halvor Haugan 3e6678fc8c Fieldset: Add example on hideLegend (#4739) 2026-03-17 15:36:21 +01:00
Ken edff0148ad [DataTable]: Resize event cleanup 2026-03-17 15:22:39 +01:00
Ken 5bc7adeff4 [DataTable]: Resize refactor 2026-03-17 15:22:39 +01:00
Ken 4d9e66d276 [DataTable]: Resize touch-events 2026-03-17 15:22:38 +01:00
Halvor Haugan 252aed6e07 Fieldset: Update JSDoc and add examples (#4738) 2026-03-17 15:08:35 +01:00
Halvor Haugan 2d70b8df7e ⬆️ Bump tar to 7.5.11 2026-03-17 15:06:01 +01:00
Ken 8f3e5072ae [DataTable]: DND anchor demo 2026-03-17 14:58:29 +01:00
Ken ab7f08850f [DataTable]: Added selectionMode prop (not implemented) 2026-03-16 16:31:01 +01:00
Ken f3f7fb797e [DataTable]: Added loading-component 2026-03-16 16:11:31 +01:00
Ken c20d5d7211 [DataTable]: Added emptystate-component 2026-03-16 15:51:56 +01:00
dependabot[bot] 182fbf9819 ⬆️ Bump the npm_and_yarn group across 2 directories with 1 update (#4736)
Bumps the npm_and_yarn group with 1 update in the /examples/astro directory: [tar](https://github.com/isaacs/node-tar).
Bumps the npm_and_yarn group with 1 update in the /examples/shadow-dom directory: [tar](https://github.com/isaacs/node-tar).


Updates `tar` from 7.5.10 to 7.5.11
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.10...v7.5.11)

Updates `tar` from 7.5.10 to 7.5.11
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v7.5.10...v7.5.11)

---
updated-dependencies:
- dependency-name: tar
  dependency-version: 7.5.11
  dependency-type: indirect
  dependency-group: npm_and_yarn
- dependency-name: tar
  dependency-version: 7.5.11
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 15:15:40 +01:00
dependabot[bot]andKen 95c58bacc6 ⬆️ Bump @floating-ui/react-dom from 2.1.7 to 2.1.8 (#4733)
Bumps [@floating-ui/react-dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/react-dom) from 2.1.7 to 2.1.8.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/react-dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/react-dom@2.1.8/packages/react-dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/react-dom"
  dependency-version: 2.1.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2026-03-16 15:14:49 +01:00
dependabot[bot] 942d98945d ⬆️ Bump eslint-plugin-testing-library from 7.15.4 to 7.16.0 (#4732)
Bumps [eslint-plugin-testing-library](https://github.com/testing-library/eslint-plugin-testing-library) from 7.15.4 to 7.16.0.
- [Release notes](https://github.com/testing-library/eslint-plugin-testing-library/releases)
- [Changelog](https://github.com/testing-library/eslint-plugin-testing-library/blob/main/release.config.js)
- [Commits](https://github.com/testing-library/eslint-plugin-testing-library/compare/v7.15.4...v7.16.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-testing-library
  dependency-version: 7.16.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-16 15:09:50 +01:00
KenandHalvor Haugan befae1e0a2 [Readmore] Added variants ghost and moderate (#4723)
* 🎉 WIP readmore

* ♻️ Readmore CSS refactor

* 🎉 Finishing up Readmore refactor and variant addition

* 🎉 Finishing up Readmore refactor and variant addition

* 📝 Update Readmore examples

* Update .changeset/fine-seals-rule.md

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 📝 Story and example updated

* Update @navikt/core/react/src/read-more/ReadMore.tsx

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

* 🐛 Miscalculated border-radius fixed

* 📝 Desc-texts

* 📝 Short and long readmore demo

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-03-16 15:08:10 +01:00
Ken 763ed480ca [DataTabke] Only add tabIndex when keyboardsupport is enabled 2026-03-16 15:00:17 +01:00
Halvor Haugan 03a0ec0d69 Playroom: allow-forms 2026-03-16 14:51:06 +01:00
Anniken Granberg 66cb8e7c14 DataTable: ops wrong type 2026-03-16 14:20:01 +01:00
Anniken Granberg e527923580 DataTabel: bad example of our own drag and drop 2026-03-16 14:15:21 +01:00
Ken 7009d899f1 [DataTable] Support starting with auto size when maxWidth is smaller than auto 2026-03-16 12:47:01 +01:00
Ken 8976136b3e [DataTable] style-forwarding 2026-03-16 10:45:02 +01:00
Ken 59dff16be0 [DataTable] Handle focus in header-row and col-span better 2026-03-16 10:37:27 +01:00
KenandHalvor Haugan 7074d96fba README update (#4726)
* 📝 README update

* 📝 Update contributing.md

* Update CONTRIBUTING.md

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2026-03-16 09:40:30 +01:00
Halvor Haugan b4df1bd349 DataTable: Sort button css adjustments 2026-03-13 23:01:22 +01:00
389 changed files with 21166 additions and 14623 deletions

No files matched your search

-5
View File
@@ -1,5 +0,0 @@
---
"@navikt/ds-react": patch
---
Dialog: Improved scrollbar handling when opening dialog-popup.
-5
View File
@@ -1,5 +0,0 @@
---
"@navikt/ds-react": patch
---
useDatepicker, useMonthpicker: Add JsDoc to validation object
-5
View File
@@ -1,5 +0,0 @@
---
"@navikt/ds-react": patch
---
DatePicker, MonthPicker: Removed controlled tabindex on Input-button based on open-state.
+1 -1
View File
@@ -13,4 +13,4 @@
- [ ] Exports (`@navikt/core/react/src/index.ts` and `@navikt/core/react/package.json`)
- [ ] New component? CSS import (`@navikt/core/css/index.css`)
- [ ] Breaking change? Update migration guide. Consider codemod.
- [ ] Changeset (Format: `<Component>: <gitmoji?> <Text>.` E.g. "Button: :sparkles: Add feature xyz.")
- [ ] Changeset (Format: `<Component>: <gitmoji?> <Text>` E.g. "Button: :sparkles: Add feature xyz")
+102 -203
View File
@@ -1,246 +1,145 @@
# Aksel – GitHub Copilot Instructions
# Aksel - Copilot Instructions
This file tells Copilot how to work inside the Aksel monorepo. Prefer existing patterns and symbols, keep changes minimal, and reference real files in this repo.
## Use this file first
## How to act in this monorepo (quick)
- Trust these instructions to narrow the search space, but still read the target code and nearest related files before editing.
- Optimize for local work. Prefer known paths, nearby patterns, and existing scripts over broad repo searches.
- Ignore release, deploy, changelog, CMS sync, and other remote/ops scripts unless the user asks.
- Edit only what’s asked. Don’t invent files/APIs or refactors.
- One file at a time. Provide a single coherent diff per file.
- Use existing exports, tokens, CSS layers, and patterns before adding new ones.
- When touching packages under `@navikt/*`, also update exports and stories nearby.
- Add or adjust tests and stories when behavior/visuals change.
- Link files with repo paths like `@navikt/react/src/...` or `aksel.nav.no/website/...`.
- Keep changes focused and minimal; avoid drive-by rewrites or formatting churn.
- Preserve public APIs unless the request explicitly calls for a breaking change (add a changeset if user-facing).
## How to use this file
## General code guidelines (Copilot)
- Use this file to narrow the search space, not to replace reading code.
- Before editing, read the target file and the nearest related files in the same folder such as `index.ts`, story, test, and package/root export files.
- Search wider only when nearby files do not answer the question.
## Agent mode
- Verify before you claim. Don’t speculate.
- Preserve unrelated code and existing structure.
- No apologies, no “I think”, no change summaries.
- Don’t ask to confirm info that’s already in context.
- Prefer explicit, descriptive names and follow current style.
- Favor performance and security; add robust error handling and safe logging.
- Keep functions small and focused; remove duplication.
- Replace hardcoded values with named constants when reasonable.
- Prefer composition over deep inheritance; keep modules cohesive.
- Default tone: short and answer-first. Aim for max 0–2 concise sentences where needed.
- Thinking and explanation process: Keep it short, omit whats not strictly necessary, and focus on the next edit.
- Avoid long explanations or multiple steps at once.
- Don't explain thinking process for each step, just do the next edit. Only add explanations when the user explicitly asks for it or when it's necessary to clarify a non-obvious change.
## Inline chat and editor completions
- Default tone: short and answer-first. Aim for 1–3 concise sentences before any code.
- Verify before you claim. Don’t speculate.
- Keep functions small and focused; remove duplication (rule of three).
- Show only what changes. Provide minimal diffs/snippets; don’t paste whole files or unrelated lines.
- Keep edits scoped to a single file unless explicitly asked to touch more.
- Use existing APIs, utilities, tokens, and patterns. Don’t add new deps unless requested.
- Preserve style: imports, naming, types, JSX patterns, token usage, CSS layers.
- Reference files and symbols with repo-relative paths and backticks, e.g. `@navikt/ds-react/src/...`.
- Extract requirements into a tiny checklist and proceed. Ask a question only when truly blocked.
- Avoid heavy formatting: bullets are OK; skip tables; use code fences only for code.
- For tests/visual changes: add/update the closest test/story next to the changed file.
- For Next.js: don’t mix `app/` and `pages/` in the same hierarchy; prefer server components where used; add "use client" only when required.
- For CSS/tokens: never hard-code colors/spacing; use tokens and existing layers.
- For performance/security: avoid unnecessary re-renders, side effects at module top-level, unsafe HTML, and leaking env vars.
## Repository overview
## Repo summary
Aksel is NAV’s design system: React components, CSS, design tokens, icons, tooling, and the documentation site. It’s a Yarn 4 workspaces monorepo.
- Large Yarn 4 workspaces monorepo for NAV's design system: public React/CSS/tokens/icons/stylelint/CLI packages plus docs site and playroom.
- Stack: TypeScript 6, React 19, Next.js 16, Storybook 10, Vitest 4, ESLint 9, Stylelint 17, Biome 2, Prettier 3.
- Runtime: Node 22+ recommended, Yarn 4.12.0.
- Important constraint: code under `@navikt/*` must stay React 17 API compatible. Do not use React 18/19-only APIs there.
- Languages: TypeScript, CSS, React, Next.js
- Package manager: Yarn v4 (packageManager: `yarn@4.4.0`)
- Build: Per-package TypeScript builds (run via root scripts)
- Tests: Vitest + React Testing Library
## Start and validate
Related files: `package.json`, `eslint.config.js`, `biome.json`, `tsconfig.json`.
1. `corepack enable`
2. `yarn install`
3. `yarn boot`
## Prerequisites
- Run `yarn boot` after first install and after `yarn clean`.
- Full install may need `NPM_AUTH_TOKEN` for GitHub Packages.
- Yarn 4 via Corepack is expected by the repo (`packageManager` field).
- Some maintenance scripts use Deno (for example `scripts/deno/changelog/createMainChangelog.ts`). Install Deno if you run those.
- Most packages are public. If you encounter 401s from GitHub Packages in a custom setup, set `NPM_AUTH_TOKEN` with `read:packages`.
For limited installs (no website), you can focus core packages:
Public-package-only install:
```bash
yarn workspaces focus @navikt/aksel-icons @navikt/ds-tokens @navikt/ds-css @navikt/ds-react @navikt/ds-tailwind @navikt/aksel @navikt/aksel-stylelint
```
## Repository structure (short)
## Definition of done
```
@navikt/
├─ core/react # @navikt/ds-react – React components
├─ core/css # @navikt/ds-css – CSS
├─ core/tokens # @navikt/ds-tokens – tokens
├─ core/tailwind # @navikt/ds-tailwind – Tailwind preset
├─ aksel-icons # @navikt/aksel-icons – icons
├─ aksel-stylelint # @navikt/aksel-stylelint – stylelint rules
└─ aksel # @navikt/aksel – CLI/tooling
- Behavior or visual change: update the implementation, closest story, and closest test.
- New public export: update the component `index.ts`, package `src/index.ts`, and `package.json` exports.
- User-facing package change: add a changeset unless the task says otherwise.
- Validate with the narrowest workspace command first; use root commands only for cross-workspace changes.
aksel.nav.no/
├─ website # Next.js documentation site
└─ playroom # Component playground
### Common local commands
examples/ # Example apps
scripts/ # Build/maintenance scripts
```
Always prefer using these commands that already exists in workspaces before running custom commands or doing manual steps. These are optimized for local development and validation. For example:
## Build and development
- `yarn boot` - build all workspaces
- `yarn test` - run all workspace tests
- `yarn lint` - eslint + stylelint + biome + cycle + version checks
- `yarn lint:eslint` / `yarn lint:css` / `yarn lint:biome`
- `yarn storybook` - root Storybook on `localhost:6006`
- `yarn storybook:aksel` - website/example Storybook on `localhost:6007`
- `yarn storybook:test` - Storybook browser tests, slow, uses Playwright/Firefox
- `yarn dev` - website dev server on `localhost:3000`
- `yarn clean` - remove build artifacts
- `yarn workspace @navikt/ds-react build`
- `yarn workspace @navikt/ds-react test`
- `yarn workspace website test`
- `yarn workspace playroom sync-imports`
Setup:
### Validated locally
```bash
yarn && yarn boot
```
- Works: `yarn boot`, `yarn test`, `yarn storybook --ci --smoke-test`, `yarn storybook:aksel --ci --smoke-test`
- Caveat: `yarn lint` and `yarn lint:eslint` can fail if playroom imports are stale. Fix with `yarn workspace playroom sync-imports`.
Useful scripts (root `package.json`):
## Where to edit
```bash
yarn boot # Build all workspaces (topological)
yarn storybook # Storybook dev (port 6006)
yarn storybook:aksel # Storybook with website config (port 6007)
yarn dev # Run documentation website
yarn test # Run workspace tests
yarn lint # ESLint + Stylelint (full install recommended)
yarn clean # Clean generated files
yarn changeset # Create a changeset
yarn changelog # Generate main changelog (Deno)
yarn biome:lint # Optional extra linting with Biome
```
- `@navikt/core/react/` - `@navikt/ds-react`
- `src/<component>/<Component>.tsx`
- `src/<component>/index.ts`
- `src/<component>/*.stories.tsx`
- `src/index.ts`
- `package.json` exports map for new public components
- `@navikt/core/css/src/` - component CSS
- `@navikt/core/tokens/src/` - design token source
- `@navikt/core/tailwind/` - Tailwind preset
- `@navikt/aksel-icons/icons/` - source SVGs; `src/` is generated
- `@navikt/aksel-stylelint/src/` - Stylelint rules/config
- `@navikt/aksel/src/` - CLI and codemods
- `aksel.nav.no/website/` - Next.js docs site
- `aksel.nav.no/playroom/` - playroom and generated imports
- `examples/` - example apps
- `scripts/` - shared repo scripts
- Root references: `README.md`, `CONTRIBUTING.md`, `aksel.nav.no/README.md`, `package.json`, `eslint.config.js`, `stylelint.config.mjs`, `biome.json`, `tsconfig.json`, `tsconfig.build.json`, `.storybook/`, `.github/workflows/build-validation.yml`
Note: `yarn lint` runs across the repo and may require full install (website ESLint plugins).
## Coding defaults
## CI and validation
- Keep diffs small. No drive-by refactors, formatting churn, or new dependencies unless asked.
- Read the full file and copy the nearest existing pattern before changing code.
- Keep public APIs stable. Prefer additive props and exports.
- In `@navikt/*`, import React in TSX files; root JSX runtime is classic.
- Use named exports with explicit type exports.
- Keep `forwardRef`, `className`, `...rest`, and `as`/`OverridableComponent` patterns when the surrounding component uses them.
- Reuse internal helpers instead of re-implementing them: `cl`, `composeEventHandlers`, `useId`, `omit`, `useClientLayoutEffect`, `useEventListener`.
- Use `node:` imports for Node builtins.
- Never import from `esm/` or `cjs/` build output.
- Keep import order consistent: `@navikt/*`, `@/*`, then relative. Let Prettier handle sorting.
- Preserve or add JSDoc for public props/components when changing public APIs.
- Pre-commit (Husky): `lint-staged`, plus internal version sync checks.
- CI typically runs: lint, unit tests, example/website checks, and Chromatic when applicable.
## React and ds-react specifics
Common failure causes:
- Component `index.ts` files in `@navikt/core/react/src/**` start with `"use client"`.
- When adding or exposing a public component, keep these in sync:
- component `index.ts`
- `@navikt/core/react/src/index.ts`
- `@navikt/core/react/package.json` exports
- Do not use React 18/19-only APIs under `@navikt/*`. Use internal helpers like `useId`.
- Missing dependencies in a focused install when running repo-wide scripts
- TypeScript errors in dependent workspaces
- Stylelint token checks failing due to missing token imports
## CSS and tokens
Quality gates to check locally before opening a PR:
- Never hardcode colors, spacing, radius, or shadows. Use tokens only.
- Public tokens use `--ax-*`. Internal component variables use `--__axc-*`.
- Follow existing CSS nesting, `data-*` selectors, `focus-visible`, `forced-colors`, and reduced-motion patterns.
- Prettier formats; Biome is lint-only.
- Build: `yarn boot` succeeds without TS errors.
- Lint/format: `yarn lint` (and optional `yarn biome:lint`) passes.
- Tests: `yarn test` for changed workspaces are green.
- Storybook/website (when UI changes): boots locally without errors.
## Stories, tests, website
## Tests
- Framework: Vitest (jsdom where needed)
- Website config: `aksel.nav.no/website/config/vitest.config.ts`
- Test locations: `**/__tests__/**` and `**/*.test.*`
- Add tests for new behavior and keep existing tests passing
- Prefer small, focused tests. Cover the happy path and 1–2 edge cases.
- Use Testing Library queries that reflect user intent (role/name), avoid brittle selectors.
## Linting and formatting
- ESLint config lives at root: `eslint.config.js` (React, Next.js, Storybook, Testing Library, custom rules)
- Stylelint is configured in root `package.json` with `@navikt/aksel-stylelint`
- Tokens are validated via Stylelint and `csstools/value-no-unknown-custom-properties`
- Biome config: `biome.json` (optional extra lint/format)
- Prettier uses import-sort; website adds Tailwind plugin via override
- Avoid disabling lint rules unless necessary; if you must, comment why.
## Packages and exports
- Synchronized versions: `@navikt/ds-react`, `@navikt/ds-css`, `@navikt/aksel-icons`, `@navikt/ds-tokens`, `@navikt/ds-tailwind`
- Typical package layout:
```
src/
├─ index.ts # Package exports
└─ <component>/
├─ index.ts # Component exports
├─ <component>.tsx # Implementation
└─ <component>.stories.tsx
```
When adding/editing components in `@navikt/react`:
- Update exports in `src/index.ts` and per-component `index.ts`
- Add/maintain stories and tests next to the component
- Follow existing props, theming, and token patterns
- Keep props stable; prefer additive changes. Deprecate before removal when possible.
- Ensure tree-shakeability; avoid side effects at module top-level.
## Common workflows
Add a new component
1. Implement under `@navikt/react/src/...`
2. Add stories and tests
3. Export from the package `index.ts`
4. Run `yarn boot` and fix types/lint
5. Create a changeset (`yarn changeset`)
Component change checklist (quick):
- [ ] Implementation updated under `@navikt/react/src/...`
- [ ] Exports updated (`src/index.ts` and component `index.ts`)
- [ ] Stories updated/added and render without errors
- [ ] Tests updated/added and passing (Vitest)
- [ ] Tokens/CSS use existing variables and layers (no hard-coded values)
- [ ] Changeset added if user-facing (version bump and notes)
Modify an existing component
1. Keep the public API stable unless explicitly requested
2. Update tests if behavior changes; update stories if visuals change
3. Add a changeset for user-facing changes
Troubleshooting
1. `yarn clean && yarn boot`
2. Check workspace dependency build order/issues
3. If focusing workspaces, avoid running repo-wide scripts that depend on the website
## Theming and tokens
- Use design tokens and CSS layers; avoid hard-coded colors/spacing.
- Stylelint enforces token usage; unknown/missing custom properties will fail lint.
## Website (Next.js)
- The website uses Next.js 15 and contains both `app/` and `pages/`. Place new files in the router that matches the surrounding code.
- Prefer server components where already used; mark client components with `"use client"` only when needed.
- Use Next Image, metadata APIs, and established utilities already in `aksel.nav.no/website`.
- Logging uses Next logger/pino; follow patterns in `aksel.nav.no/website` (see `next-logger.config.js`).
- Use existing route conventions and file organization; don’t mix `app/` and `pages/` in the same hierarchy.
- For Tailwind, prefer the shared preset `@navikt/ds-tailwind` and follow website `tailwind.config.js` patterns.
## Versioning and releases
- Use Changesets: `yarn changeset` and the root scripts:
- `yarn create-version` (applies versions, updates changelog, reinstalls)
- `yarn release` (boots, docgen, publish, git release helper)
- Main changelog script: `scripts/deno/changelog/createMainChangelog.ts`
## Answer snippets (for Copilot)
- Build: “Run yarn boot” (see root `package.json`)
- Storybook: “Run yarn storybook” (or `yarn storybook:aksel` for the website config)
- Lint/format: “Run yarn lint” (full install recommended) and optional `yarn biome:lint`
- Versioning: “Run yarn changeset, then yarn create-version”
- Theming: “Import @navikt/ds-css in global CSS”
## Code reviews (for Copilot)
- Summarize the pull-request on maximum two sentences
- Avoid listing all changes, focus on the most important ones
- Check the description against the actual changes
- Ensure the PR title is descriptive and follows the conventional commit format
- Look for: correctness, style, performance, security, tests, documentation
- Check: existing patterns, exports, tokens, CSS layers
- Make sure import paths are correct, updated and use existing aliases where possible
- When components are changed, ensure stories and tests are updated accordingly
- When components are changed, make sure related examples for website and playroom are updated
- Make sure changes made to packages under `@navikt/` has a related changeset where relevant
### Extra review tips
- Watch for unnecessary bundle impact (large deps, dynamic imports, side effects).
- Confirm a11y basics: semantic elements, labels, focus order, keyboard support.
- Check security footguns: unsafe HTML, unescaped data, leaking env vars, weak CSP assumptions.
- Update the closest story and test whenever behavior or visuals change.
- Use Testing Library queries by role and name.
- Stories live next to components and use `@storybook/react-vite`.
- For component work, prefer Storybook over `yarn dev`.
- `aksel.nav.no/website/pages/eksempler/**` and `pages/templates/**` feed the website and Storybook. In these files, only import from `@navikt/*` and `react`.
- The website uses both `app/` and `pages/`; stay inside the router already used nearby.
- `yarn storybook:aksel` works for website examples/templates without Sanity secrets. `yarn dev` may need website env values such as `SANITY_READ_NO_DRAFTS`.
+2 -12
View File
@@ -8,7 +8,8 @@ updates:
- package-ecosystem: npm
directory: /
exclude-paths:
- "examples/**"
- "examples/astro/package.json"
- "examples/shadow-dom/package.json"
schedule:
interval: weekly
day: monday
@@ -39,17 +40,6 @@ updates:
- "vitest"
- "@vitest/*"
- package-ecosystem: npm
directory: /examples
schedule:
interval: weekly
day: monday
time: "04:00"
groups:
all-deps:
patterns:
- "*"
- package-ecosystem: github-actions
directory: "/"
schedule:
@@ -0,0 +1,11 @@
description: "Use for JS/TS code in this repo."
applyTo: "**/\*.tsx", "**/_.jsx", "\*\*/_.ts", "\*_/_.js"
---
# JS/TS instructions
- Prefer `for...of` over `Array.forEach`.
- Prefer named exports; keep type exports separate from value exports.
- Group exports at the bottom: values first, then types.
- In `*.stories.*`, keep the default export at the top.
@@ -0,0 +1,13 @@
description: "Use for ds-react components and component CSS."
applyTo: "@navikt/core/react/src/**", "@navikt/core/css/src/**"
---
# ds-react and component instructions
- Read the full component folder before editing.
- Preserve the surrounding `forwardRef`, `className`, `...rest`, and `as`/`OverridableComponent` patterns.
- Keep `@navikt/*` code React 17 API compatible.
- Use tokens, not hardcoded component values.
- If behavior or visuals change, update the nearest story and test.
- If a public component changes, keep component exports, package exports, and root exports in sync.
@@ -0,0 +1,11 @@
description: "Use for tests and stories."
applyTo: "**/_.test._", "**/\*.stories.tsx"
---
# Testing and Storybook instructions
- Prefer story `play` functions and `yarn storybook:test` for real user flows; use Vitest for logic and non-browser cases.
- Prefer focused assertions over snapshots unless nearby tests already use snapshots.
- Cover the main path and one or two meaningful edge cases.
- If UI behavior changes, update the nearest story and test in the same change.
@@ -0,0 +1,14 @@
description: "Use for website and playroom work."
applyTo:
- "aksel.nav.no/website/\*\*"
- "aksel.nav.no/playroom/\*\*"
---
# Website and playroom instructions
- Stay inside the router already used nearby; do not mix `app/` and `pages/` patterns in the same area.
- In `aksel.nav.no/website/pages/eksempler/**` and `aksel.nav.no/website/pages/templates/**`, only import from `@navikt/*` and `react`.
- Reuse nearby website utilities and patterns before adding abstractions.
- Prefer `yarn storybook:aksel` for examples/templates; use `yarn dev` only for app-only behavior.
@@ -1,18 +1,25 @@
name: Backup sanity dateset to gcp
name: Backup Sanity dataset
on:
workflow_dispatch:
schedule:
# 12.00 every 3 days
- cron: "0 0 */3 * *"
permissions:
contents: read
jobs:
execute:
name: Export and upload Sanity backup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0 # Required to retrieve git history
fetch-depth: 1
- uses: actions/setup-node@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: yarn
@@ -28,11 +35,13 @@ jobs:
env:
SANITY_READ: ${{ secrets.SANITY_READ }}
- name: Upload GCP bucket
- name: Authenticate with GCP
uses: "google-github-actions/auth@v3"
with:
credentials_json: "${{ secrets.gcp_credentials_prod }}"
- uses: "google-github-actions/upload-cloud-storage@v3"
- name: Upload backup to GCS bucket
uses: "google-github-actions/upload-cloud-storage@v3"
with:
path: ./aksel.nav.no/website
destination: "aksel-website-prod/backups"
@@ -1,4 +1,4 @@
name: E2E / Playwright Tests
name: E2E tests (Playwright)
on:
push:
branches: [main, next]
@@ -21,7 +21,7 @@ permissions:
jobs:
prebuild-app-for-playwright:
name: "Prebuild app for Playwright tests"
name: Build app for Playwright
runs-on: ubuntu-latest
env:
IMAGE_NAME: ${{ github.repository }}-e2e
@@ -59,7 +59,7 @@ jobs:
run-playwright:
needs: [prebuild-app-for-playwright]
name: Playwright shard ${{ matrix.shardIndex }}
name: Playwright shard ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.58.1-noble
@@ -111,6 +111,7 @@ jobs:
retention-days: 1
merge-reports:
name: Merge Playwright reports
if: ${{ !cancelled() }}
needs: [run-playwright]
runs-on: ubuntu-latest
@@ -1,4 +1,4 @@
name: CI
name: Validation (Lint, Tests)
on:
push:
@@ -8,9 +8,16 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
name: "Linter: eslint, stylelint"
name: Lint (ESLint, Stylelint etc.)
runs-on: ubuntu-latest
steps:
- name: Checkout code
@@ -27,7 +34,7 @@ jobs:
run: yarn lint
validate-examples:
name: "Validate Aksel.nav.no component examples"
name: Validate component examples
runs-on: ubuntu-latest
steps:
- name: Checkout code
@@ -44,7 +51,7 @@ jobs:
run: yarn validate:eksempler
test:
name: "Tests: Unit and integration"
name: Unit and integration tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
@@ -61,7 +68,7 @@ jobs:
run: yarn test
ui:
name: "Tests: UI"
name: UI tests (Storybook)
runs-on: ubuntu-latest
timeout-minutes: 10
container:
@@ -1,4 +1,4 @@
name: Visual Regression Tests
name: Visual regression (Chromatic)
on:
push:
@@ -19,6 +19,7 @@ concurrency:
jobs:
chromatic:
name: Run Chromatic
runs-on: ubuntu-latest
permissions:
issues: write
@@ -47,7 +48,7 @@ jobs:
buildScriptName: "build:storybook-chromatic"
onlyChanged: true
untraced: "**/package.json|yarn.lock|**/*.md"
externals: "**/core/css/*.css|**/core/css/baseline/*.css|**/core/css/form/*.css|**/core/css/primitives/*.css"
externals: "**/core/css/src/**/*.css"
traceChanged: true
env:
STORYBOOK_GITHUB_SHA: ${{ github.sha }}
@@ -1,4 +1,4 @@
name: Bundle check against main branch
name: Bundle check (main branch)
on:
pull_request:
@@ -24,12 +24,12 @@ jobs:
run: echo "should-run=${{ !contains(github.event.pull_request.title, 'Version Packages') }}" >> $GITHUB_OUTPUT
analyze-trunk:
name: "Analyzing main branch"
name: Analyze main branch
runs-on: ubuntu-latest
needs: check-title
if: ${{ needs.check-title.outputs.should-run == 'true' }}
steps:
- name: Checkout main-branch
- name: Checkout main branch
uses: actions/checkout@v6
with:
fetch-depth: 1
@@ -52,12 +52,12 @@ jobs:
retention-days: 1
analyze-local:
name: "Analyzing PR branch"
name: Analyze PR branch
runs-on: ubuntu-latest
needs: check-title
if: ${{ needs.check-title.outputs.should-run == 'true' }}
steps:
- name: Checkout main-branch
- name: Checkout PR branch
uses: actions/checkout@v6
with:
fetch-depth: 1
@@ -79,7 +79,7 @@ jobs:
retention-days: 1
compare-against-trunk:
name: "Analyzing PR branch and comparing against main"
name: Compare bundles (PR vs main)
runs-on: ubuntu-latest
needs: [analyze-trunk, analyze-local]
steps:
@@ -117,7 +117,7 @@ jobs:
retention-days: 1
update-comment:
name: "Create or update PR comment with results"
name: Post PR comment with results
runs-on: ubuntu-latest
needs: [compare-against-trunk]
permissions:
+4 -4
View File
@@ -1,4 +1,4 @@
name: Bundle check against npm
name: Bundle check (npm)
on:
pull_request:
@@ -24,12 +24,12 @@ jobs:
run: echo "should-run=${{ contains(github.event.pull_request.title, 'Version Packages') }}" >> $GITHUB_OUTPUT
analyze:
name: "Analyzing npm packages"
name: Analyze npm packages
runs-on: ubuntu-latest
needs: check-title
if: ${{ needs.check-title.outputs.should-run == 'true' }}
steps:
- name: Checkout main-branch
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 1
@@ -54,7 +54,7 @@ jobs:
retention-days: 1
update-comment:
name: "Create or update PR comment with results"
name: Post PR comment with results
runs-on: ubuntu-latest
needs: [analyze]
permissions:
@@ -1,4 +1,4 @@
name: "Update remote token config for figma variables plugin"
name: Upload Figma token config to CDN
on:
workflow_dispatch:
@@ -10,6 +10,7 @@ on:
jobs:
upload:
name: Build and upload token config
runs-on: ubuntu-latest
permissions:
@@ -17,11 +18,13 @@ jobs:
id-token: "write"
steps:
- uses: actions/checkout@v6
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-depth: 1
- uses: actions/setup-node@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: yarn
@@ -35,7 +38,8 @@ jobs:
- name: Build tokens
run: yarn workspace @navikt/ds-tokens build
- id: upload
- name: Upload config to CDN
id: upload
uses: nais/deploy/actions/cdn-upload/v2@master
with:
team: designsystem
@@ -46,5 +50,6 @@ jobs:
source_keep_parent_name: false
no_cache_paths: "@navikt/tokens/figma-config.json"
- run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
- name: Log uploaded file
run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
shell: bash
@@ -1,4 +1,4 @@
name: "push-to-cdn"
name: Upload fonts to CDN
on:
workflow_dispatch:
@@ -10,16 +10,19 @@ on:
jobs:
upload:
name: Upload fonts to CDN
runs-on: ubuntu-latest
permissions:
contents: "read"
id-token: "write"
contents: read
id-token: write
steps:
- uses: "actions/checkout@v6"
- name: Checkout code
uses: "actions/checkout@v6"
- id: upload
- name: Upload fonts to CDN
id: upload
uses: nais/deploy/actions/cdn-upload/v2@master
with:
team: aksel
@@ -28,5 +31,6 @@ jobs:
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
- run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
- name: Log uploaded file
run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
shell: bash
+26
View File
@@ -0,0 +1,26 @@
name: Cleanup E2E Docker images
on:
schedule:
- cron: "0 4 * * 1"
workflow_dispatch:
permissions:
packages: write
jobs:
cleanup:
runs-on: ubuntu-latest
strategy:
matrix:
package-name:
- aksel-e2e
steps:
- name: Delete old container images
uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # actions/delete-package-versions@v5
with:
package-name: ${{ matrix.package-name }}
package-type: container
delete-only-untagged-versions: false
min-versions-to-keep: 1
token: ${{ secrets.GITHUB_TOKEN }}
@@ -1,10 +1,15 @@
name: Deploy aksel.ansatt.dev.nav.no
name: Deploy dev (aksel.ansatt.dev.nav.no)
on:
workflow_dispatch:
push:
branches:
- next
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
build_and_deploy:
name: Build and deploy to dev-gcp
@@ -13,6 +18,7 @@ jobs:
packages: "write"
contents: "read"
id-token: "write"
deployments: "write"
steps:
- name: Checkout code
uses: actions/checkout@v6
@@ -29,10 +35,8 @@ jobs:
sanity_read_token: ${{ secrets.SANITY_READ }}
sanity_read_no_drafts_token: ${{ secrets.SANITY_READ_NO_DRAFTS }}
- name: Get complete tag
run: echo "TAG=DEV-$( date +%s )" >> $GITHUB_ENV
- uses: nais/docker-build-push@v0
- name: Build and push Docker image
uses: nais/docker-build-push@v0
id: docker-push
with:
team: designsystem
@@ -1,4 +1,5 @@
name: Deploy aksel.nav.no
name: Deploy prod (aksel.nav.no)
on:
push:
branches:
@@ -6,15 +7,20 @@ on:
paths:
- "aksel.nav.no/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
env:
IMAGE: ghcr.io/navikt/aksel
jobs:
sync_data_with_sanity:
name: Update component data
name: Sync data to Sanity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Checkout code
uses: actions/checkout@v6
- name: Setup project
uses: ./.github/actions/setup
@@ -24,7 +30,7 @@ jobs:
- name: Run ts-docgen
run: yarn docgen
- name: Update sanity sync
- name: Update Sanity
env:
SANITY_WRITE: ${{ secrets.SANITY_WRITE }}
run: yarn workspace aksel.nav.no sanity:update
@@ -36,6 +42,7 @@ jobs:
packages: "write"
contents: "read"
id-token: "write"
deployments: "write"
steps:
- name: Checkout code
uses: actions/checkout@v6
@@ -55,10 +62,8 @@ jobs:
sanity_deploy_studio: ${{ secrets.SANITY_DEPLOY_STUDIO }}
next_encryption_key: ${{ secrets.NEXT_ENCRYPTION_KEY }}
- name: Get complete tag
run: echo "TAG=PROD-$( date +%s )" >> $GITHUB_ENV
- uses: nais/docker-build-push@v0
- name: Build and push Docker image
uses: nais/docker-build-push@v0
id: docker-push
with:
team: designsystem
@@ -1,10 +1,15 @@
name: Deploy aksel-v7.nav.no
name: Deploy prod (aksel-v7.nav.no)
on:
workflow_dispatch:
push:
branches:
- v7-aksel.nav.no
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
build_and_deploy:
name: Build and deploy to prod-gcp
@@ -38,10 +43,8 @@ jobs:
run: cd v7-aksel.nav.no && yarn build
shell: bash
- name: Get complete tag
run: echo "TAG=PROD-V7-$( date +%s )" >> $GITHUB_ENV
- uses: nais/docker-build-push@v0
- name: Build and push Docker image
uses: nais/docker-build-push@v0
id: docker-push
with:
team: designsystem
+10 -7
View File
@@ -1,4 +1,4 @@
name: Release
name: Release packages
on:
push:
@@ -13,8 +13,8 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
build:
name: "Release packages"
if: ${{!contains(github.event.head_commit.message, '[ci skip]')}}
name: Release packages
if: ${{ !contains(github.event.head_commit.message, '[ci skip]') }}
runs-on: ubuntu-latest
permissions:
id-token: "write"
@@ -22,17 +22,20 @@ jobs:
packages: "write"
pull-requests: "write"
steps:
- uses: actions/checkout@v6
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: lts/*
cache: yarn
cache-dependency-path: "yarn.lock"
- uses: denoland/setup-deno@v2
- name: Setup Deno
uses: denoland/setup-deno@v2
with:
deno-version: v1.x
@@ -55,7 +58,7 @@ jobs:
# Needed for push to main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Creating .npmrc
- name: Create .npmrc for GPR
run: |
cat << EOF > "$HOME/.npmrc"
@navikt:registry=https://npm.pkg.github.com
-29
View File
@@ -1,29 +0,0 @@
# https://github.com/actions/stale
name: Mark stale issues
on:
schedule:
- cron: "31 3 * * *"
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-issue-stale: 120
days-before-pr-stale: -1
days-before-close: 30
any-of-labels: "Besvart"
stale-issue-message: |-
Hei! Det ser ut som det ikke har vært aktivitet her på en stund. Etter 30 dager vil saken bli lukket automatisk.
Om saken fortsatt er relevant eller du har oppdateringer, vil en kommentar hindre at den lukkes. Du kan alltids åpne den igjen hvis det skulle være nødvendig!
stale-issue-label: "no-issue-activity"
ascending: true
operations-per-run: 200
+11 -5
View File
@@ -1,16 +1,22 @@
name: Redeploy Naisjob (update-article-views)
name: Update article views (Naisjob)
on:
workflow_dispatch:
jobs:
execute:
name: Build and deploy article views job
runs-on: ubuntu-latest
permissions:
id-token: "write"
contents: read
id-token: write
steps:
- uses: actions/checkout@v6
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: nais/docker-build-push@v0
- name: Build and push Docker image
uses: nais/docker-build-push@v0
id: docker-push
with:
team: designsystem
@@ -19,7 +25,7 @@ jobs:
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
- name: start naisjob prod-gcp
- name: Deploy Naisjob to prod-gcp
uses: nais/deploy/actions/deploy@master
env:
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
+1 -1
View File
@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname $0)/_/husky.sh"
yarn lint-staged && yarn tsx ./scripts/in-sync-versions.ts
yarn lint-staged
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
. "$(dirname $0)/_/husky.sh"
# Only run tests when pushing to main branch
while read local_ref local_sha remote_ref remote_sha; do
if [ "$remote_ref" = "refs/heads/main" ]; then
echo "Pushing to main branch - running tests...\n"
yarn test
exit $?
fi
done
exit 0
+4 -4
View File
@@ -1,4 +1,4 @@
import { StorybookConfig } from "@storybook/react-vite";
import { defineMain } from "@storybook/react-vite/node";
import FG from "fast-glob";
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
@@ -17,7 +17,7 @@ const includeWebsiteStories = process.env.WITH_WEBSITE === "true";
const indexRegex = /export const args = {\s+index: (\d+),/;
export default {
export default defineMain({
experimental_indexers: (indexers) => {
// Changes here might need to be reflected in aksel.nav.no/website/.storybook/main.ts
const customIndexer = async (fileName: string, opts: any) => {
@@ -126,9 +126,9 @@ export default {
features: {
actions: false,
},
} satisfies StorybookConfig;
});
function getAbsolutePath(value: string): any {
function getAbsolutePath(value: string) {
return dirname(require.resolve(join(value, "package.json")));
}
+8 -4
View File
@@ -1,5 +1,8 @@
import { withThemeByClassName } from "@storybook/addon-themes";
import { Preview } from "@storybook/react-vite";
import addonA11y from "@storybook/addon-a11y";
import addonDocs from "@storybook/addon-docs";
import addonThemes, { withThemeByClassName } from "@storybook/addon-themes";
import addonVitest from "@storybook/addon-vitest";
import { definePreview } from "@storybook/react-vite";
import React, { useEffect } from "react";
import "../@navikt/core/css/src/data-table.css";
import "../@navikt/core/css/src/data-token-filter.css";
@@ -55,7 +58,8 @@ const TypoDecorator = ({
return <>{children}</>;
};
export default {
export default definePreview({
addons: [addonA11y(), addonThemes(), addonDocs(), addonVitest()],
parameters: {
options: {
storySort: {
@@ -132,4 +136,4 @@ export default {
defaultTheme: "light",
}),
],
} satisfies Preview;
});
+4 -4
View File
@@ -1,13 +1,13 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"denoland.vscode-deno",
"stylelint.vscode-stylelint",
"biomejs.biome",
"esbenp.prettier-vscode",
"denoland.vscode-deno",
"github.vscode-github-actions",
"ms-playwright.playwright",
"sanity-io.vscode-sanity",
"stylelint.vscode-stylelint",
"vunguyentuan.vscode-css-variables",
"bradlc.vscode-tailwindcss"
"vunguyentuan.vscode-css-variables"
]
}
+2 -5
View File
@@ -1,8 +1,5 @@
{
"cssVariables.lookupFiles": [
"@navikt/core/tokens/dist/tokens.css",
"@navikt/core/tokens/dist/darkside/tokens.css"
],
"cssVariables.lookupFiles": ["@navikt/core/tokens/dist/tokens.css"],
"eslint.problems.shortenToSingleLine": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.watcherExclude": {
@@ -12,6 +9,6 @@
"**/cjs": true
},
"playwright.reuseBrowser": true,
"typescript.tsdk": "node_modules/typescript/lib",
"js/ts.tsdk.path": "node_modules/typescript/lib",
"deno.enablePaths": ["./scripts/deno"]
}
+2
View File
@@ -12,8 +12,10 @@ npmScopes:
npmAuthToken: "${NPM_AUTH_TOKEN:-}"
npmRegistryServer: "https://npm.pkg.github.com"
enableScripts: false
defaultSemverRangePrefix: ""
npmMinimalAgeGate: "7d"
npmPreapprovedPackages: ["@navikt/*"]
enableTelemetry: false
yarnPath: .yarn/releases/yarn-4.12.0.cjs
+12
View File
@@ -1,5 +1,17 @@
# @navikt/aksel-icons
## 8.10.2
## 8.10.1
## 8.10.0
## 8.9.1
## 8.9.0
## 8.8.0
## 8.7.0
## 8.6.0
+5 -38
View File
@@ -2,44 +2,11 @@
## Foreslå nye ikoner
Om du ikke finner et ikonet du leter etter kan du [åpne et issue på github](https://github.com/navikt/aksel/issues/new?labels=nytt+✨%2Cikoner+🖼%2Cforespørsel+🥰&template&template=new-icon.yaml&title=%5BNytt+ikon%5D%3A+).
Om du ikke finner ikonet du leter etter kan du [lage et issue på GitHub](https://github.com/navikt/aksel/issues/new?labels=nytt+✨%2Cikoner+🖼%2Cforespørsel+🥰&template=new-icon.yaml&title=%5BNytt+ikon%5D%3A+).
## Oppdatere ikon
Hvis du tenker et ikon fortjener en oppdatering eller er utdatert kan [du foreslå det her.](https://github.com/navikt/aksel/issues/new?labels=forespørsel+🥰&template=update-icon.yml&title=%5BInnspill+til+ikon%5D%3A+)
## Legge til nye ikoner selv
Hvis du selv ønsker å legge til nye ikoner kan du kopiere filenes fra `/template` og legge de inn i `/icons` med egen data. Alle ikonene har naming-format `PascalCase`. Alle ikonene har 1 SVG-fil og 1 tilhørende YML-fil.
### Svg
- Sizing, width og height må være 24x24: `width="24" height="24" `
- Viewbox: `viewBox="0 0 24 24"`
- Fill på path: `fill="#202733"`
### Yml
```yml
name: Template # Samme som filnavn
category: Template category # Hovedkategori
sub_category: Sub category # Underkategori
keywords: # Samling med søkeord
- template1
- template2
- template3
variant: Stroke # Stroke eller Fill
created_at: 01.01.2023 # Dato for opprettelse
```
### Publisere oppdatering
Når du har lagt til nye ikoner kan du opprette en pull request. Denne vil bli automatisk testet og så gått gjennom av Aksel-teamet.
Legg gjerne til en `changeset` ved å kjøre `yarn changeset` i terminalen. Dette vil gi oss bedre oversikt over hva som er endret i endringslogger og automatisk bumpe pakke-versjonen ved merge.
#### Teste nytt ikon
Hvis du ønsker å teste om alt stemmer, både i `svg` og `yml` før du lager en PR kan du kjøre `yarn && cd navikt/aksel-icons && yarn test` i terminalen lokalt.
Hvis du tenker et ikon fortjener en oppdatering eller er utdatert kan [du foreslå det her](https://github.com/navikt/aksel/issues/new?labels=forespørsel+🥰&template=update-icon.yml&title=%5BInnspill+til+ikon%5D%3A+).
## Design av nye ikoner
@@ -50,9 +17,9 @@ Hvis du ønsker å teste om alt stemmer, både i `svg` og `yml` før du lager en
### Stroke (linje)
- Ikonet må bestå av kun linjer
- Linjene skal være 1.5px, center-aligned
- Ikonet må bestå av kun linjer.
- Linjene skal være 1.5px, center-aligned.
### Fill (fylt)
- Ikoner hvor shapes kan fylles, bør fylles
- Ikoner hvor shapes kan fylles, bør fylles.
@@ -14,8 +14,8 @@
"@navikt/ds-css": "*",
"@navikt/ds-react": "*",
"fuse.js": "^7.0.0",
"react": "19.2.4",
"react-dom": "19.2.4"
"react": "19.2.5",
"react-dom": "19.2.5"
},
"devDependencies": {
"@figma/plugin-typings": "^1.100.2",
@@ -24,8 +24,8 @@
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "^5.1.0",
"typescript": "5.9.3",
"vite": "^7.2.4",
"typescript": "6.0.2",
"vite": "^7.3.2",
"vite-plugin-singlefile": "^2.3.0",
"vite-plugin-svgr": "^4.2.0"
}
@@ -155,7 +155,7 @@ const App = () => {
<div className="icons-wrapper">
{sub.icons.map((i) => {
// biome-ignore lint/performance/noDynamicNamespaceImportAccess: We do not know which icon will be rendered at build time
const T = Icons[`${i.id}Icon`]; // eslint-disable-line import/namespace
const T = Icons[`${i.id}Icon`];
if (T === undefined) {
return null;
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-icons",
"version": "8.7.0",
"version": "8.10.2",
"author": "Aksel | Nav",
"homepage": "https://aksel.nav.no/ikoner",
"repository": {
@@ -82,14 +82,14 @@
"fast-glob": "3.3.3",
"hast-util-select": "6.0.4",
"js-yaml": "^4.1.1",
"lodash": "4.17.23",
"lodash": "4.18.1",
"prettier": "3.8.1",
"react": "19.2.4",
"react": "19.2.5",
"rehype-parse": "9.0.1",
"tsc-alias": "1.8.16",
"tsx": "^4.20.6",
"typescript": "5.9.3",
"typescript": "6.0.2",
"unified": "11.0.5",
"vitest": "4.0.18"
"vitest": "4.1.4"
}
}
+2
View File
@@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"ignoreDeprecations": "6.0",
"rootDir": "./src",
"outDir": "./dist/react/cjs",
"moduleResolution": "node",
"module": "commonjs",
+1 -1
View File
@@ -14,7 +14,7 @@ function useGlobalId(idOverride?: string): string | undefined {
// We can't use it server-side.
// If you want to use random values please consider the Birthday Problem: https://en.wikipedia.org/wiki/Birthday_problem
globalId += 1;
setDefaultId(`aksel-icon-${globalId}`);
setDefaultId(`aksel-icon-${globalId}`); // eslint-disable-line react-hooks/set-state-in-effect
}
}, [defaultId]);
return id;
+16
View File
@@ -1,5 +1,21 @@
# @navikt/aksel-stylelint
## 8.10.2
## 8.10.1
## 8.10.0
## 8.9.1
## 8.9.0
## 8.8.0
### Patch Changes
- ReadMore: Deprecated classes `aksel-read-more--open` and `aksel-read-more__content--closed`. Use `data-state` instead to access state. ([#4723](https://github.com/navikt/aksel/pull/4723))
## 8.7.0
## 8.6.0
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-stylelint",
"version": "8.7.0",
"version": "8.10.2",
"type": "module",
"engines": {
"node": ">=18.12.0"
@@ -42,14 +42,14 @@
"dev": "yarn watch:lint"
},
"devDependencies": {
"@navikt/ds-css": "^8.7.0",
"@navikt/ds-tokens": "^8.7.0",
"@navikt/ds-css": "^8.10.2",
"@navikt/ds-tokens": "^8.10.2",
"concurrently": "9.2.1",
"postcss-selector-parser": "^7.1.0",
"postcss-value-parser": "^4.2.0",
"stylelint": "^17.2.0",
"stylelint-test-rule-node": "^1.0.0",
"tsx": "^4.20.6",
"typescript": "5.9.3"
"typescript": "6.0.2"
}
}
@@ -18,4 +18,9 @@ export const deprecations: DeprecatedList = [
"Removed in vX.X.X, see documentation [link] for more information.",
deprecatePrefix: true,
},
{
classes: ["aksel-read-more__content--closed", "aksel-read-more--open"],
message:
"Removed in version ^8.8. Use data-state='open' or 'closed' instead.",
},
];
+13 -10
View File
@@ -8,22 +8,25 @@ const __dirname = dirname(__filename);
const flattenObject = (
obj: Record<string, string | Record<string, string>>,
) => {
const flattened = Object.keys(obj).reduce((acc, key) => {
if (typeof obj[key] === "string") {
acc.push(key);
} else {
acc.push(flattenObject(obj[key]));
}
return acc;
}, []);
): string[] => {
const flattened = Object.keys(obj).reduce<(string | string[])[]>(
(acc, key) => {
if (typeof obj[key] === "string") {
acc.push(key);
} else {
acc.push(flattenObject(obj[key]));
}
return acc;
},
[],
);
return flattened.flat();
};
const tokenCSSFile = "./global-tokens.css";
const tokenJsonFile = "./component-tokens.json";
const allowedTokenNames = [];
const allowedTokenNames: string[] = [];
export const tokenExists = (
controlledPrefixes: string[],
+48
View File
@@ -1,5 +1,53 @@
# @navikt/aksel
## 8.10.2
### Patch Changes
- Updated dependencies [[`90194d7`](https://github.com/navikt/aksel/commit/90194d7d95edd2ad69156528ec7e1e0600daef8a)]:
- @navikt/ds-css@8.10.2
- @navikt/ds-tokens@8.10.2
## 8.10.1
### Patch Changes
- Updated dependencies [[`f66236c`](https://github.com/navikt/aksel/commit/f66236c3710d132f4a2bbe043282a98136b089d9)]:
- @navikt/ds-css@8.10.1
- @navikt/ds-tokens@8.10.1
## 8.10.0
### Patch Changes
- Updated dependencies [[`63f5aaf`](https://github.com/navikt/aksel/commit/63f5aaf2f4bfdc3402afe9617c806309e0169420), [`139805d`](https://github.com/navikt/aksel/commit/139805d5b4b6422e99ee04c1dcde1bdd15c8ddaa), [`2eab5b9`](https://github.com/navikt/aksel/commit/2eab5b956420848ca9fc785bc63263161ac79f85), [`f491aae`](https://github.com/navikt/aksel/commit/f491aaec704314fe97b77d92cc2ed1564454c0e8), [`2eab5b9`](https://github.com/navikt/aksel/commit/2eab5b956420848ca9fc785bc63263161ac79f85), [`c096f46`](https://github.com/navikt/aksel/commit/c096f46beb07f48e2869f7bcc722732e4f7ac31e), [`c096f46`](https://github.com/navikt/aksel/commit/c096f46beb07f48e2869f7bcc722732e4f7ac31e)]:
- @navikt/ds-css@8.10.0
- @navikt/ds-tokens@8.10.0
## 8.9.1
### Patch Changes
- Updated dependencies [[`f7393f7`](https://github.com/navikt/aksel/commit/f7393f75159d3e4cff5fd438fd8e275325f98f1c), [`9346578`](https://github.com/navikt/aksel/commit/93465781c13e91ec41520e1284cba42c452d1386), [`47d74be`](https://github.com/navikt/aksel/commit/47d74be1a0db844d7116e46b0608c42146dcbc01)]:
- @navikt/ds-css@8.9.1
- @navikt/ds-tokens@8.9.1
## 8.9.0
### Patch Changes
- Updated dependencies [[`86f86d3`](https://github.com/navikt/aksel/commit/86f86d37608432160333ed275f76553d936bf63a), [`72a9131`](https://github.com/navikt/aksel/commit/72a9131aeeac41d0242869f5684999e6bc731285)]:
- @navikt/ds-css@8.9.0
- @navikt/ds-tokens@8.9.0
## 8.8.0
### Patch Changes
- Updated dependencies [[`befae1e`](https://github.com/navikt/aksel/commit/befae1e0a27e32b46c45335cf438aa65f4333b9f), [`7388130`](https://github.com/navikt/aksel/commit/738813046ffece51d4670a33297f4333c6bae8d0), [`5756986`](https://github.com/navikt/aksel/commit/57569860700bf81d6eef06ddbc39270933eff528), [`232ed45`](https://github.com/navikt/aksel/commit/232ed4569414e70f5a6f8e7bab584226f191a889)]:
- @navikt/ds-css@8.8.0
- @navikt/ds-tokens@8.8.0
## 8.7.0
### Patch Changes
+15 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel",
"version": "8.7.0",
"version": "8.10.2",
"description": "Aksel command line interface. Codemods and other utilities for Aksel users.",
"author": "Aksel | Nav designsystem team",
"license": "MIT",
@@ -23,6 +23,13 @@
"test:watch": "vitest watch"
},
"bin": "./dist/index.js",
"exports": {
"./package.json": "./package.json",
"./migrations": {
"import": "./dist/migrations-config.js",
"types": "./dist/migrations-config.d.ts"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/navikt/aksel.git",
@@ -33,8 +40,8 @@
"url": "https://github.com/navikt/aksel/issues"
},
"dependencies": {
"@navikt/ds-css": "^8.7.0",
"@navikt/ds-tokens": "^8.7.0",
"@navikt/ds-css": "^8.10.2",
"@navikt/ds-tokens": "^8.10.2",
"chalk": "5.6.2",
"cli-progress": "3.12.0",
"clipboardy": "5.0.1",
@@ -45,13 +52,15 @@
"is-git-clean": "1.1.0",
"jscodeshift": "17.3.0",
"jscodeshift-add-imports": "1.0.11",
"lodash": "4.17.23"
"lodash": "4.18.1"
},
"devDependencies": {
"@types/cli-progress": "3.11.6",
"@types/is-git-clean": "1.1.2",
"@types/jscodeshift": "17.3.0",
"rimraf": "6.1.3",
"typescript": "5.9.3",
"vitest": "4.0.18"
"typescript": "6.0.2",
"vitest": "4.1.4"
},
"sideEffects": false,
"engines": {
+9 -214
View File
@@ -1,216 +1,5 @@
import chalk from "chalk";
import { SupportedCodemodExtensions } from "./codeshift.utils";
const JS_EXTENSIONS = [
"js",
"jsx",
"ts",
"tsx",
] satisfies SupportedCodemodExtensions[];
const CSS_EXTENSIONS = [
"css",
"scss",
"less",
] satisfies SupportedCodemodExtensions[];
type MigrationT = Record<
string,
{
description: string;
value: string;
path: string;
warning?: string;
/**
* Some transforms are only meant to run on specific file extensions.
* This is used to filter out files that should not be transformed.
*/
ignoredExtensions: SupportedCodemodExtensions[];
}[]
>;
export const migrations: MigrationT = {
v1: [
{
description: "Runs all codemods for beta -> v1 migration",
value: "v1-preset",
path: "v1.0.0/preset/preset",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Fixes breaking API-changes for <Pagination /> component",
value: "v1-pagination",
path: "v1.0.0/pagination/pagination",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Fixes breaking API-changes for <Tabs /> component",
value: "v1-tabs",
path: "v1.0.0/tabs/tabs",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Fixes breaking API-changes for <SpeechBubble /> (now <Chat/>) component",
value: "v1-chat",
path: "v1.0.0/chat/chat",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v2: [
{
description: "Patches changed css-variables",
value: "v2-css",
path: "v2.0.0/update-css-tokens/update-css-tokens",
ignoredExtensions: [],
},
{
description: "Patches changed js-variables",
value: "v2-js",
path: "v2.0.0/update-js-tokens/update-js-tokens",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Patches changed sass-variables",
value: "v2-sass",
path: "v2.0.0/update-sass-tokens/update-sass-tokens",
ignoredExtensions: JS_EXTENSIONS,
},
{
description: "Patches changed less-variables",
value: "v2-less",
path: "v2.0.0/update-less-tokens/update-less-tokens",
ignoredExtensions: JS_EXTENSIONS,
},
],
v3: [
{
description:
"Replaces deprecated <CopyToClipboard /> with <CopyButton />",
value: "v3-copybutton",
path: "v3.0.0/copybutton/copybutton",
warning:
"Remember to remove css-import from '@navikt/ds-css-internal' if no longer needed\nIf non-text was used as children, or different locales were handled, you need to manually fix this",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v4: [
{
description:
"Replaced deprecated 'internal'-component import to 'core'-imports",
value: "v4-internal-react",
path: "v4.0.0/internal-react/internal-react",
warning:
"Remember to also run 'v4-internal-css' if you have overwritten any css-classes!",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Replaced 'navdsi'-prefixes used to overwrite internal-css to 'navds'-prefixes",
value: "v4-internal-css",
path: "v4.0.0/internal-css/internal-css",
warning:
"Remember to remove '@navikt/ds-css-internal' imports if no longer needed! Also run 'v4-internal-react' to convert internal-react imports to core-imports",
ignoredExtensions: [],
},
{
description:
"Removes all instances of UNSAFE_ for datepicker/monthpicker.",
value: "v4-date",
path: "v4.0.0/date/date",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v6: [
{
description:
"Removes `backgroundColor` and `avatarBgColor` properties from `Chat` and `Chat.Bubble`",
value: "v6-chat",
path: "v6.0.0/chat/chat",
warning:
"Remember to update use of `variant`-prop to match previous use of colors. If needed the component exposes css-variables for custom overrides",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v8: [
{
description:
"Updates Box with legacy-tokens to Box using the new token system, and renames already migrated BoxNew/Box.New instances to Box.",
value: "v8-box",
path: "v8.0.0/box/box",
warning:
"Remember to check if 'TODO: Aksel Box migration'-comment was added to any files after migration. This comment will help you find and update Box-instances we couldn't update for you.",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Renames already migrated BoxNew/Box.New instances to Box.",
value: "v8-box-new",
path: "v8.0.0/box-new/box-new",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Removes deprecated props from components.",
value: "v8-prop-deprecate",
path: "v8.0.0/prop-deprecate/prop-deprecate",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Tries to migrate List component by wrapping it with 'Box' and moving 'title' and 'description' props to 'Heading' and 'BodyShort'.",
value: "v8-list",
path: "v8.0.0/list/list",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Updates all Primitives to use new `space`-tokens.",
value: "v8-primitive-spacing",
path: "v8.0.0/primitives-spacing/spacing",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Tag based on current variant prop.",
value: "v8-tag-variant",
path: "v8.0.0/tag-variant/tag-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on ToggleGroup based on current variant prop.",
value: "v8-toggle-group-variant",
path: "v8.0.0/toggle-group-variant/toggle-group-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Accordion based on current variant prop.",
value: "v8-accordion-variant",
path: "v8.0.0/accordion-variant/accordion-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Chips based on current variant prop.",
value: "v8-chips-variant",
path: "v8.0.0/chips-variant/chips-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Button based on current variant prop.",
value: "v8-button-variant",
path: "v8.0.0/button-variant/button-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Link based on current variant prop.",
value: "v8-link-variant",
path: "v8.0.0/link-variant/link-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
],
} as const;
import { migrations } from "../migrations-config";
/**
* Extracts `path` field for a given migration.
@@ -264,8 +53,14 @@ export function getMigrationsForVersion(version: string) {
/**
* Returns the override migrations available for a specific version.
*/
function isOverrideVersion(
version: string,
): version is keyof typeof migrationStringOverride {
return version in migrationStringOverride;
}
export function getOverridesForVersion(version: string) {
return migrationStringOverride[version] ?? [];
return isOverrideVersion(version) ? migrationStringOverride[version] : [];
}
/**
@@ -292,7 +87,7 @@ export function getMigrationString() {
Object.entries(migrations).forEach(([version, vMigrations]) => {
str += `\n${chalk.underline(version)}\n`;
const overrideMigrations = migrationStringOverride[version] || [];
const overrideMigrations = getOverridesForVersion(version);
overrideMigrations.forEach((migration) => {
str += `${chalk.blue(migration.value)}: ${migration.description}\n`;
});
+6 -1
View File
@@ -80,6 +80,11 @@ export async function runCodeshift(
warning && console.info(`\n${chalk.yellow(warning)}\n`);
} catch (error) {
program.error(chalk.red("Error:", error.message));
program.error(
chalk.red(
"Error:",
error instanceof Error ? error.message : String(error),
),
);
}
}
@@ -50,7 +50,9 @@ async function runVersionMigration(
chalk.greenBright.bold(`\nAvailable migrations for ${version}:\n`),
);
const overrideValues = new Set(overrideMigrations.map((m) => m.value));
const overrideValues = new Set<string>(
overrideMigrations.map((m) => m.value),
);
const choices = [
...overrideMigrations.map((migration) => ({
@@ -363,6 +363,6 @@ const tokens = [
["--navdsi-header-color-hover", "--a-surface-inverted-hover"],
["--navdsi-header-color-active", "--a-surface-inverted-active"],
["--navds-button-icon-adjustment", "--ac-button-icon-margin"]
]
] as const
module.exports = { tokens };
export { tokens };
@@ -1,10 +1,11 @@
import type { API, FileInfo, Options } from "jscodeshift";
import renameProps from "../../utils/rename-props";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api, options) {
export default function transformer(
file: FileInfo,
api: API,
options: Options,
) {
const j = api.jscodeshift;
const root = j(file.source);
@@ -1,11 +1,8 @@
import type { API, FileInfo } from "jscodeshift";
import { getLineTerminator } from "../../../utils/lineterminator";
import renameProps from "../../../utils/rename-props";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let localName = "SpeechBubble";
@@ -16,14 +13,17 @@ export default function transformer(file, api) {
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === "@navikt/ds-react")
.forEach((imp) => {
imp.value.specifiers.forEach((x) => {
imp.value.specifiers?.forEach((x) => {
if (x.type !== "ImportSpecifier") return;
if (x.imported.name === "SpeechBubble") {
if (x.local.name !== x.imported.name) {
localName = x.local.name;
if (x.local && x.local.name !== x.imported.name) {
localName = String(x.local.name);
x.imported.name = "Chat";
} else {
x.imported.name = "Chat";
x.local.name = "Chat";
if (x.local) {
x.local.name = "Chat";
}
}
}
});
@@ -47,20 +47,34 @@ export default function transformer(file, api) {
compRoot.forEach((x) => {
if (localName !== "SpeechBubble") return;
x.node.openingElement.name.name = "Chat";
x.node.closingElement.name.name = "Chat";
const opening = x.node.openingElement.name;
if (opening.type === "JSXIdentifier") {
opening.name = "Chat";
}
const closing = x.node.closingElement?.name;
if (closing?.type === "JSXIdentifier") {
closing.name = "Chat";
}
});
/* Need to handle dot-notations differently */
const child = root.find(j.JSXElement);
child.forEach((x) => {
const openingName = x.value.openingElement.name;
if (
x.value.openingElement.name.type === "JSXMemberExpression" &&
x.value.openingElement.name.object.name === "SpeechBubble"
openingName.type === "JSXMemberExpression" &&
openingName.object.type === "JSXIdentifier" &&
openingName.object.name === "SpeechBubble"
) {
x.value.openingElement.name.object.name = "Chat";
x.value.closingElement.name.object.name = "Chat";
openingName.object.name = "Chat";
const closingName = x.value.closingElement?.name;
if (
closingName?.type === "JSXMemberExpression" &&
closingName.object.type === "JSXIdentifier"
) {
closingName.object.name = "Chat";
}
}
});
}
@@ -1,25 +1,29 @@
import type {
API,
FileInfo,
JSXAttribute,
JSXElement,
JSXSpreadAttribute,
} from "jscodeshift";
import { getJSXLiteralValue } from "../../../utils/jsx-value";
import { getLineTerminator } from "../../../utils/lineterminator";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let localName = "Pagination";
const root = j(file.source);
function addMigrationTag(node) {
function addMigrationTag(node: JSXElement) {
const attributes = node.openingElement.attributes;
const isMigrated = attributes.find(
(attr) =>
const isMigrated = attributes?.find(
(attr: JSXAttribute | JSXSpreadAttribute) =>
attr.type === "JSXAttribute" &&
attr.name.name === "data-version" &&
attr.value.value === "v1",
getJSXLiteralValue(attr.value) === "v1",
);
if (!isMigrated) {
if (!isMigrated && attributes) {
attributes.push(
j.jsxAttribute(j.jsxIdentifier("data-version"), j.literal("v1")),
);
@@ -27,13 +31,14 @@ export default function transformer(file, api) {
}
/* https://github.com/mui/material-ui/blob/master/packages/mui-codemod/src/v5.0.0/variant-prop.js */
function addExplicitStandardProp(node) {
function addExplicitStandardProp(node: JSXElement) {
const attributes = node.openingElement.attributes;
const variant = attributes.find(
(attr) => attr.type === "JSXAttribute" && attr.name.name === "size",
const variant = attributes?.find(
(attr: JSXAttribute | JSXSpreadAttribute) =>
attr.type === "JSXAttribute" && attr.name.name === "size",
);
if (!variant) {
if (!variant && attributes) {
attributes.unshift(
j.jsxAttribute(j.jsxIdentifier("size"), j.literal("small")),
);
@@ -46,37 +51,45 @@ export default function transformer(file, api) {
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === "@navikt/ds-react")
.forEach((imp) => {
imp.value.specifiers.forEach((x) => {
imp.value.specifiers?.forEach((x) => {
if (
x.type === "ImportSpecifier" &&
x.imported.type === "Identifier" &&
x.imported.name === "Pagination" &&
x.local.name !== x.imported.name
x.local?.name !== x.imported.name &&
x.local?.name
) {
localName = x.local.name;
localName = String(x.local.name);
}
});
});
if (j(file.source).findJSXElements(localName)) {
root.findJSXElements(`${localName}`).forEach((parent) => {
const skip = !!parent.value.openingElement?.attributes.find(
(x) => x.name.name === "data-version" && x.value.value === "v1",
const skip = !!parent.value.openingElement?.attributes?.find(
(attr: JSXAttribute | JSXSpreadAttribute) =>
attr.type === "JSXAttribute" &&
attr.name.name === "data-version" &&
getJSXLiteralValue(attr.value) === "v1",
);
parent.value.openingElement?.attributes.forEach((x) => {
let didUpdate = false;
if (x.name?.name === "size" && x.type === "JSXAttribute" && !skip) {
/* addExplicitStandardProp */
if (x.value.value === "medium") {
x.value = j.literal("small");
didUpdate = true;
} else if (x.value.value === "small") {
x.value = j.literal("xsmall");
didUpdate = true;
}
parent.value.openingElement?.attributes?.forEach(
(x: JSXAttribute | JSXSpreadAttribute) => {
let didUpdate = false;
if (x.type === "JSXAttribute" && x.name?.name === "size" && !skip) {
const value = getJSXLiteralValue(x.value);
if (value === "medium") {
x.value = j.literal("small");
didUpdate = true;
} else if (value === "small") {
x.value = j.literal("xsmall");
didUpdate = true;
}
didUpdate && addMigrationTag(parent.value);
}
});
didUpdate && addMigrationTag(parent.value);
}
},
);
addExplicitStandardProp(parent.value);
});
}
@@ -0,0 +1,11 @@
import { Pagination as DsPagination, Button } from "@navikt/ds-react";
export const Demo = () => {
return (
<div>
<DsPagination onPageChange={setPage} />
<DsPagination size={"medium"} onPageChange={setPage} />
<DsPagination size={"small"} onPageChange={setPage} />
</div>
);
};
@@ -0,0 +1,11 @@
import { Pagination as DsPagination, Button } from "@navikt/ds-react";
export const Demo = () => {
return (
<div>
<DsPagination size="small" onPageChange={setPage} data-version="v1" />
<DsPagination size="small" onPageChange={setPage} data-version="v1" />
<DsPagination size="xsmall" onPageChange={setPage} data-version="v1" />
</div>
);
};
@@ -1,7 +1,7 @@
import { check } from "../../../../utils/check";
const migration = "pagination";
const fixtures = ["size", "idempotent", "import"];
const fixtures = ["size", "idempotent", "import", "literal"];
for (const fixture of fixtures) {
check(__dirname, {
@@ -1,12 +1,9 @@
import type { API, FileInfo } from "jscodeshift";
import transformChat from "../chat/chat";
import transformPagination from "../pagination/pagination";
import transformTabs from "../tabs/tabs";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
file.source = transformTabs(file, api);
file.source = transformChat(file, api);
file.source = transformPagination(file, api);
@@ -1,14 +1,11 @@
import type { API, FileInfo, JSXAttribute } from "jscodeshift";
import { getLineTerminator } from "../../../utils/lineterminator";
import renameProps from "../../../utils/rename-props";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let localName = "Tabs";
let iconPositionProp = null;
let iconPositionProp: JSXAttribute | null = null;
const root = j(file.source);
@@ -17,9 +14,14 @@ export default function transformer(file, api) {
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === "@navikt/ds-react")
.forEach((imp) => {
imp.value.specifiers.forEach((x) => {
if (x.imported.name === "Tabs" && x.local.name !== x.imported.name) {
localName = x.local.name;
imp.value.specifiers?.forEach((x) => {
if (
x.type === "ImportSpecifier" &&
x.imported.name === "Tabs" &&
x.local &&
x.local.name !== x.imported.name
) {
localName = String(x.local.name);
}
});
});
@@ -34,48 +36,52 @@ export default function transformer(file, api) {
});
root.findJSXElements(`${localName}`).forEach((parent) => {
parent.value.children.forEach((el) => {
parent.value.children?.forEach((el) => {
if (el.type !== "JSXElement") return;
const openingEl = el.openingElement;
if (openingEl?.name && openingEl.name.type === "JSXMemberExpression") {
if (openingEl.name.type === "JSXMemberExpression") {
if (
openingEl.name.object.type === "JSXIdentifier" &&
openingEl.name.object.name === localName &&
openingEl.name.property.name === "List"
) {
/* Move loop-prop */
el.openingElement.attributes.forEach((x, index) => {
if (x.name?.name === "loop" && x.type === "JSXAttribute") {
parent.value.openingElement.attributes.push(x);
delete el.openingElement.attributes[index];
openingEl.attributes?.forEach((x, index) => {
if (x.type === "JSXAttribute" && x.name.name === "loop") {
parent.value.openingElement.attributes?.push(x);
openingEl.attributes?.splice(index, 1);
}
});
/* Find and move iconPosition-prop to <Tabs/> */
el.children.forEach((tab) => {
el.children?.forEach((tab) => {
if (tab.type !== "JSXElement") return;
const tabEl = tab.openingElement;
if (tabEl?.name && tabEl.name.type === "JSXMemberExpression") {
if (
tabEl.name.object.name === localName &&
tabEl.name.property.name === "Tab"
) {
tabEl?.attributes.forEach((x, index) => {
if (
x.name?.name === "iconPosition" &&
x.type === "JSXAttribute"
) {
if (!iconPositionProp) {
iconPositionProp = x;
}
delete tabEl.attributes[index];
if (
tabEl.name.type === "JSXMemberExpression" &&
tabEl.name.object.type === "JSXIdentifier" &&
tabEl.name.object.name === localName &&
tabEl.name.property.name === "Tab"
) {
tabEl.attributes?.forEach((x, index) => {
if (
x.type === "JSXAttribute" &&
x.name.name === "iconPosition"
) {
if (!iconPositionProp) {
iconPositionProp = x;
}
});
}
tabEl.attributes?.splice(index, 1);
}
});
}
});
}
}
});
iconPositionProp &&
parent.value.openingElement.attributes.push(iconPositionProp);
if (iconPositionProp) {
parent.value.openingElement.attributes?.push(iconPositionProp);
}
iconPositionProp = null;
});
}
@@ -1,10 +1,7 @@
import type { FileInfo } from "jscodeshift";
import { tokens } from "../../../tokens-map.js";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file) {
export default function transformer(file: FileInfo) {
let src = file.source;
tokens.forEach((tok) => {
@@ -1,4 +1,4 @@
import type { JSCodeshift } from "jscodeshift";
import type { API, JSCodeshift } from "jscodeshift";
import { tokens } from "../../../tokens-map.js";
import {
getImportSpecifier,
@@ -12,7 +12,7 @@ import { translateToken } from "../../../utils/translate-token";
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file: JSCodeshift, api) {
export default function transformer(file: JSCodeshift, api: API) {
const src = file.source;
const j = api.jscodeshift as JSCodeshift;
@@ -37,7 +37,7 @@ export default function transformer(file: JSCodeshift, api) {
getImportSpecifier(j, root, name, "@navikt/ds-tokens/dist/tokens").forEach(
(x) => {
foundName = x.node.imported.name;
foundName = String(x.node.imported.name);
},
);
@@ -1,11 +1,8 @@
import type { FileInfo } from "jscodeshift";
import { tokens } from "../../../tokens-map.js";
import { translateToken } from "../../../utils/translate-token";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file) {
export default function transformer(file: FileInfo) {
let src = file.source;
tokens.forEach((tok) => {
@@ -1,11 +1,8 @@
import type { FileInfo } from "jscodeshift";
import { tokens } from "../../../tokens-map.js";
import { translateToken } from "../../../utils/translate-token";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file) {
export default function transformer(file: FileInfo) {
let src = file.source;
tokens.forEach((tok) => {
@@ -1,16 +1,13 @@
import chalk from "chalk";
import type { API, Collection, FileInfo } from "jscodeshift";
import { getLineTerminator } from "../../../utils/lineterminator";
import moveAndRenameImport from "../../../utils/packageImports";
import removePropsFromComponent from "../../../utils/removeProps";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let root: any;
let root: Collection<any>;
try {
root = j(file.source);
} catch {
@@ -46,13 +43,14 @@ export default function transformer(file, api) {
const children = node.node.children;
let flagged = false;
if (
children &&
children.length > 0 &&
!node.node.openingElement.attributes.some(
(attr) => attr.name.name === "text",
!node.node.openingElement.attributes?.some(
(attr) => attr.type === "JSXAttribute" && attr.name.name === "text",
)
) {
if (children.length === 1 && children[0].type === "JSXText") {
node.node.openingElement.attributes.push(
node.node.openingElement.attributes?.push(
j.jsxAttribute(
j.jsxIdentifier("text"),
j.literal(children[0].value.trim()),
@@ -80,9 +78,15 @@ export default function transformer(file, api) {
});
compRoot.forEach((x) => {
x.node.openingElement.name.name = "CopyButton";
if (x.node.children.length > 0) {
x.node.closingElement.name.name = "CopyButton";
const openingName = x.node.openingElement.name;
if (openingName.type === "JSXIdentifier") {
openingName.name = "CopyButton";
}
if (x.node.children && x.node.children.length > 0) {
const closingName = x.node.closingElement?.name;
if (closingName?.type === "JSXIdentifier") {
closingName.name = "CopyButton";
}
}
});
}
@@ -1,8 +1,6 @@
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file) {
import type { FileInfo } from "jscodeshift";
export default function transformer(file: FileInfo) {
const names = [
"UNSAFE_useDatepicker",
"UNSAFE_DatePicker",
@@ -1,3 +1,5 @@
import type { FileInfo } from "jscodeshift";
const cssConversions = {
".navdsi-dropdown": ".navds-dropdown",
".navdsi-header": ".navds-internalheader",
@@ -8,11 +10,8 @@ const cssConversions = {
"--ac-header-hover-bg": "--ac-internalheader-hover-bg",
"--ac-header-active-bg": "--ac-internalheader-active-bg",
};
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file) {
export default function transformer(file: FileInfo) {
let src = file.source;
Object.entries(cssConversions).forEach(([key, value]) => {
@@ -1,11 +1,8 @@
import type { API, FileInfo } from "jscodeshift";
import { getLineTerminator } from "../../../utils/lineterminator";
import moveAndRenameImport from "../../../utils/packageImports";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let root: any;
@@ -1,10 +1,7 @@
import type { API, FileInfo } from "jscodeshift";
import { getLineTerminator } from "../../../utils/lineterminator";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api) {
export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
let localName = "Chat";
@@ -15,9 +12,14 @@ export default function transformer(file, api) {
.find(j.ImportDeclaration)
.filter((path) => path.node.source.value === "@navikt/ds-react")
.forEach((imp) => {
imp.value.specifiers.forEach((x) => {
if (x.imported.name === "Chat" && x.local.name !== x.imported.name) {
localName = x.local.name;
imp.value.specifiers?.forEach((x) => {
if (x.type !== "ImportSpecifier") return;
if (
x.imported.name === "Chat" &&
x.local &&
x.local.name !== x.imported.name
) {
localName = String(x.local.name);
}
});
});
@@ -43,7 +43,7 @@ export default function transformer(file: FileInfo, api: API) {
for (const prop of propsAffected) {
findProps({ j, path: astElement, name: prop }).forEach((attr) => {
const attrvalue = attr.value.value;
if (attrvalue.type === "StringLiteral") {
if (attrvalue?.type === "StringLiteral") {
/**
* Skips if the replacement token already set
*/
@@ -65,7 +65,7 @@ export default function transformer(file: FileInfo, api: API) {
tokenComments.push(tokenComment);
}
} else if (
attrvalue.type === "JSXExpressionContainer" &&
attrvalue?.type === "JSXExpressionContainer" &&
attrvalue.expression.type === "StringLiteral"
) {
const literal = attrvalue.expression;
@@ -96,10 +96,10 @@ export default function transformer(file: FileInfo, api: API) {
findProps({ j, path: astElement, name: "borderRadius" }).forEach((attr) => {
const attrValue = attr.value.value;
if (attrValue.type === "StringLiteral") {
if (attrValue?.type === "StringLiteral") {
/* borderRadius="xlarge" */
attrValue.value = convertBorderRadiusToRadius(attrValue.value);
} else if (attrValue.type === "JSXExpressionContainer") {
} else if (attrValue?.type === "JSXExpressionContainer") {
/* borderRadius={{xs: "xlarge", sm: "large"}} */
const expression = attrValue.expression;
if (expression.type === "ObjectExpression") {
@@ -189,7 +189,9 @@ function convertBorderRadiusToRadius(oldValue: string): string {
console.warn(`Possibly invalid radius token found: ${radiusToken}\n`);
newRadius.push(radiusToken);
} else {
newRadius.push(`${legacyBorderRadiusNameTokenLookup[radiusToken]}`);
newRadius.push(
`${legacyBorderRadiusNameTokenLookup[radiusToken as keyof typeof legacyBorderRadiusNameTokenLookup]}`,
);
}
}
@@ -4,23 +4,25 @@ import type {
FileInfo,
ImportDeclaration,
JSXAttribute,
JSXElement,
JSXSpreadAttribute,
} from "jscodeshift";
import { getJSXStringValue } from "../../../utils/jsx-value";
import { getLineTerminator } from "../../../utils/lineterminator";
const headingSizeMap = {
const headingSizeMap: Record<string, string> = {
small: "xsmall",
medium: "small",
large: "medium",
};
const bodySizeMap = {
const bodySizeMap: Record<string, string> = {
small: "small",
medium: "medium",
large: "large",
};
const boxMarginMap = {
const boxMarginMap: Record<string, string> = {
small: "space-12",
medium: "space-16",
large: "space-16",
@@ -32,7 +34,7 @@ export default function transformer(file: FileInfo, api: API) {
let localListName = "List";
let hasListImport = false;
let dsReactImportPath: ASTPath<ImportDeclaration> | null = null;
let dsReactImportPath: ASTPath<ImportDeclaration> | undefined;
let localHeadingName = "Heading";
let hasHeadingImport = false;
@@ -50,19 +52,19 @@ export default function transformer(file: FileInfo, api: API) {
path.node.specifiers?.forEach((specifier) => {
if (specifier.type === "ImportSpecifier") {
if (specifier.imported.name === "List") {
localListName = specifier.local?.name || "List";
localListName = String(specifier.local?.name || "List");
hasListImport = true;
}
if (specifier.imported.name === "Heading") {
localHeadingName = specifier.local?.name || "Heading";
localHeadingName = String(specifier.local?.name || "Heading");
hasHeadingImport = true;
}
if (specifier.imported.name === "BodyShort") {
localBodyShortName = specifier.local?.name || "BodyShort";
localBodyShortName = String(specifier.local?.name || "BodyShort");
hasBodyShortImport = true;
}
if (specifier.imported.name === "Box") {
localBoxName = specifier.local?.name || "Box";
localBoxName = String(specifier.local?.name || "Box");
hasBoxImport = true;
}
}
@@ -71,7 +73,7 @@ export default function transformer(file: FileInfo, api: API) {
path.node.specifiers?.forEach((specifier) => {
if (specifier.type === "ImportSpecifier") {
if (specifier.imported.name === "List") {
localListName = specifier.local?.name || "List";
localListName = String(specifier.local?.name || "List");
hasListImport = true;
}
}
@@ -92,6 +94,10 @@ export default function transformer(file: FileInfo, api: API) {
.forEach((path) => {
const attributes = path.node.openingElement.attributes;
if (!attributes) {
return;
}
const titleAttr = attributes.find(
(attr) => attr.type === "JSXAttribute" && attr.name.name === "title",
) as JSXAttribute | undefined;
@@ -122,15 +128,11 @@ export default function transformer(file: FileInfo, api: API) {
const titleValue = titleAttr?.value;
const descValue = descAttr?.value;
let sizeValue = "medium";
if (sizeAttr && sizeAttr.value?.type === "StringLiteral") {
sizeValue = sizeAttr.value.value;
}
const extractedSize = getJSXStringValue(sizeAttr?.value);
const sizeValue = extractedSize || "medium";
let headingAs = "h3";
if (headingTagAttr && headingTagAttr.value?.type === "StringLiteral") {
headingAs = headingTagAttr.value.value;
}
const extractedHeadingAs = getJSXStringValue(headingTagAttr?.value);
const headingAs = extractedHeadingAs || "h3";
// Separate attributes
const listAttributes: JSXAttribute[] = [
@@ -168,7 +170,7 @@ export default function transformer(file: FileInfo, api: API) {
}
});
const newNodes = [];
const newNodes: JSXElement[] = [];
// Create Heading
if (titleValue) {
@@ -189,11 +191,13 @@ export default function transformer(file: FileInfo, api: API) {
);
}
let children = [];
let children: (ReturnType<typeof j.jsxText> | typeof titleValue)[];
if (titleValue.type === "StringLiteral") {
children = [j.jsxText(titleValue.value)];
} else if (titleValue.type === "JSXExpressionContainer") {
children = [titleValue];
} else {
children = [];
}
const heading = j.jsxElement(
@@ -209,7 +213,7 @@ export default function transformer(file: FileInfo, api: API) {
if (!hasBodyShortImport) {
newImports.add("BodyShort");
}
const bodyAttrs = [];
const bodyAttrs: JSXAttribute[] = [];
const mappedSize = bodySizeMap[sizeValue];
if (mappedSize && mappedSize !== "medium") {
bodyAttrs.push(
@@ -220,11 +224,13 @@ export default function transformer(file: FileInfo, api: API) {
);
}
let children = [];
let children: (ReturnType<typeof j.jsxText> | typeof descValue)[];
if (descValue.type === "StringLiteral") {
children = [j.jsxText(descValue.value)];
} else if (descValue.type === "JSXExpressionContainer") {
children = [descValue];
} else {
children = [];
}
const body = j.jsxElement(
@@ -285,8 +291,8 @@ export default function transformer(file: FileInfo, api: API) {
);
newImports.forEach((imp) => {
if (!existingSpecifiers.has(imp)) {
dsReactImportPath!.node.specifiers?.push(
if (!existingSpecifiers.has(imp) && dsReactImportPath) {
dsReactImportPath.node.specifiers?.push(
j.importSpecifier(j.identifier(imp)),
);
}
@@ -56,17 +56,17 @@ export default function transformer(file: FileInfo, api: API) {
findProps({ j, path, name: prop }).forEach((attr) => {
const attrValue = attr.value.value;
if (attrValue.type === "StringLiteral") {
if (attrValue?.type === "StringLiteral") {
/* padding="32" */
attrValue.value = convertSpacingToSpace(attrValue.value);
} else if (
attrValue.type === "JSXExpressionContainer" &&
attrValue?.type === "JSXExpressionContainer" &&
attrValue.expression.type === "StringLiteral"
) {
attrValue.expression.value = convertSpacingToSpace(
attrValue.expression.value,
);
} else if (attrValue.type === "JSXExpressionContainer") {
} else if (attrValue?.type === "JSXExpressionContainer") {
/* padding={{xs: "16", sm: "32"}} */
const expression = attrValue.expression;
if (expression.type === "ObjectExpression") {
+4 -4
View File
@@ -33,14 +33,14 @@ function findComponentImport(input: {
return;
}
path.node.specifiers.forEach((specifier) => {
path.node.specifiers?.forEach((specifier) => {
if (
specifier.type === "ImportSpecifier" &&
specifier.imported.name === name
) {
foundName = specifier.local
? specifier.local.name
: specifier.imported.name;
foundName = String(
specifier.local ? specifier.local.name : specifier.imported.name,
);
}
});
});
+1
View File
@@ -1,3 +1,4 @@
/* @ts-expect-error No avaliable types for testUtils */
import { applyTransform } from "jscodeshift/dist/testUtils";
import fs from "node:fs";
import path from "node:path";
@@ -0,0 +1,88 @@
import type { JSXAttribute, JSXExpressionContainer } from "jscodeshift";
type AttributeValue =
| JSXAttribute["value"]
| JSXExpressionContainer["expression"];
type LiteralValue = string | number | boolean;
/**
* Extracts a literal value (string, number, or boolean) from a JSX attribute value.
* Handles the following patterns:
* - `prop="value"` (StringLiteral)
* - `prop={"value"}` (JSXExpressionContainer with StringLiteral)
* - `prop={`value`}` (TemplateLiteral with no expressions)
* - `prop={42}` (NumericLiteral)
* - `prop={true}` / `prop={false}` (BooleanLiteral)
*
* @param node - The JSX attribute value node to extract the value from
* @returns The literal value if it can be extracted, otherwise null
*
* @example
* ```tsx
* getJSXLiteralValue(attr.value) // where attr is prop="hello" => "hello"
* getJSXLiteralValue(attr.value) // where attr is prop={42} => 42
* getJSXLiteralValue(attr.value) // where attr is prop={true} => true
* ```
*/
export function getJSXLiteralValue(node: AttributeValue): LiteralValue | null {
if (!node) return null;
if (node.type === "StringLiteral") {
return node.value;
}
if (node.type === "NumericLiteral") {
return node.value;
}
if (node.type === "UnaryExpression") {
const unary = node;
if (unary.operator === "-" && unary.argument.type === "NumericLiteral") {
return -unary.argument.value;
}
return null;
}
if (node.type === "BooleanLiteral") {
return node.value;
}
if (node.type === "Literal") {
const value = node.value;
if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean"
) {
return value;
}
return null;
}
if (node.type === "TemplateLiteral") {
const template = node;
if (template.expressions.length === 0 && template.quasis.length === 1) {
return template.quasis[0].value.cooked ?? null;
}
return null;
}
if (node.type === "JSXExpressionContainer") {
return getJSXLiteralValue(node.expression);
}
return null;
}
/**
* Extracts the string value from a JSX attribute value.
* Convenience wrapper around `getJSXLiteralValue` that only returns strings.
*
* @param node - The JSX attribute value node to extract the string from
* @returns The string value if it can be extracted, otherwise null
*/
export function getJSXStringValue(node: AttributeValue): string | null {
const value = getJSXLiteralValue(node);
return typeof value === "string" ? value : null;
}
@@ -1,10 +1,10 @@
import type {
API,
FileInfo,
JSXAttribute,
JSXExpressionContainer,
Literal,
} from "jscodeshift";
import { getJSXStringValue } from "./jsx-value";
import { getLineTerminator } from "./lineterminator";
export interface MigrationConfig {
@@ -44,7 +44,7 @@ export function moveVariantToDataColor(
specifier.type === "ImportSpecifier" &&
specifier.imported.name === rootComponent
) {
localName = specifier.local?.name || specifier.imported.name;
localName = String(specifier.local?.name || specifier.imported.name);
}
});
});
@@ -77,7 +77,7 @@ export function moveVariantToDataColor(
if (attr.type !== "JSXAttribute") return;
if (attr.name.name === config.prop) {
variantPropIndex = index;
const value = getStringValue(attr.value);
const value = getJSXStringValue(attr.value);
if (value) {
variantValue = value;
}
@@ -134,25 +134,3 @@ export function moveVariantToDataColor(
const toSourceOptions = getLineTerminator(file.source);
return root.toSource(toSourceOptions);
}
type AttributeValue =
| JSXAttribute["value"]
| JSXExpressionContainer["expression"];
function getStringValue(node: AttributeValue): string | null {
if (!node) return null;
if (node.type === "StringLiteral" || node.type === "Literal") {
return node.value as string;
}
if (
node.type === "TemplateLiteral" &&
node.expressions.length === 0 &&
node.quasis.length === 1
) {
return node.quasis[0].value.cooked ?? null;
}
if (node.type === "JSXExpressionContainer") {
return getStringValue(node.expression);
}
return null;
}
@@ -59,8 +59,8 @@ export default function moveAndRenameImport(
const existingFromImportSpecifier = existingFromImport?.find(
j.ImportSpecifier,
(node) => {
if (node.imported.name === fromName) {
localname = node.local.name;
if (node.imported.name === fromName && node.local?.name) {
localname = String(node.local.name);
}
return node.imported.name === fromName;
},
@@ -11,6 +11,10 @@ export default function removePropsFromComponent(
component.forEach((node) => {
const attributes = node.node.openingElement.attributes;
if (!attributes) {
return;
}
for (let i = attributes.length - 1; i >= 0; i--) {
const attribute = attributes[i];
@@ -1,8 +1,21 @@
export default function renameProps({ root, componentName, props }) {
import type { Collection } from "jscodeshift";
interface RenamePropsOptions {
root: Collection;
componentName: string;
props: Record<string, string>;
}
export default function renameProps({
root,
componentName,
props,
}: RenamePropsOptions) {
return root.findJSXElements(componentName).forEach((path) => {
path.node.openingElement.attributes.forEach((node) => {
path.node.openingElement.attributes?.forEach((node) => {
if (
node.type === "JSXAttribute" &&
typeof node.name.name === "string" &&
Object.keys(props).includes(node.name.name)
) {
node.name.name = props[node.name.name];
@@ -0,0 +1,112 @@
import jscodeshift from "jscodeshift";
import { describe, expect, test } from "vitest";
import { getJSXLiteralValue, getJSXStringValue } from "../jsx-value";
const j = jscodeshift.withParser("tsx");
function getAttrValue(source: string) {
const root = j(source);
const attr = root.find(j.JSXAttribute, { name: { name: "prop" } });
return attr.paths()[0]?.value.value ?? null;
}
describe("getJSXLiteralValue", () => {
test("returns null for null/undefined input", () => {
expect(getJSXLiteralValue(null)).toBe(null);
expect(getJSXLiteralValue(undefined)).toBe(null);
});
test('handles StringLiteral: prop="value"', () => {
const node = getAttrValue('<Component prop="hello" />');
expect(getJSXLiteralValue(node)).toBe("hello");
});
test("handles empty StringLiteral", () => {
const node = getAttrValue('<Component prop="" />');
expect(getJSXLiteralValue(node)).toBe("");
});
test('handles JSXExpressionContainer with StringLiteral: prop={"value"}', () => {
const node = getAttrValue('<Component prop={"hello"} />');
expect(getJSXLiteralValue(node)).toBe("hello");
});
test("handles TemplateLiteral without expressions: prop={`value`}", () => {
const node = getAttrValue("<Component prop={`hello`} />");
expect(getJSXLiteralValue(node)).toBe("hello");
});
test("returns null for TemplateLiteral with expressions", () => {
// biome-ignore lint/suspicious/noTemplateCurlyInString: Testing only
const node = getAttrValue("<Component prop={`hello ${name}`} />");
expect(getJSXLiteralValue(node)).toBe(null);
});
test("handles numeric values: prop={42}", () => {
const node = getAttrValue("<Component prop={42} />");
expect(getJSXLiteralValue(node)).toBe(42);
});
test("handles negative numbers: prop={-5}", () => {
const node = getAttrValue("<Component prop={-5} />");
expect(getJSXLiteralValue(node)).toBe(-5);
});
test("handles floating point numbers: prop={3.14}", () => {
const node = getAttrValue("<Component prop={3.14} />");
expect(getJSXLiteralValue(node)).toBe(3.14);
});
test("handles boolean true: prop={true}", () => {
const node = getAttrValue("<Component prop={true} />");
expect(getJSXLiteralValue(node)).toBe(true);
});
test("handles boolean false: prop={false}", () => {
const node = getAttrValue("<Component prop={false} />");
expect(getJSXLiteralValue(node)).toBe(false);
});
test("returns null for variable references", () => {
const node = getAttrValue("<Component prop={someVar} />");
expect(getJSXLiteralValue(node)).toBe(null);
});
test("returns null for function calls", () => {
const node = getAttrValue("<Component prop={getValue()} />");
expect(getJSXLiteralValue(node)).toBe(null);
});
test("returns null for object expressions", () => {
const node = getAttrValue('<Component prop={{ key: "value" }} />');
expect(getJSXLiteralValue(node)).toBe(null);
});
test("handles strings with special characters", () => {
const node = getAttrValue('<Component prop={"hello, world! 👋"} />');
expect(getJSXLiteralValue(node)).toBe("hello, world! 👋");
});
test("handles multiline template literal without expressions", () => {
const node = getAttrValue(`<Component prop={\`hello
world\`} />`);
expect(getJSXLiteralValue(node)).toBe("hello\nworld");
});
});
describe("getJSXStringValue", () => {
test("returns string for StringLiteral", () => {
const node = getAttrValue('<Component prop="hello" />');
expect(getJSXStringValue(node)).toBe("hello");
});
test("returns null for numeric values", () => {
const node = getAttrValue("<Component prop={42} />");
expect(getJSXStringValue(node)).toBe(null);
});
test("returns null for boolean values", () => {
const node = getAttrValue("<Component prop={true} />");
expect(getJSXStringValue(node)).toBe(null);
});
});
@@ -29,11 +29,11 @@ class TokenStatus {
status: StatusT;
constructor() {
this.initStatus();
this.status = this.initStatus();
}
initStatus() {
this.status = {
return {
css: { legacy: [], updated: [] },
scss: { legacy: [], updated: [] },
less: { legacy: [], updated: [] },
@@ -44,6 +44,10 @@ class TokenStatus {
};
}
resetStatus() {
this.status = this.initStatus();
}
add({
isLegacy,
type,
@@ -96,11 +100,9 @@ class TokenStatus {
let statusDataObj: StatusDataT;
if (type === "summary") {
statusDataObj = {
legacy: [].concat(
...Object.values(this.status).map((_status) => _status.legacy),
),
updated: [].concat(
...Object.values(this.status).map((_status) => _status.updated),
legacy: Object.values(this.status).flatMap((_status) => _status.legacy),
updated: Object.values(this.status).flatMap(
(_status) => _status.updated,
),
};
@@ -1230,7 +1230,7 @@ const colors = {
type ColorObjWithTwType = ColorObjType & {
twOld: string;
twNew: string;
twNew?: string;
};
const colorWithTailwindConversion = Object.entries(colors).reduce<
@@ -9,7 +9,7 @@ function getFrameworkRegexes({
legacy = false,
}: {
token: string;
twString: string | null;
twString?: string | null;
legacy: boolean;
}): Record<"css" | "scss" | "less" | "js" | "tailwind", RegExp | null> {
const regexes: ReturnType<typeof getFrameworkRegexes> = {
@@ -453,7 +453,7 @@ const newTokensWithoutRegex: TokensWithTailwindTag = {
type TokensWithRegexes = Record<
string,
{ tw: string; regexes: ReturnType<typeof getFrameworkRegexes> }
{ tw: string | null; regexes: ReturnType<typeof getFrameworkRegexes> }
>;
const v8TokenConfig: TokensWithRegexes = Object.entries(
@@ -107,7 +107,12 @@ export async function runTooling(
() => getStatus(filepaths, "no-print"),
);
} catch (error) {
program.error(chalk.red("Error:", error.message));
program.error(
chalk.red(
"Error:",
error instanceof Error ? error.message : String(error),
),
);
}
task = await getNextTask(currentStatus.status);
@@ -261,15 +266,21 @@ function getScopedFilesForTask(
return safeFilepaths.filter((f) => {
switch (task) {
case "css-tokens":
return !!status.css.legacy.find((config) => config.fileName === f);
return !!status.css.legacy.find((config: any) => config.fileName === f);
case "scss-tokens":
return !!status.scss.legacy.find((config) => config.fileName === f);
return !!status.scss.legacy.find(
(config: any) => config.fileName === f,
);
case "less-tokens":
return !!status.less.legacy.find((config) => config.fileName === f);
return !!status.less.legacy.find(
(config: any) => config.fileName === f,
);
case "js-tokens":
return !!status.js.legacy.find((config) => config.fileName === f);
return !!status.js.legacy.find((config: any) => config.fileName === f);
case "tailwind-tokens":
return !!status.tailwind.legacy.find((config) => config.fileName === f);
return !!status.tailwind.legacy.find(
(config: any) => config.fileName === f,
);
default:
return false;
}
@@ -361,7 +372,12 @@ async function getNextTask(status?: any): Promise<TaskName> {
} as any);
return response.task;
} catch (error) {
if (error.isTtyError) {
if (
error != null &&
typeof error === "object" &&
"isTtyError" in error &&
error.isTtyError
) {
console.info(
"Oops, something went wrong! Looks like @navikt/aksel can't run in this terminal. " +
"Contact Aksel for support if this persists, or try another terminal.",
@@ -190,7 +190,10 @@ async function printRemaining(files: string[], status?: TokenStatus["status"]) {
clipboardy.writeSync(JSON.stringify(jsonOutput, null, 2));
console.info("✅ Report (JSON) copied to clipboard!");
} catch (error) {
console.error("❌ Failed to copy to clipboard:", error.message);
console.error(
"❌ Failed to copy to clipboard:",
error instanceof Error ? error.message : String(error),
);
}
}
}
@@ -29,7 +29,7 @@ function getStatus(
progressBar.start(files.length, 0);
}
StatusStore.initStatus();
StatusStore.resetStatus();
/**
* Prepare search terms for legacy and v8 tokens.
@@ -39,7 +39,7 @@ export default function transformer(file: FileInfo, api: API) {
oldJsVar,
"@navikt/ds-tokens/dist/tokens",
).forEach((x) => {
foundName = x.node.imported.name;
foundName = x.node.imported.name as string;
});
if (!foundName) {
@@ -14,7 +14,7 @@ export default function transformer(file: FileInfo) {
let src = file.source;
for (const config of Object.values(legacyTokenConfig)) {
if (config.replacement.length > 0) {
if (config.replacement.length > 0 && config.regexes.less) {
src = src.replace(
config.regexes.less,
translateToken(`--ax-${config.replacement}`, "less"),
@@ -14,7 +14,7 @@ export default function transformer(file: FileInfo) {
let src = file.source;
for (const config of Object.values(legacyTokenConfig)) {
if (config.replacement.length > 0) {
if (config.replacement.length > 0 && config.regexes.scss) {
src = src.replace(
config.regexes.scss,
translateToken(`--ax-${config.replacement}`, "scss"),
+214
View File
@@ -0,0 +1,214 @@
import type { SupportedCodemodExtensions } from "./codemod/codeshift.utils";
const JS_EXTENSIONS = [
"js",
"jsx",
"ts",
"tsx",
] satisfies SupportedCodemodExtensions[];
const CSS_EXTENSIONS = [
"css",
"scss",
"less",
] satisfies SupportedCodemodExtensions[];
type MigrationT = Record<
string,
{
description: string;
value: string;
path: string;
warning?: string;
/**
* Some transforms are only meant to run on specific file extensions.
* This is used to filter out files that should not be transformed.
*/
ignoredExtensions: SupportedCodemodExtensions[];
}[]
>;
const migrations: MigrationT = {
v1: [
{
description: "Runs all codemods for beta -> v1 migration",
value: "v1-preset",
path: "v1.0.0/preset/preset",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Fixes breaking API-changes for <Pagination /> component",
value: "v1-pagination",
path: "v1.0.0/pagination/pagination",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Fixes breaking API-changes for <Tabs /> component",
value: "v1-tabs",
path: "v1.0.0/tabs/tabs",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Fixes breaking API-changes for <SpeechBubble /> (now <Chat/>) component",
value: "v1-chat",
path: "v1.0.0/chat/chat",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v2: [
{
description: "Patches changed css-variables",
value: "v2-css",
path: "v2.0.0/update-css-tokens/update-css-tokens",
ignoredExtensions: [],
},
{
description: "Patches changed js-variables",
value: "v2-js",
path: "v2.0.0/update-js-tokens/update-js-tokens",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Patches changed sass-variables",
value: "v2-sass",
path: "v2.0.0/update-sass-tokens/update-sass-tokens",
ignoredExtensions: JS_EXTENSIONS,
},
{
description: "Patches changed less-variables",
value: "v2-less",
path: "v2.0.0/update-less-tokens/update-less-tokens",
ignoredExtensions: JS_EXTENSIONS,
},
],
v3: [
{
description:
"Replaces deprecated <CopyToClipboard /> with <CopyButton />",
value: "v3-copybutton",
path: "v3.0.0/copybutton/copybutton",
warning:
"Remember to remove css-import from '@navikt/ds-css-internal' if no longer needed\nIf non-text was used as children, or different locales were handled, you need to manually fix this",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v4: [
{
description:
"Replaced deprecated 'internal'-component import to 'core'-imports",
value: "v4-internal-react",
path: "v4.0.0/internal-react/internal-react",
warning:
"Remember to also run 'v4-internal-css' if you have overwritten any css-classes!",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Replaced 'navdsi'-prefixes used to overwrite internal-css to 'navds'-prefixes",
value: "v4-internal-css",
path: "v4.0.0/internal-css/internal-css",
warning:
"Remember to remove '@navikt/ds-css-internal' imports if no longer needed! Also run 'v4-internal-react' to convert internal-react imports to core-imports",
ignoredExtensions: [],
},
{
description:
"Removes all instances of UNSAFE_ for datepicker/monthpicker.",
value: "v4-date",
path: "v4.0.0/date/date",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v6: [
{
description:
"Removes `backgroundColor` and `avatarBgColor` properties from `Chat` and `Chat.Bubble`",
value: "v6-chat",
path: "v6.0.0/chat/chat",
warning:
"Remember to update use of `variant`-prop to match previous use of colors. If needed the component exposes css-variables for custom overrides",
ignoredExtensions: CSS_EXTENSIONS,
},
],
v8: [
{
description:
"Updates Box with legacy-tokens to Box using the new token system, and renames already migrated BoxNew/Box.New instances to Box.",
value: "v8-box",
path: "v8.0.0/box/box",
warning:
"Remember to check if 'TODO: Aksel Box migration'-comment was added to any files after migration. This comment will help you find and update Box-instances we couldn't update for you.",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Renames already migrated BoxNew/Box.New instances to Box.",
value: "v8-box-new",
path: "v8.0.0/box-new/box-new",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Removes deprecated props from components.",
value: "v8-prop-deprecate",
path: "v8.0.0/prop-deprecate/prop-deprecate",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Tries to migrate List component by wrapping it with 'Box' and moving 'title' and 'description' props to 'Heading' and 'BodyShort'.",
value: "v8-list",
path: "v8.0.0/list/list",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description: "Updates all Primitives to use new `space`-tokens.",
value: "v8-primitive-spacing",
path: "v8.0.0/primitives-spacing/spacing",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Tag based on current variant prop.",
value: "v8-tag-variant",
path: "v8.0.0/tag-variant/tag-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on ToggleGroup based on current variant prop.",
value: "v8-toggle-group-variant",
path: "v8.0.0/toggle-group-variant/toggle-group-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Accordion based on current variant prop.",
value: "v8-accordion-variant",
path: "v8.0.0/accordion-variant/accordion-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Chips based on current variant prop.",
value: "v8-chips-variant",
path: "v8.0.0/chips-variant/chips-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Button based on current variant prop.",
value: "v8-button-variant",
path: "v8.0.0/button-variant/button-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
{
description:
"Updates variant + data-color props on Link based on current variant prop.",
value: "v8-link-variant",
path: "v8.0.0/link-variant/link-variant",
ignoredExtensions: CSS_EXTENSIONS,
},
],
} as const;
export { migrations };
+2 -1
View File
@@ -4,8 +4,9 @@
"sourceMap": false,
"esModuleInterop": true,
"target": "es2015",
"lib": ["ES2021"],
"preserveWatchOutput": true,
"declaration": false,
"declaration": true,
"types": ["node"],
"outDir": "dist",
"rootDir": "./src",
+64
View File
@@ -1,5 +1,69 @@
# @navikt/ds-css
## 8.10.2
### Patch Changes
- Dialog: Now aligns to bottom when centered at 480px instead of 768px screen width ([#4831](https://github.com/navikt/aksel/pull/4831))
## 8.10.1
### Patch Changes
- Modal: Changing `size` had no effect before ([#4823](https://github.com/navikt/aksel/pull/4823))
## 8.10.0
### Minor Changes
- DatePicker: Highlight days between start and hovered day ([#4801](https://github.com/navikt/aksel/pull/4801))
### Patch Changes
- Skeleton: Text-variant now has properly rounded edges ([#4808](https://github.com/navikt/aksel/pull/4808))
- ExpandableRow: Fix selected row top border not showing when row above was collapsed ([#4810](https://github.com/navikt/aksel/pull/4810))
- Timeline: Icons in periods now scale based on avaliable space. No longer clips on smaller periods ([#4809](https://github.com/navikt/aksel/pull/4809))
- DatePicker, MonthPicker: Change styling on disabled days/months ([#4801](https://github.com/navikt/aksel/pull/4801))
- InfoCard: Align header with content when no icon is present for small version. ([#4815](https://github.com/navikt/aksel/pull/4815))
- InfoCard, LocalAlert, GlobalAlert: Update content typography use and sizing. ([#4815](https://github.com/navikt/aksel/pull/4815))
## 8.9.1
### Patch Changes
- Button: Use correct text color when inherited `data-color` is "neutral" ([#4772](https://github.com/navikt/aksel/pull/4772))
- Checkbox, Radio: Internal updates. ([#4760](https://github.com/navikt/aksel/pull/4760))
- Datepicker, Monthpicker: Sync background on DateInput button to Input. ([#4781](https://github.com/navikt/aksel/pull/4781))
## 8.9.0
### Minor Changes
- InternalHeader: Added `isActive`-prop to `InternalHeader.Button`. ([#4761](https://github.com/navikt/aksel/pull/4761))
### Patch Changes
- DatePicker, MonthPicker: Make open button more prominent ([#4751](https://github.com/navikt/aksel/pull/4751))
## 8.8.0
### Minor Changes
- ReadMore: Added variant `moderate`. ([#4723](https://github.com/navikt/aksel/pull/4723))
- InfoCard: New sub-component InfoCard.Message. ([#4717](https://github.com/navikt/aksel/pull/4717))
### Patch Changes
- GlobalAlert, LocalAlert: Content outline changed from 4px to 2px. ([#4745](https://github.com/navikt/aksel/pull/4745))
## 8.7.0
### Minor Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "8.7.0",
"version": "8.10.2",
"description": "CSS for Nav Designsystem",
"author": "Aksel | Nav designsystem team",
"keywords": [
@@ -30,9 +30,9 @@
"css:get-version": "node config/get-version.js"
},
"devDependencies": {
"@navikt/ds-tokens": "^8.7.0",
"@navikt/ds-tokens": "^8.10.2",
"browserslist": "^4.25.0",
"esbuild": "^0.27.2",
"esbuild": "^0.27.4",
"fast-glob": "3.3.3",
"lightningcss": "^1.30.1",
"normalize.css": "^8.0.1",
+35 -2
View File
@@ -114,11 +114,16 @@
&[data-variant="moderate"] {
outline: 1px solid var(--ax-border-default);
outline-offset: -1px;
/* Adjust horizontal padding for small moderate alerts */
&[data-size="small"] {
--__axc-base-alert-pi: var(--ax-space-16);
}
}
&[data-variant="strong"] {
outline: 4px solid var(--ax-border-default);
outline-offset: -4px;
outline: 2px solid var(--ax-border-default);
outline-offset: -2px;
&[data-color="neutral"] {
outline-color: var(--ax-border-strong);
@@ -145,6 +150,9 @@
background: var(--ax-bg-moderate);
color: var(--ax-text-default);
border-color: var(--ax-border-subtleA);
/* Optical alignment */
padding-top: var(--ax-space-1);
}
.aksel-base-alert[data-variant="strong"] & {
@@ -172,6 +180,10 @@
padding: var(--__axc-base-alert-content-p);
background-color: var(--ax-bg-default);
&[data-color] {
color: var(--ax-text-neutral);
}
.aksel-base-alert[data-global="true"] & {
padding-inline: var(--__axc-global-alert-alignment);
}
@@ -192,3 +204,24 @@
color: var(--ax-text-neutral-contrast);
}
}
.aksel-base-alert__message {
border-radius: var(--ax-radius-12);
height: fit-content;
outline: 1px solid var(--ax-border-default);
outline-offset: -1px;
background: var(--ax-bg-moderate);
color: var(--ax-text-default);
display: flex;
align-items: flex-start;
gap: var(--ax-space-8);
padding: var(--ax-space-12) var(--ax-space-16);
& > .aksel-base-alert__icon {
margin-top: var(--ax-space-2);
}
.aksel-base-alert[data-size="small"] & > .aksel-base-alert__icon {
margin-top: 0;
}
}
+10 -4
View File
@@ -44,7 +44,9 @@
background-color: transparent;
color: var(--ax-text-subtle);
&[data-color="neutral"] {
&[data-color="neutral"],
[data-color="neutral"] > &:not([data-color]),
[data-color="neutral"] :not([data-color]) &:not([data-color]) {
color: var(--ax-text-default);
}
@@ -62,7 +64,8 @@
color: var(--ax-text-subtle);
background-color: transparent;
&[data-color="neutral"] {
&[data-color="neutral"],
[data-color="neutral"] > &:not([data-color]) {
color: var(--ax-text-default);
}
}
@@ -72,7 +75,9 @@
background-color: transparent;
color: var(--ax-text-subtle);
&[data-color="neutral"] {
&[data-color="neutral"],
[data-color="neutral"] > &:not([data-color], [data-pressed="true"]),
[data-color="neutral"] :not([data-color]) &:not([data-color], [data-pressed="true"]) {
color: var(--ax-text-default);
}
@@ -93,7 +98,8 @@
color: var(--ax-text-subtle);
background-color: transparent;
&[data-color="neutral"] {
&[data-color="neutral"],
[data-color="neutral"] > &:not([data-color]) {
color: var(--ax-text-default);
}
}
-2
View File
@@ -95,8 +95,6 @@
padding-left: var(--ax-space-6);
}
/* -------------------------- start old CSS -------------------------- */
/* ----------------------------- Chips removable ---------------------------- */
.aksel-chips__removable {
gap: 0;
+285 -82
View File
@@ -1,3 +1,4 @@
/* stylelint-disable csstools/value-no-unknown-custom-properties */
/* stylelint-disable no-duplicate-selectors */
.aksel-data-table__border-wrapper {
@@ -48,41 +49,70 @@
background-color: var(--ax-bg-neutral-softA);
}
}
&[data-truncate-content="true"] {
.aksel-data-table__td > div {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
}
.aksel-data-table__thead {
background-color: var(--ax-bg-raised);
position: sticky;
top: 0;
.aksel-data-table[data-loading="true"] &::after {
content: "";
position: absolute;
block-size: 2px;
inset-block-end: -2px;
background-color: var(--ax-bg-strong);
animation: animateDataTableLoading 1s linear infinite;
z-index: 11;
}
}
.aksel-data-table__tbody {
background-color: var(--ax-bg-raised);
}
position: relative;
.aksel-data-table__tr--selected {
background-color: var(--ax-bg-softA);
box-shadow:
inset 1px 0 0 0 var(--ax-border-default),
inset -1px 0 0 0 var(--ax-border-default);
&[inert] {
transition: opacity 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
opacity: var(--ax-opacity-disabled);
&:first-of-type {
box-shadow:
inset 1px 0 0 0 var(--ax-border-default),
inset -1px 0 0 0 var(--ax-border-default),
inset 0 1px 0 0 var(--ax-border-default);
@starting-style {
opacity: 0.001;
}
}
& :is(.aksel-data-table__td, .aksel-data-table__th) {
border-color: var(--ax-border-default);
&[inert]::after {
content: "";
position: absolute;
inset: 0;
background-color: var(--ax-bg-overlay);
transition: opacity 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
z-index: 10;
opacity: 0.2;
/* iOS 26+: Ensure the backdrop covers the entire visible viewport. */
@starting-style {
opacity: 0.001;
}
}
}
.aksel-data-table__tr {
&[data-selected="true"] {
background-color: var(--ax-bg-softA);
}
.aksel-data-table__thead &[data-sticky="true"] {
position: sticky;
top: 0;
z-index: 3;
&::after {
content: "";
position: absolute;
inset-inline: 0;
bottom: -1px;
pointer-events: none;
border-bottom: 1px solid var(--ax-border-neutral-subtle);
}
}
}
@@ -100,6 +130,7 @@
pointer-events: none;
border: 1px solid var(--ax-border-neutral-subtle);
border-radius: var(--ax-radius-12);
z-index: 3;
}
}
@@ -111,16 +142,32 @@
}
.aksel-data-table__thead {
position: relative; /* Shadow ends up behind loading/empty-state without, consider after-element instead like with sticky */
box-shadow: 0 1px 0 0 var(--ax-border-neutral-subtle);
}
.aksel-data-table__th,
.aksel-data-table__td {
.aksel-data-table__cell {
/* border doesn't work on sticky thead when we have collapsed borders, so using box-shadow instead */
box-shadow: inset 1px 1px 0 0 var(--ax-border-neutral-subtle);
text-align: start;
vertical-align: middle;
scroll-margin: var(--ax-space-0);
padding: 0;
&[data-nested="true"] {
position: relative;
& > div {
margin-inline-start: calc(32px + 8px + calc(var(--__axc-data-table-nested-depth) * var(--ax-space-16)));
}
}
.aksel-data-table__thead & {
background-color: var(--ax-bg-neutral-soft);
}
&[data-align="left"] {
text-align: left;
text-align: start;
}
&[data-align="center"] {
@@ -128,18 +175,90 @@
}
&[data-align="right"] {
text-align: right;
text-align: end;
}
&[data-sticky] {
position: sticky;
z-index: 1;
&::after {
content: "";
position: absolute;
inset-block: 0;
pointer-events: none;
border-color: var(--ax-border-neutral-subtle);
border-style: solid;
border-width: 0;
}
&[data-sticky="start"] {
left: 0;
&::after {
inset-inline: 0 -1px;
border-right-width: 1px;
}
}
&[data-sticky="end"] {
right: 0;
}
background-color: var(--ax-bg-raised);
.aksel-data-table__thead & {
background-color: var(--ax-bg-neutral-soft);
}
}
&:focus-visible,
/* Focus instead of focus-visible so that effect of sort-icon staying isnt strange */
/* TODO: Update from th to generic */
&:has(.aksel-data-table__th-sort-button:focus) {
outline: 2px solid var(--ax-border-focus);
outline-offset: -4px;
}
&[data-selectable="true"] {
padding: 0;
& > div {
display: grid;
place-content: center;
}
}
--__axc-data-table-pi-cell: var(--ax-space-16);
&:not([data-selectable="true"]) > div {
padding-block: var(--__axc-data-table-density);
padding-inline: var(--__axc-data-table-pi-cell);
.aksel-data-table[data-truncate-content="true"] & {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
}
/* BORDER STYLING END */
.aksel-data-table__th {
.aksel-data-table__column-header {
/* TODO: Might want this to be dynamic */
--__axc-data-table-density: var(--ax-space-8);
position: relative;
background-color: var(--ax-bg-neutral-soft);
color: var(--ax-text-neutral);
padding: var(--ax-space-8) var(--ax-space-16);
text-align: start;
font-weight: var(--ax-font-weight-bold);
&:has(.aksel-data-table__th-sort-button:hover) {
background-color: var(--ax-bg-neutral-moderate-hover);
}
&:has(.aksel-data-table__th-sort-button:active) {
background-color: var(--ax-bg-neutral-moderate-pressed);
}
&[data-sortable="true"] {
padding: 0;
@@ -151,21 +270,14 @@
display: flex;
align-items: center;
gap: var(--ax-space-2);
padding-inline-start: var(--ax-space-16);
block-size: calc(var(--__axc-data-table-density) + 1.5rem);
width: 100%;
cursor: pointer;
text-align: start;
background-color: transparent;
border: none;
&:hover {
background-color: var(--ax-bg-neutral-moderate-hover);
}
&:active {
background-color: var(--ax-bg-neutral-moderate-pressed);
}
font-weight: inherit;
padding: 0;
&:focus-visible {
outline: none;
@@ -200,7 +312,7 @@
}
.aksel-data-table__th-resize-handle {
z-index: 2;
z-index: 1;
position: absolute;
cursor: col-resize;
margin: 0;
@@ -231,6 +343,13 @@
transition: background 50ms linear;
}
&:hover,
&:focus-visible,
&:active {
/* Avoids clipping when having sticky columns */
z-index: 3;
}
&:hover::after {
/* TODO: Consider if the resize-handle should be visible already when hovering the column header */
background: var(--ax-bg-strong);
@@ -241,7 +360,7 @@
background: var(--ax-bg-strong-pressed);
}
.aksel-data-table__th:last-of-type & {
.aksel-data-table__column-header:last-of-type & {
inset-inline-end: 0;
width: 15px;
@@ -299,18 +418,6 @@
}
}
.aksel-data-table__td {
text-align: start;
vertical-align: middle;
color: var(--ax-text-neutral-subtle);
> div {
padding-block: var(--__axc-data-table-density);
padding-inline: 1rem;
}
}
.aksel-data-table__td,
.aksel-data-table__th {
scroll-margin-block: var(--ax-space-0);
scroll-margin-inline: var(--ax-space-0);
@@ -321,6 +428,15 @@
outline: 2px solid var(--ax-border-focus);
outline-offset: -4px;
}
&[data-selectable="true"] {
padding: 0;
& > div {
display: grid;
place-content: center;
}
}
}
.aksel-data-table__tfoot {
@@ -330,17 +446,38 @@
.aksel-data-table__filler-cell {
width: auto;
display: table-cell;
padding: 0;
}
.aksel-data-drag-and-drop__drag-handler__button {
height: 1.5rem;
position: relative;
background: transparent;
border: none;
padding: 0;
&:hover {
cursor: grab;
}
&:focus-visible,
&[data-drag-handler-active="true"] {
outline: 2px solid var(--ax-border-focus);
outline-offset: -1px;
border-radius: var(--ax-radius-8);
}
}
.aksel-data-table__drag-and-drop-item {
&[data-dragging="true"] {
background: var(--ax-bg-default);
}
background-color: var(--ax-bg-default);
&[data-mouse-dragging="true"]:not(:active) {
&[data-overlay="true"] {
width: 100%;
opacity: 0.8;
box-shadow: var(--ax-shadow-dialog);
}
/* TODO - might be removable */
&[data-keyboard-dragging="true"] {
.aksel-data-drag-and-drop__drag-handler__button {
outline: 2px solid var(--ax-border-focus);
@@ -349,44 +486,110 @@
}
}
&[data-drop-target="true"] {
&[data-drop-target="true"]:not([data-overlay="true"]) {
background: var(--ax-bg-neutral-moderate);
}
}
.aksel-data-drag-and-drop__drag-handler__button {
cursor: grab;
.aksel-data-drag-and-drop__drag-handler__alt,
.aksel-data-drag-and-drop__drag-handler {
position: relative;
height: 1.5rem;
position: relative;
background: transparent;
border: none;
padding: 0;
&:focus-visible {
outline: 2px solid var(--ax-border-focus);
outline-offset: -1px;
border-radius: var(--ax-radius-8);
}
}
.aksel-data-drag-and-drop__drag-handler__arrow {
height: 1.2rem;
}
.aksel-data-drag-and-drop__drag-handler__alt {
position: relative;
.aksel-data-drag-and-drop__drag-handler__arrow {
height: 1.8rem;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background: var(--ax-bg-default);
border: none;
cursor: pointer;
padding: 0;
border-radius: 50%;
z-index: 1;
&[data-direction="up"] {
top: -10px;
top: -18px;
}
&[data-direction="down"] {
bottom: calc(-100% - 6px);
bottom: calc(-100% - 22px);
}
&:disabled {
opacity: 0.8;
cursor: not-allowed;
}
}
}
.aksel-data-table__empty-state {
display: grid;
place-content: center;
padding-block: var(--ax-space-32);
padding-inline: var(--ax-space-16);
text-align: center;
gap: var(--ax-space-8);
justify-items: center;
}
.aksel-data-table__loading-state {
display: grid;
place-content: center;
padding-block: var(--ax-space-32);
padding-inline: var(--ax-space-16);
text-align: center;
gap: var(--ax-space-8);
justify-items: center;
position: relative;
}
@keyframes animateDataTableLoading {
0% {
inset-inline-start: 0;
inline-size: 0;
}
20% {
inset-inline-start: 0;
inline-size: 40%;
}
80% {
inset-inline-start: 60%;
inline-size: 40%;
}
100% {
inset-inline-start: 100%;
inline-size: 0;
}
}
/* TODO: Look to handle "inline"-checkbox better than custom CSS-overrides in the future. */
.aksel-data-table tr .aksel-checkbox {
padding: 0;
}
.aksel-data-table tr .aksel-checkbox:focus-within::after {
inset: 0;
}
/* TODO -
* This is needed to prevent the cursor from changing back to default when dragging over interactive elements in the row.
* Not sure if this is the best approach or breaks styling elsewhere */
html[data-dragging-cursor="true"],
html[data-dragging-cursor="true"] *,
html[data-dragging-cursor="true"] *::before,
html[data-dragging-cursor="true"] *::after {
cursor: grabbing !important;
}
/* TODO: alignment not optimal when resizing column with nesting */
.aksel-data-table__nested-toggle {
position: absolute;
inset-block: 0;
left: calc(var(--__axc-data-table-pi-cell) + var(--__axc-data-table-nested-depth) * var(--ax-space-16));
display: flex;
align-items: center;
}
+78 -9
View File
@@ -1,36 +1,105 @@
/* .aksel-property-filter {
flex: 1 1 fit-content;
max-inline-size: 100%;
} */
.aksel-property-filter__popup {
overflow: hidden;
border-radius: var(--ax-radius-12);
border-radius: var(--ax-radius-8);
border: 1px solid var(--ax-border-neutral-subtleA);
box-shadow: var(--ax-shadow-dialog);
/* stylelint-disable-next-line csstools/value-no-unknown-custom-properties */
transform-origin: var(--__axc-floating-transform-origin);
transition:
transform 150ms ease allow-discrete,
opacity 150ms ease allow-discrete;
transition: opacity 150ms ease allow-discrete;
@starting-style {
opacity: 0.8;
transform: scale3d(0.94, 0.94, 0.94);
opacity: 0.6;
}
min-width: 260px;
}
.aksel-property-filter__popup-inner {
--__axc-token-filter-content-p: var(--ax-space-8);
--__axc-token-filter-item-pr: var(--ax-space-8);
--__axc-token-filter-item-pl: var(--ax-space-8);
--__axc-token-filter-item-height: 2rem;
border-radius: var(--ax-radius-12);
border-radius: var(--ax-radius-8);
background-color: var(--ax-bg-raised);
min-width: 128px;
max-width: min(95vw, 640px);
animation-duration: 160ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
padding: var(--__axc-token-filter-content-p);
overflow: auto;
/* stylelint-disable-next-line csstools/value-no-unknown-custom-properties */
max-height: calc(var(--__axc-floating-available-height) - 4px);
}
.aksel-property-filter__input {
max-inline-size: 640px;
}
.aksel-property-filter__chips {
display: flex;
flex-wrap: wrap;
gap: var(--ax-space-8);
margin: 0;
margin-block-start: var(--ax-space-12);
padding: 0;
font-size: var(--ax-font-size-medium);
}
.aksel-property-filter__chip {
display: flex;
gap: var(--ax-space-1);
}
.aksel-property-filter__chip-button {
display: flex;
align-items: center;
gap: var(--ax-space-4);
padding: var(--ax-space-4) var(--ax-space-8);
background-color: var(--ax-bg-strong);
color: var(--ax-text-contrast);
border: none;
cursor: pointer;
&:hover {
background-color: var(--ax-bg-strong-hover);
}
&:active {
background-color: var(--ax-bg-strong-pressed);
}
&:focus-visible {
outline: 3px solid var(--ax-border-focus);
outline-offset: 2px;
z-index: 1;
}
&:first-of-type {
border-start-start-radius: var(--ax-radius-8);
border-end-start-radius: var(--ax-radius-8);
}
&:last-child {
border-start-end-radius: var(--ax-radius-8);
border-end-end-radius: var(--ax-radius-8);
}
&[data-type="operation"] {
/* background-color: var(--ax-bg-default);
box-shadow: inset 0 0 0 1px var(--ax-bg-strong);
color: var(--ax-text-default); */
color: var(--ax-text-neutral);
background-color: var(--ax-bg-neutral-moderate-pressed);
}
/* &[data-type="value"] {
} */
&[data-type="remove"] {
padding-inline: var(--ax-space-4);
}
}
+24 -13
View File
@@ -1,18 +1,29 @@
.aksel-data-toolbar {
padding: var(--ax-space-12);
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: var(--ax-space-8);
}
.aksel-data-toolbar__actions {
margin-inline-start: auto;
display: flex;
align-items: center;
> :not(:last-child) {
border-right: 1px solid var(--ax-border-neutral-subtle);
margin-inline-end: var(--ax-space-4);
padding-inline-end: var(--ax-space-4);
}
}
.aksel-data-toolbar__input {
flex: 1 1 fit-content;
max-inline-size: 100%;
}
.aksel-data-toolbar__pagination {
display: flex;
align-items: center;
gap: var(--ax-space-8);
border: 1px solid var(--ax-border-neutral);
border-radius: var(--ax-radius-12);
background-color: var(--ax-bg-raised);
}
.aksel-data-toolbar__toggle-button {
&[aria-pressed="true"] {
--__axc-button-border-width: 0px; /* ??? */
color: var(--ax-text-contrast);
background-color: var(--ax-bg-strong-pressed);
}
}
+89 -52
View File
@@ -4,11 +4,11 @@
padding: var(--ax-space-16);
.rdp-table {
border-collapse: separate; /* Some CSS-resets sets border-collapse:collapse on tables */
border-collapse: collapse;
}
.rdp-cell {
padding: 1px; /* Some CSS-resets sets padding:0 on all items */
padding: 0;
&[data-outside="true"] {
width: var(--__axc-date-button-size);
@@ -23,18 +23,22 @@
}
.rdp-day_range_middle {
&.rdp-day_disabled {
&.rdp-day_disabled .rdp-day__inner {
color: var(--ax-text-neutral);
background: var(--ax-bg-neutral-moderateA);
}
&.rdp-day_selected {
&.rdp-day_selected .rdp-day__inner {
background-color: var(--ax-bg-moderate-pressedA);
box-shadow: inset 0 0 0 1px var(--ax-border-subtleA);
color: var(--ax-text-neutral);
}
}
.rdp-button.rdp-day__range-hover-middle .rdp-day__inner {
background-color: var(--ax-bg-moderate-hoverA);
}
.rdp-month,
&.rdp-month {
display: grid;
@@ -52,22 +56,30 @@
.rdp-button {
all: unset;
display: block;
width: var(--__axc-date-button-size);
height: var(--__axc-date-button-size);
text-align: center;
padding: var(--ax-space-2);
cursor: pointer;
& .rdp-day__inner {
width: var(--__axc-date-button-size);
height: var(--__axc-date-button-size);
}
}
.rdp-day__inner {
display: grid;
place-items: center;
border-radius: var(--ax-radius-8);
}
.rdp-day_range_start {
.rdp-day_range_start .rdp-day__inner {
border-radius: 100% var(--ax-radius-12) var(--ax-radius-12) 100%;
}
.rdp-day_range_end:not(.rdp-day_range_start) {
.rdp-day_range_end:not(.rdp-day_range_start) .rdp-day__inner {
border-radius: var(--ax-radius-8) 100% 100% var(--ax-radius-8);
}
.rdp-day_range_start.rdp-day_range_end {
.rdp-day_range_start.rdp-day_range_end .rdp-day__inner {
border-radius: var(--ax-radius-8);
}
@@ -78,24 +90,23 @@
position: relative;
}
.rdp-day_selected,
.aksel-monthpicker__month--selected {
.rdp-day_selected .rdp-day__inner {
color: var(--ax-text-contrast);
background: var(--ax-bg-strong-pressed);
cursor: pointer;
}
.rdp-day_disabled {
.rdp-day_disabled .rdp-day__inner {
cursor: not-allowed;
text-decoration: line-through;
background-color: var(--ax-bg-neutral-moderateA);
color: var(--ax-text-neutral-subtle);
opacity: var(--ax-opacity-disabled);
}
.rdp-button:where(:not(.rdp-day_selected, [disabled])):hover,
.aksel-date__month-button:where(:not(.rdp-day_selected, [disabled])):hover {
background: var(--ax-bg-moderate-hoverA);
cursor: pointer;
.rdp-day__inner {
background: var(--ax-bg-moderate-hoverA);
}
}
.rdp-day_today {
@@ -154,7 +165,7 @@
justify-content: space-between;
align-items: center;
gap: var(--ax-space-4);
padding-inline: var(--ax-space-4);
padding-inline: var(--ax-space-2);
}
.aksel-date__caption-button {
@@ -167,15 +178,17 @@
text-transform: capitalize;
}
/* Monthpicker */
/* MonthPicker */
.aksel-date__month-button {
all: unset;
text-align: center;
width: 3rem;
height: 3rem;
text-transform: capitalize;
border-radius: var(--ax-radius-8);
padding: var(--ax-space-2);
cursor: pointer;
& .rdp-day__inner {
width: 3rem;
height: 3rem;
text-transform: capitalize;
}
}
.aksel-date__year-label {
@@ -190,12 +203,12 @@
.rdp-cell > button.rdp-day,
button.aksel-date__month-button {
&:focus-visible {
&:focus-visible .rdp-day__inner {
outline: 3px solid var(--ax-border-focus);
outline-offset: 3px;
}
&:active:not(:disabled) {
&:active:not(:disabled) .rdp-day__inner {
color: var(--ax-text-contrast);
background-color: var(--ax-bg-strong-pressed);
}
@@ -203,35 +216,41 @@
}
.aksel-date__field-input {
&.aksel-text-field__input {
padding-right: var(--ax-space-48);
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: none;
&:focus-visible {
outline: none;
}
.aksel-form-field--small & {
padding-right: var(--ax-space-32);
.aksel-date__field--error &:not(:disabled) {
box-shadow:
inset -2px 0 0 0 var(--ax-border-danger-strong),
inset 0 0 0 1px var(--ax-border-danger-strong);
}
}
.aksel-date__field-button {
position: absolute;
right: 0.0625rem;
top: 50%;
transform: translateY(-50%);
color: var(--ax-text-neutral);
display: inline-flex;
cursor: pointer;
margin: 0;
text-decoration: none;
border: none;
background: none;
border-radius: calc(var(--ax-radius-8) - 1px);
padding: var(--ax-space-12);
align-items: center;
justify-content: center;
font-size: 1.5rem;
height: calc(100% - 0.125rem);
--__axc-button-border-width: 1px;
--__axc-button-border-color: var(--ax-border-neutral);
border-start-start-radius: 0;
border-end-start-radius: 0;
position: relative;
&:focus-visible {
outline: 3px solid var(--ax-border-focus);
outline-offset: 3px;
}
.aksel-date__field:not(.aksel-date__field--readonly):has(.aksel-date__field-input:not(:disabled)) &:hover,
.aksel-date__field:not(.aksel-date__field--readonly, .aksel-date__field--error):has(
.aksel-date__field-input:is(:focus-visible, :hover):not(:disabled)
)
& {
--__axc-button-border-color: var(--ax-border-strong);
}
.aksel-form-field--small & {
padding: var(--ax-space-4);
@@ -244,19 +263,37 @@
/* Readonly */
.aksel-date__field--readonly & {
--__axc-button-border-color: var(--ax-border-neutral-subtleA);
cursor: default;
opacity: 1;
background-color: var(--ax-bg-neutral-moderate);
color: var(--ax-text-neutral-subtle);
}
&:focus-visible {
outline-color: var(--ax-border-focus);
/* Syncs button-bg with input while respecting hover/active states */
&::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background-color: var(--ax-bg-input);
z-index: -1;
}
}
.aksel-date__field-wrapper {
display: inline-flex;
align-items: center;
position: relative;
width: fit-content;
border-radius: var(--ax-radius-8);
/* Initializes stacking context to allow z-index: -1 on button to work. */
z-index: 0;
&:has(.aksel-date__field-input:focus-visible) {
outline: 3px solid var(--ax-border-focus);
outline-offset: 3px;
}
}
.aksel-date__week-row {
+1 -1
View File
@@ -96,7 +96,7 @@
transform: translateY(calc(1rem * var(--__axc-nested-level) * -1)) scale(calc(1 - 0.02 * var(--__axc-nested-level)));
}
@media (max-width: 768px) or (max-height: 479px) {
@media (max-width: 480px) or (max-height: 479px) {
--__axc-dialog-transform: translateY(35%);
max-height: calc(100dvh - max(16px, 10dvh));
+2 -1
View File
@@ -18,7 +18,8 @@
}
/* Applied when hideLegend is applied to fieldset */
.aksel-fieldset > .aksel-sr-only + :not(:first-child, :empty) {
.aksel-fieldset > .aksel-sr-only + :not(:first-child, :empty),
.aksel-fieldset > .aksel-typo--visually-hidden + :not(:first-child, :empty) {
margin-top: 0;
}
Loaded 100 of 389 files, more files were not shown because too many files have changed in this diff. Show more