Compare commits

...
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] 792962592f Version Packages (#2720)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-08 13:08:21 +01:00
Ken 4a02a1987c Deprecate Panel (#2712)
* ⚰️ Markert Panel som deprecated

* 📝 Changeset

* 📝 JSDOC var feil for border på Box

* 🐛 📝 JSDoc manglet border-radius
2024-02-08 11:46:20 +01:00
Ken 700943b4a5 [ci skip] ♻️ Refaktorert Button-story 2024-02-07 20:31:25 +01:00
Ken 521c982457 🚚 Oppdatert imports til direkteimports og ikke fra root-index (#2715) 2024-02-07 16:17:17 +01:00
Ken 8c17099087 🔥 Fjernet hyphen på blogg-headings (#2711)
* 🔥 Fjernet hyphen på blogg-headings

* 🎨 Bare hyphens på mobil
2024-02-07 13:42:58 +01:00
Ken 29241a7153 ⚡ Refaktorert alert-stories for mindre chromatic-tester (#2709)
* ⚡ refaktorert alert-stories for mindre chromatic-tester

* 🐛 Fikset imports
2024-02-07 13:42:26 +01:00
github-actions[bot]andgithub-actions[bot] 7e4ee40a7f Version Packages (#2708)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-07 12:26:07 +01:00
Halvor Haugan 2be97970d6 Date/MonthPicker: Justeringer JSDOC og eksempel-desc (#2704) 2024-02-07 09:42:37 +01:00
Halvor Haugan 5b3c1f33c4 Eksterne typer kommer nå med i docgen (#2705) 2024-02-07 09:30:27 +01:00
KenandHalvor Haugan f44ff44410 Bytter ut FloatingPortal med egen implementasjon (#2697)
* 🎉 Egen Portal-komponent

* 🎨 Portal og Overlay exportert i root

* ♻️ Tooltip bruker egen Portal

* 📝 Changeset

* 🔥 Fjernet ID på Portal-element

* 🎉 Ny type WithAsChild

* ♻️ Mer robust sjekk for conditional elements i WithAsChild

* 📝 WithAsChild JSDOC

* 📝 WithAsChild JSDOC 2

* Update .changeset/lovely-points-heal.md

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

* ♻️ Fikset kommentarer fra git-pr

---------

Co-authored-by: Halvor Haugan <83693529+HalvorHaugan@users.noreply.github.com>
2024-02-06 18:02:00 +01:00
Ken 855669538e ⚡ Kjører bare release-workflow når nødvendige filer er endret (#2701) 2024-02-06 18:01:43 +01:00
github-actions[bot]andgithub-actions[bot] 3d830dc123 Version Packages (#2703)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-06 13:56:46 +01:00
Ken dcca2a9560 Expansioncard padding top (#2699)
* 🎉 Justert padding for expansioncard small

* 🎉 Justert padding for expansioncard small
2024-02-06 13:10:08 +01:00
Ken 26fb028f07 ⚡ Filterer ut chromatic-snapshots for build-files (#2700) 2024-02-06 11:59:51 +01:00
Halvor Haugan d928769d6f [aksel.nav.no] Fiks for teksting i video 2024-02-05 14:55:22 +01:00
Julian Nymark e96d33d13e 👷 update permissions (removed too much) 2024-02-05 14:35:38 +01:00
Julian Nymark 00ebe1c18b 👷 update workflow (post merge) 2024-02-05 14:31:51 +01:00
Julian NymarkandKen 53be894ad0 Gp popular articles (#2647)
* ❇️ new schema for view tracking

* 🚧 wip for article views schema

* 🚧 wip on schema

* 🚧 schema changes for ArticleViews

* 🚧 run prettier with new config

* 🚧 deno script to update article views

* 🚧 working sanity document updates with bogus view data

* 🚧 helper to delete all article_views

* 🚧 add views_day

* ✨ working update for views on all gp articles

* 💄 eye icon for page views in sanity studio

* ♻️ cleanup from PR review / huddle

* 🚧 improvements to updateViews script

* 🚧 seemingly healthy queries (sometimes proxy gives stale data?)

* 👷 add .github/workflow for update views

* 👷 update .github/workflow for update views

* 👷 add env var in workflow

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* ♻️ refactor from PR comments

* 👷 update workflow

* 🐛 correct paths to changelog script

* 🐛 remove unused ?? -1

* 👷 dockerfile and naisjob.yml

* 👷 yml variable formatting

* 👷 yml update

* 👷 yml variable formatting

* 🔨 .prettierignore for all yml/yaml starting with nais

* 👷 unique name for naisjob

* 👷 new nais yaml

* 👷 yml variable formatting

* 👷 remove workflow, the workflow is developed in main

* 👷 update yml

* 🚧 update naisjob yml

* 🚧 update naisjob yml

* 🚧 update Dockerfile

* 🚧 update Dockerfile (permissions)

* 🚧 update Dockerfile

* 🚧 update Dockerfile

* 🚧 update Dockerfile

* 👷 decouple config code from rest of repo (more duplication, more robustness), build with correct docker context

* 👷 cache deps in dockerfile on build-time (no need to fetch at runtime and add to pod AccessPolicy)

* 👷 relative path might work, test Dockerfile live as it works fine locally... buildx?!

* 👷 test github action docker context tweak

* 👷 test script command entrypoint (workdir is not project root)

* 👷 add AccessPolicy for reops-proxy

* 👷 better github workflow naming

* 👷 refactor _and_ optimize the dockerfile

* 👷 new docker command path for nais yml

* Update scripts/article-views/queries.ts

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>

* 👷 do not add rows if no data

* 🐛 fix sanity query) + now delete + update in single transaction

---------

Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
2024-02-05 14:29:14 +01:00
Julian Nymark 614946097e [aksel.nav.no] ♿ forbedret Video-modul (#2693) 2024-02-05 14:09:43 +01:00
89 changed files with 1144 additions and 676 deletions

No files matched your search

+2
View File
@@ -59,7 +59,9 @@ jobs:
exitZeroOnChanges: false
buildScriptName: "build:storybook"
onlyChanged: true
untraced: "**/package.json|yarn.lock|**/*.md"
externals: \@navikt/core/css/**/*.css
traceChanged: true
env:
STORYBOOK_GITHUB_SHA: ${{ github.sha }}
+3
View File
@@ -2,6 +2,9 @@ name: Release
on:
push:
paths:
- ".changeset/**"
- "@navikt/**"
branches:
- main
workflow_dispatch:
+1 -2
View File
@@ -4,14 +4,13 @@ on:
jobs:
execute:
runs-on: ubuntu-latest
permissions: # TODO: remove once merged
permissions:
packages: "write"
contents: "read"
id-token: "write"
steps:
- uses: actions/checkout@v3
with:
ref: gp-popular-articles # TODO: remove once merged
fetch-depth: 1
- uses: denoland/setup-deno@v1
with:
+2 -2
View File
@@ -1,5 +1,5 @@
**/nais-dev.yaml
**/nais-prod.yaml
**/nais*.yaml
**/nais*.yml
**/codemod/**/tests/**/*.js
node_modules
.next
+1 -1
View File
@@ -10,7 +10,7 @@ export const parameters = {
"Getting started",
"ds-react",
["Primitives"],
["Default"],
["Default", "Controls"],
"Aksel-icons",
],
},
+6
View File
@@ -1,5 +1,11 @@
# @navikt/aksel-icons
## 5.18.1
## 5.18.0
## 5.17.5
## 5.17.4
## 5.17.3
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-icons",
"version": "5.17.4",
"version": "5.18.1",
"author": "Aksel | NAV",
"homepage": "https://aksel.nav.no/ikoner",
"repository": {
+6
View File
@@ -1,5 +1,11 @@
# @navikt/aksel-stylelint
## 5.18.1
## 5.18.0
## 5.17.5
## 5.17.4
## 5.17.3
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-stylelint",
"version": "5.17.4",
"version": "5.18.1",
"author": "Aksel | NAV",
"homepage": "https://aksel.nav.no/grunnleggende/kode/stylelint",
"repository": {
@@ -35,8 +35,8 @@
"dev": "yarn watch:lint"
},
"devDependencies": {
"@navikt/ds-css": "^5.17.4",
"@navikt/ds-tokens": "^5.17.4",
"@navikt/ds-css": "^5.18.1",
"@navikt/ds-tokens": "^5.18.1",
"@types/jest": "^29.0.0",
"concurrently": "7.2.1",
"copyfiles": "2.4.1",
+21
View File
@@ -1,5 +1,26 @@
# @navikt/aksel
## 5.18.1
### Patch Changes
- Updated dependencies []:
- @navikt/ds-css@5.18.1
## 5.18.0
### Patch Changes
- Updated dependencies []:
- @navikt/ds-css@5.18.0
## 5.17.5
### Patch Changes
- Updated dependencies [[`dcca2a956`](https://github.com/navikt/aksel/commit/dcca2a95600152cb84c3b79ba5bb3894ac63e881)]:
- @navikt/ds-css@5.17.5
## 5.17.4
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel",
"version": "5.17.4",
"version": "5.18.1",
"description": "Aksel command line interface. Handles css-imports, codemods and more",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -29,7 +29,7 @@
},
"homepage": "https://aksel.nav.no/grunnleggende/kode/kommandolinje",
"dependencies": {
"@navikt/ds-css": "5.17.4",
"@navikt/ds-css": "5.18.1",
"axios": "1.6.0",
"chalk": "4.1.0",
"clipboardy": "^2.3.0",
+10
View File
@@ -1,5 +1,15 @@
# @navikt/ds-css
## 5.18.1
## 5.18.0
## 5.17.5
### Patch Changes
- ExpansionCard: Padding-top for Content er justert opp 8px (medium) og 4px (small) ([#2699](https://github.com/navikt/aksel/pull/2699))
## 5.17.4
## 5.17.3
+5 -1
View File
@@ -177,7 +177,7 @@
* Content *
*************************/
.navds-expansioncard__content {
--__ac-expansioncard-padding-block: var(--a-spacing-3);
--__ac-expansioncard-padding-block: var(--a-spacing-5);
border-end-end-radius: var(--__ac-expansioncard-border-radius);
border-end-start-radius: var(--__ac-expansioncard-border-radius);
@@ -187,6 +187,10 @@
border-top: none;
}
.navds-expansioncard--small .navds-expansioncard__content {
--__ac-expansioncard-padding-block: var(--a-spacing-4);
}
.navds-expansioncard__content--closed {
display: none;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "5.17.4",
"version": "5.18.1",
"description": "CSS for NAV Designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -27,7 +27,7 @@
"css:get-version": "node config/get-version.js"
},
"devDependencies": {
"@navikt/ds-tokens": "^5.17.4",
"@navikt/ds-tokens": "^5.18.1",
"cssnano": "6.0.0",
"fast-glob": "3.2.11",
"lodash": "4.17.21",
+30
View File
@@ -1,5 +1,35 @@
# @navikt/ds-react
## 5.18.1
### Patch Changes
- Panel: Komponent er nå markert som deprecated. Bruk `Box` i fremtiden. ([#2712](https://github.com/navikt/aksel/pull/2712))
- Updated dependencies []:
- @navikt/ds-tokens@5.18.1
- @navikt/aksel-icons@5.18.1
## 5.18.0
### Minor Changes
- Portal: Ny komponent `Portal` som lar deg enkelt bruke `createPortal`, også på serversiden ([#2697](https://github.com/navikt/aksel/pull/2697))
### Patch Changes
- Updated dependencies []:
- @navikt/ds-tokens@5.18.0
- @navikt/aksel-icons@5.18.0
## 5.17.5
### Patch Changes
- Updated dependencies []:
- @navikt/ds-tokens@5.17.5
- @navikt/aksel-icons@5.17.5
## 5.17.4
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "5.17.4",
"version": "5.18.1",
"description": "Aksel react-components for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -38,8 +38,8 @@
},
"dependencies": {
"@floating-ui/react": "0.25.4",
"@navikt/aksel-icons": "^5.17.4",
"@navikt/ds-tokens": "^5.17.4",
"@navikt/aksel-icons": "^5.18.1",
"@navikt/ds-tokens": "^5.18.1",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
@@ -1,6 +1,6 @@
import React, { useState } from "react";
import { Accordion, AccordionProps } from ".";
import { Table } from "..";
import { Table } from "../table";
import AccordionContent from "./AccordionContent";
import AccordionHeader from "./AccordionHeader";
import AccordionItem from "./AccordionItem";
+202 -113
View File
@@ -1,12 +1,16 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, userEvent, within } from "@storybook/test";
import React from "react";
import { Alert, AlertProps } from ".";
import { BodyLong, Heading as DsHeading, Link } from "..";
import { VStack } from "../layout/stack";
import { Link } from "../link";
import { BodyLong, Heading as DsHeading } from "../typography";
import Alert, { AlertProps } from "./Alert";
const meta: Meta<typeof Alert> = {
title: "ds-react/Alert",
component: Alert,
parameters: {
chromatic: { disable: true },
},
};
export default meta;
@@ -20,12 +24,13 @@ const variants: AlertProps["variant"][] = [
"success",
];
export const Default: Story = {
export const Controls: Story = {
render: (props) => <Alert {...props} />,
args: {
children: "Id elit esse enim reprehenderit enim nisi veniam nostrud.",
fullWidth: false,
inline: false,
variant: "info",
size: "medium",
closeButton: false,
@@ -42,43 +47,18 @@ export const Default: Story = {
},
};
export const Small: Story = {
render: (props) => {
return (
<div className="colgap">
{variants.map((variant, i) => (
<Alert
key={variant}
variant={variant}
size="small"
closeButton={props.closeButton}
>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
</Alert>
))}
</div>
);
},
args: {
closeButton: false,
},
};
export const FullWidth = () => {
export const Variants = () => {
return (
<div className="colgap">
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} fullWidth>
<Alert key={variant} variant={variant}>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
</Alert>
))}
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} fullWidth size="small">
<Alert key={variant} variant={variant} size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
@@ -88,24 +68,42 @@ export const FullWidth = () => {
);
};
export const FullWidth = () => {
return (
<VStack gap="4">
<Alert variant="info" fullWidth>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" fullWidth size="small">
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
</VStack>
);
};
export const Inline = () => {
return (
<div className="colgap">
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} inline>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
</Alert>
))}
{variants.map((variant, i) => (
<Alert key={variant} variant={variant} inline size="small">
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
</Alert>
))}
</div>
<VStack gap="4">
<h2>Inline</h2>
<Alert variant="info" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim reprehenderit
enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim reprehenderit
enim nisi veniam nostrud.
</Alert>
</VStack>
);
};
@@ -136,82 +134,173 @@ export const Heading = () => {
);
};
export const Links = () => {
return (
<div className="colgap">
{variants.map((variant) => (
<Alert key={variant} variant={variant}>
<Link href="#">Id elit esse enim reprehenderit</Link>
</Alert>
))}
</div>
);
};
const AlertWithCloseButton = ({
children,
size,
}: {
size?: "medium" | "small";
children?: React.ReactNode;
}) => {
const [show, setShow] = React.useState(true);
return show ? (
<Alert
variant="warning"
size={size}
closeButton
onClose={() => setShow(false)}
>
{children || "Content"}
</Alert>
) : null;
};
export const WithCloseButton: Story = {
export const CloseButton: Story = {
render: () => {
return (
<div className="colgap">
<AlertWithCloseButton />
<AlertWithCloseButton>
<BodyLong>Ullamco ullamco laborum et commodo sint culpa</BodyLong>
</AlertWithCloseButton>
<AlertWithCloseButton>
<DsHeading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
<VStack gap="4">
<h2>CloseButton</h2>
<Alert variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert size="small" variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert size="small" variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" closeButton>
<DsHeading size="small" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
sint commodo consequat eu aute.
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</AlertWithCloseButton>
<AlertWithCloseButton size="small">
<BodyLong>Ullamco ullamco laborum et commodo</BodyLong>
</AlertWithCloseButton>
<AlertWithCloseButton size="small">
<DsHeading spacing size="small" level="3">
Aliquip duis est in commodo pariatur
</Alert>
<Alert variant="info" closeButton size="small">
<DsHeading size="xsmall" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong>
Ullamco ullamco laborum et commodo sint culpa cupidatat culpa qui
laboris ex. Labore ex occaecat proident qui qui fugiat magna. Fugiat
sint commodo consequat eu aute.
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</AlertWithCloseButton>
</div>
</Alert>
</VStack>
);
},
play: async ({ canvasElement, step }) => {
const canvas = within(canvasElement);
const buttons = canvas.getAllByTitle("Lukk Alert");
};
await step("click button", async () => {
await userEvent.click(buttons[0]);
});
export const Chromatic: Story = {
render: () => (
<VStack gap="6">
<VStack gap="2">
<h2>Variant</h2>
{variants.map((variant, i) => (
<Alert key={variant} variant={variant}>
{new Array(i + 1).fill(
"Id elit esse enim reprehenderit enim nisi veniam nostrud.",
)}
</Alert>
))}
</VStack>
<VStack gap="2">
<h2>Small</h2>
<Alert variant="info" size="small">
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small">
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
</VStack>
<VStack gap="2">
<h2>FullWidth</h2>
<Alert variant="info" fullWidth>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small" fullWidth>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
</VStack>
<VStack gap="2">
<h2>Inline</h2>
<Alert variant="info" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" size="small" inline>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
</VStack>
<VStack gap="2">
<h2>Heading</h2>
<Alert variant="info">
<DsHeading size="small" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</Alert>
<Alert variant="info" size="small">
<DsHeading size="xsmall" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong size="small">
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</Alert>
</VStack>
<VStack gap="2">
<h2>CloseButton</h2>
<Alert variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert size="small" variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert size="small" variant="info" closeButton>
Id elit esse enim reprehenderit enim nisi veniam nostrud. Id elit esse
enim reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud. Id elit esse enim
reprehenderit enim nisi veniam nostrud.
</Alert>
<Alert variant="info" closeButton>
<DsHeading size="small" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong>
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</Alert>
<Alert variant="info" size="small" closeButton>
<DsHeading size="xsmall" level="3">
Id elit esse enim reprehenderit
</DsHeading>
<BodyLong size="small">
Id elit esse enim reprehenderit enim nisi veniam nostrud.
</BodyLong>
</Alert>
</VStack>
const buttonsAfter = canvas.getAllByTitle("Lukk Alert");
expect(buttonsAfter.length).toBe(4);
<VStack gap="2">
<h2>Links</h2>
{variants.map((variant) => (
<Alert key={variant} variant={variant}>
<Link href="#">Id elit esse enim reprehenderit</Link>
</Alert>
))}
</VStack>
</VStack>
),
parameters: {
chromatic: { disable: false },
},
};
+96 -193
View File
@@ -1,15 +1,21 @@
import { StoryObj } from "@storybook/react";
import React from "react";
import { StarIcon } from "@navikt/aksel-icons";
import { StarIcon as BaseStarIcon } from "@navikt/aksel-icons";
import { HStack, VStack } from "../layout/stack";
import { Button } from "./index";
export default {
title: "ds-react/Button",
component: Button,
parameters: {
chromatic: { delay: 600 },
chromatic: { disable: true },
},
};
type Story = StoryObj<typeof Button>;
const StarIcon = () => <BaseStarIcon aria-hidden />;
const variants: (
| "primary"
| "secondary"
@@ -28,17 +34,7 @@ const variants: (
"tertiary-neutral",
];
const varSwitch = {
primary: "Primary",
secondary: "Secondary",
tertiary: "Tertiary",
danger: "Danger",
"primary-neutral": "Primary",
"secondary-neutral": "Secondary",
"tertiary-neutral": "Tertiary",
};
export const Default = {
export const Controls: Story = {
render: (props) => {
return (
<Button
@@ -57,7 +53,7 @@ export const Default = {
icon: false,
loading: false,
iconPosition: "left",
children: "Knapp",
children: "Button",
variant: "primary",
size: "medium",
},
@@ -91,192 +87,99 @@ export const Default = {
},
};
export const Small = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="small">
{varSwitch[variant]}
</Button>
))}
</div>
);
export const XSmall = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} size="xsmall">
{varSwitch[variant]}
</Button>
))}
</div>
);
export const Link = () => (
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} as="a" href="#thecakeisalie">
{varSwitch[variant]}
</Button>
))}
</div>
);
export const Loading = {
render: () => (
<div className="colgap chromatic-ignore">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading>
{varSwitch[variant]}
function ButtonGrid(props: any) {
return (
<VStack gap="2">
{variants.map((variant) => (
<HStack gap="2" key={variant}>
<Button variant={variant} {...props}>
Button
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading size="small">
{varSwitch[variant]}
<Button variant={variant} {...props} icon={<StarIcon />}>
Button
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading size="xsmall">
{varSwitch[variant]}
</Button>
))}
</div>
</div>
),
parameters: {
chromatic: { disableSnapshot: true },
},
};
export const Icon = () => (
<div className="colgap ">
<div className="rowgap">
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
icon={<StarIcon title="Stjerne" />}
/>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
size="small"
icon={<StarIcon title="Stjerne" />}
/>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
size="xsmall"
icon={<StarIcon title="Stjerne" />}
/>
))}
</div>
</div>
);
export const IconWText = () => (
<div className="colgap">
<div className="rowgap">
{variants.map((variant, i) => (
<Button
key={variant}
variant={variant}
icon={<StarIcon title="Stjerne" />}
iconPosition={i % 2 ? "left" : "right"}
>
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant, i) => (
<Button
key={variant}
variant={variant}
size="small"
icon={<StarIcon title="Stjerne" />}
iconPosition={i % 2 ? "left" : "right"}
>
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant, i) => (
<Button
key={variant}
variant={variant}
size="xsmall"
icon={<StarIcon title="Stjerne" />}
iconPosition={i % 2 ? "left" : "right"}
>
{varSwitch[variant]}
</Button>
))}
</div>
</div>
);
export const Disabled = () => (
<div className="colgap">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} disabled>
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} disabled as="a" href="#">
{varSwitch[variant]}
</Button>
))}
</div>
</div>
);
export const LoadingWithAs = {
render: () => (
<div className="colgap chromatic-ignore">
<div className="rowgap">
{variants.map((variant) => (
<Button key={variant} variant={variant} loading size="small">
{varSwitch[variant]}
</Button>
))}
</div>
<div className="rowgap">
{variants.map((variant) => (
<Button
key={variant}
variant={variant}
loading
size="small"
as="a"
href="#"
{...props}
icon={<StarIcon />}
iconPosition="right"
>
{varSwitch[variant]}
Button
</Button>
))}
</div>
</div>
),
<Button variant={variant} {...props} icon={<StarIcon />} />
</HStack>
))}
</VStack>
);
}
export const Medium: Story = {
render: () => <ButtonGrid size="medium" />,
};
export const Small: Story = {
render: () => <ButtonGrid size="small" />,
};
export const XSmall: Story = {
render: () => <ButtonGrid size="xsmall" />,
};
export const AsLink: Story = {
render: () => (
<VStack gap="4">
<Button href="#" as="a">
Button as a-tag
</Button>
<Button href="#" as="a" disabled>
Disabled Button as a-tag
</Button>
</VStack>
),
};
export const Loading: Story = {
render: () => <ButtonGrid loading />,
};
export const LoadingAsLink: Story = {
render: () => <ButtonGrid loading href="#" as="a" />,
};
export const Disabled: Story = {
render: () => <ButtonGrid disabled />,
};
export const DisabledAsLink: Story = {
render: () => <ButtonGrid disabled href="#" as="a" />,
};
export const Chromatic: Story = {
render: () => (
<VStack gap="6" align="center">
<div>
<h2>Medium</h2>
<ButtonGrid size="medium" />
</div>
<div>
<h2>Small</h2>
<ButtonGrid size="small" />
</div>
<div>
<h2>XSmall</h2>
<ButtonGrid size="xsmall" />
</div>
<div>
<h2>As Link</h2>
<ButtonGrid as="a" href="#" />
</div>
<div>
<h2>Disabled</h2>
<ButtonGrid disabled />
</div>
</VStack>
),
parameters: {
chromatic: { disableSnapshot: true },
chromatic: { disable: false },
},
};
@@ -2,8 +2,12 @@
import { Meta, StoryObj } from "@storybook/react";
import isSameDay from "date-fns/isSameDay";
import React, { useId, useState } from "react";
import { useDatepicker, useRangeDatepicker } from "..";
import { BodyLong, Button, HGrid, Modal, VStack } from "../..";
import { Button } from "../../button";
import { HGrid } from "../../layout/grid";
import { VStack } from "../../layout/stack";
import Modal from "../../modal/Modal";
import { BodyLong } from "../../typography";
import { useDatepicker, useRangeDatepicker } from "../hooks";
import DatePicker, { DatePickerProps } from "./DatePicker";
const disabledDays = [
@@ -53,7 +53,7 @@ export interface UseDatepickerOptions
* Allows input of with 'yy' year format.
* @default true
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
* In 2023 this equals to 1943 - 2042
* In 2024 this equals to 1944 - 2043
*/
allowTwoDigitYear?: boolean;
/**
@@ -39,7 +39,7 @@ export interface UseMonthPickerOptions
* Allows input of with 'yy' year format.
* @default true
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
* In 2023 this equals to 1943 - 2042
* In 2024 this equals to 1944 - 2043
*/
allowTwoDigitYear?: boolean;
/**
@@ -1,8 +1,9 @@
import { Meta, StoryFn } from "@storybook/react";
import setYear from "date-fns/setYear";
import React, { useId, useState } from "react";
import { Button, DateInputProps } from "../..";
import { Button } from "../../button";
import { useMonthpicker } from "../hooks";
import { DateInputProps } from "../parts/DateInput";
import MonthPicker from "./MonthPicker";
import { MonthPickerProps } from "./types";
@@ -15,7 +15,7 @@ export interface DateInputProps
*/
label: React.ReactNode;
/**
* Shows label and description for screenreaders-only
* Shows label and description for screen readers only
* @default false
*/
hideLabel?: boolean;
@@ -1,7 +1,7 @@
import { Meta } from "@storybook/react";
import React, { useState } from "react";
import { Dropdown } from "..";
import { Button } from "../button";
import Dropdown from "./Dropdown";
export default {
title: "ds-react/Dropdown",
@@ -1,6 +1,6 @@
import { Meta } from "@storybook/react";
import React from "react";
import { ErrorSummary } from "..";
import { ErrorSummary } from "./ErrorSummary";
export default {
title: "ds-react/Errorsummary",
@@ -1,6 +1,6 @@
import { Meta } from "@storybook/react";
import React, { useState } from "react";
import { Link } from "../..";
import { Link } from "../../link";
import { ConfirmationPanel } from "../index";
export default {
@@ -1,6 +1,7 @@
import { Meta, StoryFn, StoryObj } from "@storybook/react";
import React, { useEffect, useRef } from "react";
import { BodyLong, Heading, HelpText } from "..";
import { BodyLong, Heading } from "../typography";
import HelpText from "./HelpText";
const meta: Meta<typeof HelpText> = {
title: "ds-react/HelpText",
+1
View File
@@ -10,6 +10,7 @@ export * from "./expansion-card";
export * from "./form";
export * from "./grid";
export * from "./guide-panel";
export * from "./overlays";
export * from "./help-text";
export * from "./internal-header";
export * from "./link";
@@ -6,7 +6,8 @@ import {
MenuGridIcon,
} from "@navikt/aksel-icons";
import { BodyLong, BodyShort, Detail } from "@navikt/ds-react";
import { Dropdown, InternalHeader } from "..";
import { Dropdown } from "../dropdown";
import InternalHeader from "./InternalHeader";
export default {
title: "ds-react/InternalHeader",
@@ -1,7 +1,8 @@
import type { Meta } from "@storybook/react";
import React from "react";
import { Box, HStack, VStack } from "../..";
import { BodyLong } from "../../typography";
import { Box } from "../box";
import { HStack, VStack } from "../stack";
import { Bleed } from "./Bleed";
export default {
@@ -1,8 +1,9 @@
import type { Meta } from "@storybook/react";
import React, { ReactNode } from "react";
import { ChevronRightIcon } from "@navikt/aksel-icons";
import { HGrid, HStack, VStack } from "../..";
import { BodyLong, Detail, Heading } from "../../typography";
import { HGrid } from "../grid";
import { HStack, VStack } from "../stack";
import { BackgroundToken, BorderRadiiToken } from "../utilities/types";
import { Box } from "./Box";
@@ -1,6 +1,9 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import { Box, HGrid, Hide, Show, VStack } from "../..";
import { Box } from "../box";
import { HGrid } from "../grid";
import { Hide, Show } from "../responsive";
import { VStack } from "../stack";
import { Content } from "./Content";
import { FilterCard } from "./Filter";
import { Header } from "./Header";
@@ -13,6 +16,7 @@ const meta = {
title: "kitchen sink/navno-sidemal",
parameters: {
layout: "fullscreen",
chromatic: { disable: true },
},
} satisfies Meta;
@@ -1,6 +1,6 @@
import { Meta } from "@storybook/react";
import React from "react";
import { LinkPanel } from "..";
import LinkPanel from "./LinkPanel";
export default {
title: "ds-react/LinkPanel",
@@ -1,11 +1,9 @@
import React from "react";
import { PlusCircleFillIcon } from "@navikt/aksel-icons";
import {
BodyLong,
Alert as DsAlert,
ConfirmationPanel as DsConfirmationPanel,
Link,
} from "../..";
import { Alert } from "../../alert";
import { ConfirmationPanel } from "../../form";
import { BodyLong } from "../../typography";
import Link from "../Link";
import { RandomIcon } from "./RandomIcon";
export default {
@@ -139,37 +137,37 @@ const DemoLink = () => (
export const Icon = () => <DemoLink />;
export const Alert = () => {
export const InAlert = () => {
return (
<div className="colgap">
<DsAlert variant="info">
<Alert variant="info">
<DemoLink />
</DsAlert>
<DsAlert variant="success">
</Alert>
<Alert variant="success">
<DemoLink />
</DsAlert>
<DsAlert variant="warning">
</Alert>
<Alert variant="warning">
<DemoLink />
</DsAlert>
<DsAlert variant="error">
</Alert>
<Alert variant="error">
<DemoLink />
</DsAlert>
</Alert>
</div>
);
};
export const ConfirmationPanel = () => {
export const InConfirmationPanel = () => {
return (
<div className="colgap">
<DsConfirmationPanel label="demo">
<ConfirmationPanel label="demo">
<DemoLink />
</DsConfirmationPanel>
<DsConfirmationPanel checked label="demo">
</ConfirmationPanel>
<ConfirmationPanel checked label="demo">
<DemoLink />
</DsConfirmationPanel>
<DsConfirmationPanel error="demo" label="demo">
</ConfirmationPanel>
<ConfirmationPanel error="demo" label="demo">
<DemoLink />
</DsConfirmationPanel>
</ConfirmationPanel>
</div>
);
};
+2 -1
View File
@@ -6,7 +6,8 @@ import {
HeadHeartIcon,
RecycleIcon,
} from "@navikt/aksel-icons";
import { List, VStack } from "..";
import { VStack } from "../layout/stack";
import List from "./List";
export default {
title: "ds-react/List",
@@ -1,6 +1,6 @@
import { Meta } from "@storybook/react";
import React from "react";
import { Loader, LoaderProps } from "..";
import Loader, { LoaderProps } from "./Loader";
export default {
title: "ds-react/Loader",
@@ -1,9 +1,11 @@
import { Meta, StoryFn } from "@storybook/react";
import React, { useRef, useState } from "react";
import { FileIcon } from "@navikt/aksel-icons";
import { BodyLong, Button, Heading, Tooltip } from "..";
import { Button } from "../button";
import { Checkbox, CheckboxGroup } from "../form/checkbox";
import { VStack } from "../layout/stack";
import { Tooltip } from "../tooltip";
import { BodyLong, Heading } from "../typography";
import Modal from "./Modal";
const meta: Meta<typeof Modal> = {
+2
View File
@@ -0,0 +1,2 @@
export { Portal } from "./portal/Portal";
export type { PortalProps } from "./portal/Portal";
@@ -0,0 +1,99 @@
import React from "react";
import { Box } from "../../layout/box";
import { Provider } from "../../provider";
import { Portal } from "./Portal";
export default {
title: "Utilities/Portal",
parameters: {
chromatic: { disable: true },
},
};
export const Default = () => {
return (
<Box background="surface-neutral-subtle" border>
<h1>In regular DOM tree</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio eum
commodi tempora unde. Nulla vel tempora incidunt? Voluptatem molestias
impedit commodi. Tenetur!
</p>
<Portal>
<h1>Inside Portal to different DOM tree</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio
eum commodi tempora unde. Nulla vel tempora incidunt? Voluptatem
molestias impedit commodi. Tenetur!
</p>
</Portal>
</Box>
);
};
export const CustomPortalRoot = () => {
const [portalContainer, setPortalContainer] =
React.useState<HTMLDivElement | null>(null);
return (
<Box background="surface-neutral-subtle">
<Box background="surface-alt-1-subtle">
<h1>Tree A</h1>
<Portal rootElement={portalContainer}>
<p>This is mounted to Tree B, while created inside Tree A</p>
</Portal>
</Box>
<Box background="surface-alt-3-subtle" ref={setPortalContainer}>
<h1>Tree B</h1>
</Box>
</Box>
);
};
export const CustomPortalRootFromProvider = () => {
const [portalContainer, setPortalContainer] =
React.useState<HTMLDivElement>();
return (
<Provider rootElement={portalContainer}>
<Box background="surface-neutral-subtle">
<Box background="surface-alt-1-subtle">
<h1>Tree A</h1>
<Portal>
<p>This is mounted to Tree B, while created inside Tree A</p>
</Portal>
</Box>
<Box background="surface-alt-3-subtle" ref={setPortalContainer}>
<h1>Tree B</h1>
</Box>
</Box>
</Provider>
);
};
export const AsChild = () => {
return (
<Box background="surface-neutral-subtle" border>
<h1>In regular DOM tree</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio eum
commodi tempora unde. Nulla vel tempora incidunt? Voluptatem molestias
impedit commodi. Tenetur!
</p>
<Portal asChild>
<div data-this-is-the-child>
<h1>Inside Portal to different DOM tree</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus
necessitatibus quis esse nesciunt est velit voluptatibus. Distinctio
eum commodi tempora unde. Nulla vel tempora incidunt? Voluptatem
molestias impedit commodi. Tenetur!
</p>
</div>
</Portal>
</Box>
);
};
@@ -0,0 +1,32 @@
import React, { HTMLAttributes, forwardRef } from "react";
import ReactDOM from "react-dom";
import { useProvider } from "../../provider";
import { Slot } from "../../util/Slot";
import { AsChildProps } from "../../util/types";
interface PortalBaseProps extends HTMLAttributes<HTMLDivElement> {
/**
* An optional container where the portaled content should be appended.
*/
rootElement?: HTMLElement | null;
}
export type PortalProps = PortalBaseProps & AsChildProps;
export const Portal = forwardRef<HTMLDivElement, PortalProps>(
({ rootElement, asChild, ...rest }, ref) => {
const contextRoot = useProvider()?.rootElement;
const root = rootElement ?? contextRoot ?? globalThis?.document?.body;
const Component = asChild ? Slot : "div";
return root
? ReactDOM.createPortal(
<Component ref={ref} data-aksel-portal="" {...rest} />,
root,
)
: null;
},
);
export default Portal;
+9 -16
View File
@@ -2,6 +2,9 @@ import cl from "clsx";
import React, { forwardRef } from "react";
import { OverridableComponent } from "../util/types";
/**
* @deprecated Use Box with padding and border instead
*/
export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
/**
* Panel content
@@ -17,23 +20,13 @@ export interface PanelProps extends React.HTMLAttributes<HTMLElement> {
export type PanelType = OverridableComponent<PanelProps, HTMLElement>;
/**
* A component that displays a bordered panel with heading and body.
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/panel)
* @see 🏷️ {@link PanelProps}
* @see [🤖 OverridableComponent](https://aksel.nav.no/grunnleggende/kode/overridablecomponent) support
*
* @example
* ```jsx
* <Panel border>
* <Heading spacing level="2" size="large">
* Søk om økonomisk sosialhjelp
* </Heading>
* <BodyLong>
* Du kan søke om det du trenger økonomisk støtte til.
* </BodyLong>
* </Panel>
* @deprecated
* Use Box with padding and border instead
* ```
* <Box padding="4" borderRadius="small" />
* <Box padding="4" borderWidth="1" borderRadius="small" />
* ```
* Component will be removed in a future major release
*/
export const Panel: PanelType = forwardRef(
(
@@ -1,63 +0,0 @@
import { Meta } from "@storybook/react";
import React from "react";
import { Panel } from "../index";
export default {
title: "ds-react/Panel",
component: Panel,
argTypes: {
border: {
defaultValue: true,
control: {
type: "boolean",
},
},
},
} as Meta;
export const Default = {
render: (props) => {
return (
<Panel {...props}>
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
</Panel>
);
},
};
export const Border = () => {
return (
<div className="colgap">
<Panel>
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
</Panel>
<Panel border>
Eu quis exercitation voluptate ex. Aute irure esse occaecat minim
cupidatat velit minim duis sint culpa anim laboris. Consectetur nulla eu
commodo ea culpa velit commodo incididunt sunt ipsum. Amet anim
adipisicing minim ipsum do. Non laborum culpa reprehenderit est sint
officia quis excepteur. Fugiat eiusmod eiusmod commodo incididunt nisi
minim ex eu cupidatat quis ex. Lorem irure ea ea enim consectetur ea
aliqua cupidatat. Officia aute veniam aute exercitation ipsum aliqua
adipisicing. Est aliqua ad ullamco aute nostrud amet ea adipisicing
consequat id officia irure pariatur. Eu mollit amet culpa culpa velit.
</Panel>
</div>
);
};
@@ -1,6 +1,6 @@
import { Meta } from "@storybook/react";
import React, { useState } from "react";
import { BodyLong } from "..";
import { BodyLong } from "../typography";
import Stepper from "./Stepper";
const meta: Meta<typeof Stepper> = {
@@ -1,7 +1,9 @@
import React, { useState } from "react";
import useSWR from "swr";
import { Loader, Pagination, SortState } from "../..";
import { Table } from "../index";
import { Loader } from "../../loader";
import { Pagination } from "../../pagination";
import Table from "../Table";
import { SortState } from "../types";
import peopleJson from "./people.json";
export default {
@@ -1,6 +1,8 @@
import React, { useState } from "react";
import { Table } from "..";
import { Button, Checkbox, Link } from "../..";
import { Button } from "../../button";
import { Checkbox } from "../../form";
import { Link } from "../../link";
import Table from "../Table";
export default {
title: "ds-react/Table",
@@ -1,6 +1,9 @@
import React, { useState } from "react";
import { Table, TableProps } from "../";
import { Alert, Button, Checkbox, CheckboxGroup, Link } from "../..";
import { Alert } from "../../alert";
import { Button } from "../../button";
import { Checkbox, CheckboxGroup } from "../../form";
import { Link } from "../../link";
export default {
title: "ds-react/Table",
@@ -1,6 +1,6 @@
import { expect, fn, userEvent, within } from "@storybook/test";
import React from "react";
import { Table } from "../..";
import Table from "../../Table";
export default {
title: "ds-react/Table/Tests",
+4 -8
View File
@@ -1,5 +1,4 @@
import {
FloatingPortal,
autoUpdate,
arrow as flArrow,
flip,
@@ -21,7 +20,7 @@ import React, {
useRef,
} from "react";
import { ModalContext } from "../modal/ModalContext";
import { useProvider } from "../provider";
import Portal from "../overlays/portal/Portal";
import { Detail } from "../typography";
import { useId } from "../util/hooks";
import { useControllableState } from "../util/hooks/useControllableState";
@@ -123,10 +122,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
const arrowRef = useRef<HTMLDivElement | null>(null);
const modalContext = useContext(ModalContext);
const providerRootElement = useProvider()?.rootElement;
const rootElement = modalContext
? modalContext.ref.current
: providerRootElement;
const rootElement = modalContext ? modalContext.ref.current : undefined;
const {
x,
@@ -199,7 +195,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
: children?.props["aria-describedby"],
}),
)}
<FloatingPortal root={rootElement}>
<Portal rootElement={rootElement}>
{_open && (
<div
{...getFloatingProps({
@@ -253,7 +249,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
)}
</div>
)}
</FloatingPortal>
</Portal>
</>
);
},
@@ -1,6 +1,9 @@
import { Meta } from "@storybook/react";
import React from "react";
import { Alert, Button, Search, Tooltip } from "..";
import { Alert } from "../alert";
import { Button } from "../button";
import { Search } from "../form";
import Tooltip from "./Tooltip";
export default {
title: "ds-react/Tooltip",
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { BodyLong } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import BodyLong from "../BodyLong";
const meta = {
title: "ds-react/Typography/BodyLong",
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { BodyShort } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import { BodyShort } from "../BodyShort";
const meta = {
title: "ds-react/Typography/BodyShort",
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { Detail } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import Detail from "../Detail";
const meta = {
title: "ds-react/Typography/Detail",
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { ErrorMessage } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import ErrorMessage from "../ErrorMessage";
const meta = {
title: "ds-react/Typography/ErrorMessage",
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import { default as React } from "react";
import { Heading } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import Heading from "../Heading";
const meta = {
title: "ds-react/Typography/Heading",
@@ -1,50 +0,0 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { Ingress } from "..";
const meta = {
title: "ds-react/Typography/deprecated/Ingress",
component: Ingress,
} satisfies Meta<typeof Ingress>;
export default meta;
type Story = StoryObj<typeof meta>;
const lorem =
"Hvis du ikke bor sammen med begge foreldrene dine, kan du ha rett til barnebidrag fra en eller begge foreldre mens du fullfører videregående skole eller tilsvarende.";
export const Default: Story = {
args: {
spacing: false,
children: lorem,
},
};
export const Spacing: Story = {
render: () => (
<div>
<Ingress spacing>{lorem}</Ingress>
<Ingress spacing>{lorem}</Ingress>
</div>
),
};
export const OverrideTag: Story = {
render: () => (
<div>
<Ingress spacing>default ingress</Ingress>
<Ingress as="legend">legend ingress</Ingress>
</div>
),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const defaultIngress = canvas.getByText("default ingress");
const legendIngress = canvas.getByText("legend ingress");
expect(defaultIngress.tagName).toEqual("P");
expect(legendIngress.tagName).toEqual("LEGEND");
},
};
@@ -1,8 +1,8 @@
import type { Meta, StoryObj } from "@storybook/react";
import { expect, within } from "@storybook/test";
import React from "react";
import { Label } from "..";
import { VStack } from "../..";
import { VStack } from "../../layout/stack";
import Label from "../Label";
const meta = {
title: "ds-react/Typography/Label",
+4 -2
View File
@@ -20,10 +20,12 @@ export const Slot = React.forwardRef<HTMLElement, SlotProps>(
}
if (React.Children.count(children) > 1) {
console.error(
const error = new Error(
"Aksel: Components using 'asChild' expects to recieve a single React element child.",
);
return React.Children.only(null);
error.name = "SlotError";
Error.captureStackTrace?.(error, Slot);
throw error;
}
return null;
@@ -0,0 +1,37 @@
export type AsChildProps =
| {
children: React.ReactElement | false | null;
/**
* Renders the component and its child as a single element,
* merging the props of the component with the props of the child.
*
* @example
* ```tsx
* <Component asChild data-prop>
* <ChildComponent data-child />
* </Component>
*
* // Renders
* <MergedComponent data-prop data-child />
* ```
*/
asChild: true;
}
| {
children: React.ReactNode;
/**
* Renders the component and its child as a single element,
* merging the props of the component with the props of the child.
*
* @example
* ```tsx
* <Component asChild data-prop>
* <ChildComponent data-child />
* </Component>
*
* // Renders
* <MergedComponent data-prop data-child />
* ```
*/
asChild?: false;
};
@@ -1 +1,2 @@
export type { OverridableComponent } from "./OverridableComponent";
export type { AsChildProps } from "./AsChildProps";
+6
View File
@@ -1,5 +1,11 @@
# @navikt/ds-tailwind
## 5.18.1
## 5.18.0
## 5.17.5
## 5.17.4
## 5.17.3
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "5.17.4",
"version": "5.18.1",
"description": "Tailwind config based on @navikt/ds-tokens",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -24,7 +24,7 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^5.17.4",
"@navikt/ds-tokens": "^5.18.1",
"@types/jest": "^29.0.0",
"color": "4.2.3",
"jest": "^29.0.0",
+6
View File
@@ -1,5 +1,11 @@
# @navikt/ds-tokens
## 5.18.1
## 5.18.0
## 5.17.5
## 5.17.4
## 5.17.3
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "5.17.4",
"version": "5.18.1",
"description": "Design-tokens for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
+80 -70
View File
@@ -1,12 +1,22 @@
# Changelog
## 5.18
### @navikt/ds-react
- Panel: Komponent er nå markert som deprecated. Bruk `Box` i fremtiden. ([#2712](https://github.com/navikt/aksel/pull/2712))
* Portal: Ny komponent `Portal` som lar deg enkelt bruke `createPortal`, også på serversiden ([#2697](https://github.com/navikt/aksel/pull/2697))
## 5.17
### @navikt/ds-css
- Checkbox: I noen edgecaser ved bruk av shadow-dom ble ikke checkmark sentert i Checkbox ([#2682](https://github.com/navikt/aksel/pull/2682))
- ExpansionCard: Padding-top for Content er justert opp 8px (medium) og 4px (small) ([#2699](https://github.com/navikt/aksel/pull/2699))
* Høykontrast: Komponenter støtter nå standard høykontrast-modus på Windows ([#2680](https://github.com/navikt/aksel/pull/2680))
* Checkbox: I noen edgecaser ved bruk av shadow-dom ble ikke checkmark sentert i Checkbox ([#2682](https://github.com/navikt/aksel/pull/2682))
- Høykontrast: Komponenter støtter nå standard høykontrast-modus på Windows ([#2680](https://github.com/navikt/aksel/pull/2680))
### @navikt/ds-react
@@ -78,6 +88,10 @@
- Page: Lagt til ny bakgrunnsfarge `surface-subtle` og ny maksbredde på Page.Block `text` ([#2572](https://github.com/navikt/aksel/pull/2572))
### @navikt/ds-tokens
- Tokens: Ny token `--a-text-width-max: 576px` ([#2572](https://github.com/navikt/aksel/pull/2572))
### @navikt/ds-react
- Accordion.Item, Dropdown, ReadMore og Tooltip: Har en ny prop `onOpenChange?: (open: boolean) => void;` som forteller nå-state når `open`-state endrer seg. Dette vil være nyttig hvis man ikke bruker controlled-state, men fortsatt ønsker å vite om komponenten er `open` eller ikke (f.eks logging). ([#2585](https://github.com/navikt/aksel/pull/2585))
@@ -86,10 +100,6 @@
* Page: Lagt til ny bakgrunnsfarge `surface-subtle` og ny maksbredde på Page.Block `text` ([#2572](https://github.com/navikt/aksel/pull/2572))
### @navikt/ds-tokens
- Tokens: Ny token `--a-text-width-max: 576px` ([#2572](https://github.com/navikt/aksel/pull/2572))
## 5.12
### @navikt/aksel-stylelint
@@ -254,6 +264,10 @@
- :lipstick: CopyButton: Justert padding, gap og animasjon ([#2355](https://github.com/navikt/aksel/pull/2355))
### @navikt/ds-tokens
- Ny spacing token på 0.375rem ([#2370](https://github.com/navikt/aksel/pull/2370))
### @navikt/ds-react
- :lipstick: Chips.Toggle: Ikon i uvalgt tilstand ([#2395](https://github.com/navikt/aksel/pull/2395))
@@ -274,10 +288,6 @@
- :lipstick: CopyButton: Justert padding, gap og animasjon ([#2355](https://github.com/navikt/aksel/pull/2355))
### @navikt/ds-tokens
- Ny spacing token på 0.375rem ([#2370](https://github.com/navikt/aksel/pull/2370))
### @navikt/aksel-icons
- Ikoner: Nye ikoner `ChevronLeftFirstCircle` og `ChevronRightLastCircle` ([#2365](https://github.com/navikt/aksel/pull/2365))
@@ -304,6 +314,10 @@
- MonthPicker: Tilpasset padding og sizing på mobil. ([#2311](https://github.com/navikt/aksel/pull/2311))
### @navikt/ds-tokens
- Tokens: Tilbyr nå token literals for typer, tidligere string literals ([#2342](https://github.com/navikt/aksel/pull/2342))
### @navikt/ds-react
- Datepicker: Popover legger seg nå ikke ovenfor input ([#2349](https://github.com/navikt/aksel/pull/2349))
@@ -330,10 +344,6 @@
- Remove tabIndex="-1" on Popover to fix VoiceOver navigation issue inside Popover ([#2303](https://github.com/navikt/aksel/pull/2303))
### @navikt/ds-tokens
- Tokens: Tilbyr nå token literals for typer, tidligere string literals ([#2342](https://github.com/navikt/aksel/pull/2342))
### @navikt/aksel-icons
- Ikoner: SVG export setter nå `height="1em"`, `width="1em"` og `fill="currentColor"`. ([#2300](https://github.com/navikt/aksel/pull/2300))
@@ -350,16 +360,16 @@
* Skeleton: Width fungerer nå med inline-variant av Skeleton ([#2273](https://github.com/navikt/aksel/pull/2273))
### @navikt/ds-tokens
- Box: Ny primitive, erstatter dagens `Panel` ([#2195](https://github.com/navikt/aksel/pull/2195))
### @navikt/ds-react
- Box: Ny primitive, erstatter dagens `Panel` ([#2195](https://github.com/navikt/aksel/pull/2195))
* Skeleton: Width fungerer nå med inline-variant av Skeleton ([#2273](https://github.com/navikt/aksel/pull/2273))
### @navikt/ds-tokens
- Box: Ny primitive, erstatter dagens `Panel` ([#2195](https://github.com/navikt/aksel/pull/2195))
## 5.4
### @navikt/ds-css
@@ -368,6 +378,10 @@
* ErrorSummary: Har nå 8px border-radius ([#2256](https://github.com/navikt/aksel/pull/2256))
### @navikt/ds-tokens
- Tokens: `data-theme="light"` vil nå tilbakestille theming ([#2238](https://github.com/navikt/aksel/pull/2238))
### @navikt/ds-react
- MonthPicker: Fikset kalkulering av fromDate/toDate ([#2269](https://github.com/navikt/aksel/pull/2269))
@@ -376,10 +390,6 @@
- Search: Kjører nå bare preventDefault ved Escape når `input` inneholder tekst ([#2245](https://github.com/navikt/aksel/pull/2245))
### @navikt/ds-tokens
- Tokens: `data-theme="light"` vil nå tilbakestille theming ([#2238](https://github.com/navikt/aksel/pull/2238))
## 5.3
### @navikt/ds-css
@@ -479,6 +489,16 @@
* Table: Alle størrelser har justert padding. Small-size table bruker nå også standard typografi-størrelse (18px). ([#2178](https://github.com/navikt/aksel/pull/2178))
### @navikt/ds-tokens
- ConfirmationPanel: Fikset opplesing av feilmelding ([#2199](https://github.com/navikt/aksel/pull/2199))
- Tokens: `--a-icon-alt-3` er nå i synk med figma ([#2199](https://github.com/navikt/aksel/pull/2199))
* Gray: Gråfarger er nå mindre varme ([#2092](https://github.com/navikt/aksel/pull/2092))
* Action: Selected-varianter av action er nå 'blue' ('deepblue' før) ([#2092](https://github.com/navikt/aksel/pull/2092))
### @navikt/ds-react
- ConfirmationPanel: Fikset opplesing av feilmelding ([#2199](https://github.com/navikt/aksel/pull/2199))
@@ -495,16 +515,6 @@
* Table: Har lagt til ny size: 'large'. ([#2178](https://github.com/navikt/aksel/pull/2178))
### @navikt/ds-tokens
- ConfirmationPanel: Fikset opplesing av feilmelding ([#2199](https://github.com/navikt/aksel/pull/2199))
- Tokens: `--a-icon-alt-3` er nå i synk med figma ([#2199](https://github.com/navikt/aksel/pull/2199))
* Gray: Gråfarger er nå mindre varme ([#2092](https://github.com/navikt/aksel/pull/2092))
* Action: Selected-varianter av action er nå 'blue' ('deepblue' før) ([#2092](https://github.com/navikt/aksel/pull/2092))
## 4.12
### @navikt/ds-css
@@ -659,6 +669,10 @@
* Shadow-tokens er oppdatert: Datepicker har nå ikke border, Modal bruker shadow-xlarge, LinkCard bruker shadow-xsmall ([PR](https://github.com/navikt/aksel/pull/2041))
### @navikt/ds-tokens
- Shadow-tokens er oppdatert til mer tydeligere varianter ([PR](https://github.com/navikt/aksel/pull/2041))
### @navikt/ds-tailwind
- Shadow-tokens er oppdatert ([PR](https://github.com/navikt/aksel/pull/2041))
@@ -671,10 +685,6 @@
* Fikset klassenavn brukt for popover i Datepicker og Monthpicker ([PR](https://github.com/navikt/aksel/pull/2041))
### @navikt/ds-tokens
- Shadow-tokens er oppdatert til mer tydeligere varianter ([PR](https://github.com/navikt/aksel/pull/2041))
## 4.3
### @navikt/ds-css
@@ -713,6 +723,12 @@
- Alle description-felter på fieldsets har nå `text-subtle` som farge. ([PR](https://github.com/navikt/aksel/pull/2036))
### @navikt/ds-tokens
- :tada: Fargetokens for datavisualisering. ([PR](https://github.com/navikt/aksel/pull/2032))
- Oppdatert text-subtle og icon-subtle tokens til 700-skala (tidligere 600). ([PR](https://github.com/navikt/aksel/pull/2036))
### @navikt/ds-tailwind
- :tada: Fargetokens for datavisualisering. ([PR](https://github.com/navikt/aksel/pull/2032))
@@ -741,24 +757,12 @@
- Accordion: La til `indent`-prop ([PR](https://github.com/navikt/aksel/pull/2027))
### @navikt/ds-tokens
- :tada: Fargetokens for datavisualisering. ([PR](https://github.com/navikt/aksel/pull/2032))
- Oppdatert text-subtle og icon-subtle tokens til 700-skala (tidligere 600). ([PR](https://github.com/navikt/aksel/pull/2036))
### @navikt/aksel-icons
- Nye ikoner `ChevronRightLast` og `ChevronLeftLast` ([PR](https://github.com/navikt/aksel/pull/2054))
## 4.0
### @navikt/aksel
- Codemod for migrering av Datepicker/Monthpicker ut av Beta. `npx @navikt/aksel codemod v4-date` ([PR](https://github.com/navikt/aksel/pull/2026))
- Codemods for migrering fra `@navikt/ds-react-internal` til `@navikt/ds-react` [Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h3b8538e1981d) ([PR](https://github.com/navikt/aksel/pull/2026))
### @navikt/ds-css
- All styling fra `@navikt/ds-css-internal` er flyttet til `@navikt/ds-css`. ([PR](https://github.com/navikt/aksel/pull/2026))
@@ -775,6 +779,12 @@
- Komponenter i `@navikt/ds-react-internal` er flyttet over til `@navikt/ds-react`. [Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h3b8538e1981d) ([PR](https://github.com/navikt/aksel/pull/2026))
### @navikt/aksel
- Codemod for migrering av Datepicker/Monthpicker ut av Beta. `npx @navikt/aksel codemod v4-date` ([PR](https://github.com/navikt/aksel/pull/2026))
- Codemods for migrering fra `@navikt/ds-react-internal` til `@navikt/ds-react` [Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h3b8538e1981d) ([PR](https://github.com/navikt/aksel/pull/2026))
## 3.4
### @navikt/aksel-stylelint
@@ -857,10 +867,6 @@
## 2.9
### @navikt/aksel
- :truck: Flyttet Codemods fra `@navikt/ds-codemods` -> `@navikt/aksel`. `@navikt/ds-codemods` regnes nå som deprecated ([PR](https://github.com/navikt/aksel/pull/1952))
### @navikt/ds-css
- CSS nå tilgjengelig som separate filer: Kan lastest fra CDN, minified-versjoner tilgjengelig ([PR](https://github.com/navikt/aksel/pull/1941))
@@ -869,6 +875,10 @@
- ExpansionCard: Støtter nå `aria-labelledby` i tillegg til `aria-label` ([PR](https://github.com/navikt/aksel/pull/1944))
### @navikt/aksel
- :truck: Flyttet Codemods fra `@navikt/ds-codemods` -> `@navikt/aksel`. `@navikt/ds-codemods` regnes nå som deprecated ([PR](https://github.com/navikt/aksel/pull/1952))
### @navikt/aksel-icons
- Oppdatert Statusikoner til å være tydeligere og mer konsistente. ([PR](https://github.com/navikt/aksel/pull/1959))
@@ -953,6 +963,10 @@
## 2.5
### @navikt/ds-tokens
- Breakpoint-tokens lagt til ([PR](https://github.com/navikt/aksel/pull/1832))
### @navikt/ds-tailwind
- Breakpoint-tokens er lagt til. Overskriver native tailwind-breakpoints ([PR](https://github.com/navikt/aksel/pull/1832))
@@ -961,10 +975,6 @@
- List: Refaktorert nestede lister
### @navikt/ds-tokens
- Breakpoint-tokens lagt til ([PR](https://github.com/navikt/aksel/pull/1832))
## 2.4
### @navikt/ds-css
@@ -999,24 +1009,28 @@
- Button: `Neutral`-variant.
### @navikt/ds-react
- ToggleGroup: `neutral`-variant ([PR](https://github.com/navikt/aksel/pull/1789))
- Button: `neutral`-variant ([PR](https://github.com/navikt/aksel/pull/1789))
### @navikt/ds-tokens
- Justeringer av semantiske fargetokens, statusfarger nå mer tydelig ([PR](https://github.com/navikt/aksel/pull/1787))
- Oppdatert neutral-tokens ([PR](https://github.com/navikt/aksel/pull/1789))
### @navikt/ds-react
- ToggleGroup: `neutral`-variant ([PR](https://github.com/navikt/aksel/pull/1789))
- Button: `neutral`-variant ([PR](https://github.com/navikt/aksel/pull/1789))
## 2.1
### @navikt/ds-css
- TextField: `small`-variant har nå 8px horisontal padding (før 4px)
### @navikt/ds-tokens
- Fikset feil danger-hover token ([PR](https://github.com/navikt/aksel/pull/1665))
### @navikt/ds-react
- Datepicker: Fikset rekkefølge på `onValidate` og `onRangeChange` i useRangepicker-hook
@@ -1033,10 +1047,6 @@
- Datepicker/Monthpicker: år med 2 siffer i input fungerer nå
### @navikt/ds-tokens
- Fikset feil danger-hover token ([PR](https://github.com/navikt/aksel/pull/1665))
## 2.0
### @navikt/ds-css
@@ -1051,6 +1061,10 @@
* Tokens: Alle komponenter bruker nå semantiske tokens for som standard, med innebygd støtte for komponent-spesifikke tokens.
### @navikt/ds-tokens
- Alle token er oppdatert til nytt format. ([Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h76f47744d112))
### @navikt/ds-tailwind
- Alle token er oppdatert til nytt format. ([Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h76f47744d112))
@@ -1073,10 +1087,6 @@
* Fonter blir bruk i all typografi blir nå lastet fra CDN
### @navikt/ds-tokens
- Alle token er oppdatert til nytt format. ([Guide](https://aksel.nav.no/grunnleggende/kode/migrering#h76f47744d112))
## 1.5
### @navikt/ds-css
+5 -5
View File
@@ -16,10 +16,10 @@
"playroom"
],
"dependencies": {
"@navikt/aksel-icons": "^5.17.4",
"@navikt/ds-css": "^5.17.4",
"@navikt/ds-react": "^5.17.4",
"@navikt/ds-tailwind": "^5.17.4",
"@navikt/ds-tokens": "^5.17.4"
"@navikt/aksel-icons": "^5.18.1",
"@navikt/ds-css": "^5.18.1",
"@navikt/ds-react": "^5.18.1",
"@navikt/ds-tailwind": "^5.18.1",
"@navikt/ds-tokens": "^5.18.1"
}
}
@@ -17,11 +17,14 @@ const args = {
_key: getKey(),
alt: "Alt-tekst for video",
caption: "caption-tekst",
transkripsjon: "Transkripsjonstekst",
transkripsjon:
"Transkripsjonstekst avsnitt 1 linje 1\nLinje 2\n\nTranskripsjonstekst avsnitt 2",
webm: {
url: `https://cdn.sanity.io/files/${SANITY_PROJECT_ID}/production/274a2ceb69b056e1a7048ad1a5a2f8deff53a2f4.webm`,
extension: "WEBM",
},
track:
"data:@file/octet-stream;base64,V0VCVlRUCgowMDowMS4wMDAgLS0+IDAwOjAyLjAwMApIZWkhCgowMDowMy4wMDAgLS0+IDAwOjA0LjUwMApEZXR0ZSBlciBldCBla3NlbXBlbAoKMDA6MDQuNTAwIC0tPiAwMDowNS43MDAKcMOlIHVuZGVydGVrc3Rlci4=",
},
};
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useId, useState } from "react";
import { BodyLong, ReadMore } from "@navikt/ds-react";
import ErrorBoundary from "@/error-boundary";
import { VideoT } from "@/types";
@@ -9,6 +9,7 @@ type VideoProps = {
const Video = ({ node }: VideoProps) => {
const [open, setOpen] = useState(false);
const transcriptId = useId();
if (!node || (!node.webm && !node.fallback) || !node.alt) {
return null;
@@ -24,11 +25,9 @@ const Video = ({ node }: VideoProps) => {
playsInline
controls
loop
aria-describedby={
node.transkripsjon ? node.alt + "transkript" : undefined
}
aria-label="Trykk space for å starte/pause video"
aria-describedby={node.transkripsjon ? transcriptId : undefined}
poster="/images/og/video-poster.png"
crossOrigin="anonymous" // Needed for the <track>
>
<source src={node.webm.url} type={`video/${node.webm.extension}`} />
{node.fallback && (
@@ -37,19 +36,27 @@ const Video = ({ node }: VideoProps) => {
type={`video/${node.fallback.extension}`}
/>
)}
{node.track && <track kind="captions" srcLang="no" src={node.track} />}
</video>
{node?.caption && (
<BodyLong as="figcaption" className="px-7">
<BodyLong as="figcaption" className="px-4">
{node.caption}
</BodyLong>
)}
{node?.transkripsjon && (
<ReadMore
header="transkripsjon"
className="px-4"
header="Transkripsjon"
open={open}
onClick={() => setOpen((x) => !x)}
>
<span id={node.alt + "transkript"}>{node.transkripsjon}</span>
<div id={transcriptId} className="whitespace-break-spaces">
{node.transkripsjon.split("\n\n").map((paragraph, i, array) => (
<BodyLong key={i} spacing={i < array.length - 1}>
{paragraph}
</BodyLong>
))}
</div>
</ReadMore>
)}
</figure>
@@ -359,6 +359,7 @@ export type VideoT = ArrayObjectT<{
alt: string;
webm: { extension: string; url: string } | null;
fallback?: { extension: string; url: string } | null;
track?: string;
transkripsjon?: string;
caption?: string;
}>;
@@ -44,5 +44,5 @@ export const Demo = {
export const args = {
index: 7,
desc: "Før du belger å bruke range, vurder om to enkelte datepickere for start/slutt-dato ville vært bedre. Range fungerer bedre for korte perioder innenfor en måned.",
desc: "Før du velger å bruke range, vurder om to separate datepickere i single mode er bedre. Range fungerer best for korte perioder innenfor en måned.",
};
@@ -32,5 +32,5 @@ export const Demo = {
export const args = {
index: 10,
desc: "Prop allowTwoDigitYear legger til støtte for 'yy'-format. Tilgjengelig year-range vil være fra 1943-2042 (2023).",
desc: "Prop 'allowTwoDigitYear' legger til støtte for 'yy'-format. Tilgjengelig year-range vil være 80 år bakover og 19 år framover. I 2024 tilsvarer det 1944-2043.",
};
@@ -101,7 +101,7 @@ const Page = ({ blogg, morePosts, publishDate }: PageProps["props"]) => {
<Heading
level="1"
size="xlarge"
className="text-wrap-balance mt-1 break-words text-5xl leading-[1.2] text-deepblue-800 [hyphens:_auto]"
className="text-wrap-balance mt-1 hyphens-auto break-words text-5xl leading-[1.2] text-deepblue-800 md:hyphens-none"
>
{blogg.heading}
</Heading>
@@ -79,7 +79,8 @@ const defaultBlock = `
"fallback": {
"url": fallback.asset->url,
"extension": fallback.asset->extension
}
},
"track": track.asset->url
},
_type == "alert" =>{
...,
@@ -10,6 +10,7 @@ import {
PencilBoardIcon,
RectangleSectionsIcon,
TokenIcon,
EyeIcon,
} from "@navikt/aksel-icons";
import {
SANITY_API_VERSION,
@@ -298,10 +299,11 @@ export const structure: StructureResolver = async (
.icon(FileTextIcon)
.id(`publication_flow`),
S.listItem()
.title("Artikkel Visninger")
.title("Artikkelvisninger")
.icon(EyeIcon)
.child(
S.documentList()
.title("Artikkel Visninger")
.title("Artikkelvisninger")
.filter(`_type == 'article_views'`)
.apiVersion(SANITY_API_VERSION)
.menuItems([
@@ -2,7 +2,7 @@ import { defineField, defineType } from "sanity";
import { LineGraphIcon } from "@navikt/aksel-icons";
export const ArticleViews = defineType({
title: "Artikkel Visninger",
title: "Artikkelvisninger",
name: "article_views",
type: "document",
readOnly: ({ currentUser }) =>
@@ -20,9 +20,9 @@ export const ArticleViews = defineType({
},
orderings: [
{
title: "Views total",
name: "views",
by: [{ field: "views", direction: "desc" }],
title: "Views day",
name: "views_day",
by: [{ field: "views_day", direction: "desc" }],
},
{
title: "Views week",
@@ -43,28 +43,29 @@ export const ArticleViews = defineType({
fields: [
defineField({
type: "number",
name: "views",
description: "total lifetime views",
name: "views_day",
title: "Visninger i de siste 24 timer",
}),
defineField({
type: "number",
name: "views_week",
description: "views in the last week",
title: "Visninger siste 7 dager",
}),
defineField({
type: "number",
name: "views_month",
description: "views in the last month",
title: "Visninger siste 30 dager",
}),
defineField({
type: "number",
name: "views_year",
description: "views in the last year",
title: "Visninger siste 365 dager",
}),
defineField({
title: "articleRef",
name: "article_ref",
type: "reference",
weak: true,
to: { type: "aksel_artikkel" },
}),
defineField({
@@ -1,5 +1,27 @@
import { defineField, defineType } from "sanity";
import { createClient, groq } from "next-sanity";
import { FileValue, defineField, defineType } from "sanity";
import { VideoplayerIcon } from "@navikt/aksel-icons";
import { clientConfig } from "@/sanity/config";
const sanityClient = createClient({
...clientConfig,
withCredentials: true,
});
const query = groq`*[_id == $id][0]{size}`;
const validateFileSize = (maxSizeInMb: number) => (file: FileValue) => {
if (!file) {
return true;
}
return sanityClient
.fetch(query, { id: file.asset._ref })
.then((res) =>
res.size > 1024 * 1024 * maxSizeInMb
? `Maks filstørrelse er ${maxSizeInMb} MB`
: true,
);
};
export const Video = defineType({
name: "video",
@@ -9,33 +31,44 @@ export const Video = defineType({
fields: [
defineField({
name: "webm",
title: "Video i WebM format",
description:
"Vi anbefaler å bruke Webm formatet. Formatet minsker fil-størrelse + perseverer kvalitet bedre",
title: "Video i WebM-format",
description: `Vi bruker WebM fordi det har bedre komprimering enn f.eks. MP4.
For å konvertere kan du f.eks. bruke Handbrake (https://handbrake.fr/).
OBS: Ikke legg inn store/lange videoer! Da er det bedre å lenke til en ekstern kilde.`,
type: "file",
options: {
accept: "video/webm",
},
validation: (Rule) => Rule.required(),
validation: (Rule) => Rule.required().custom(validateFileSize(30)),
}),
defineField({
name: "fallback",
title: "Video i Mp4 format (fallback)",
title: "Video i MP4-format (fallback)",
description: "For eldre nettlesere som ikke støtter WebM",
type: "file",
options: {
accept: "video/mp4",
},
validation: (Rule) => Rule.custom(validateFileSize(60)),
}),
defineField({
name: "track",
title: "Undertekster (VTT)",
type: "file",
options: {
accept: ".vtt",
},
}),
defineField({
name: "alt",
title: "Alt tekst for skjermlesere",
title: "Alt-tekst for skjermlesere",
type: "string",
validation: (Rule) => Rule.required(),
}),
defineField({
name: "caption",
title: "Videotekst",
description: "Kort beskrivelse som vises rett under videon",
description: "Kort beskrivelse som vises rett under videoen",
type: "string",
}),
defineField({
+2 -1
View File
@@ -11,7 +11,8 @@
"storybook:aksel": "yarn concurrently \"yarn watch:tw\" \"yarn storybook dev -c aksel.nav.no/website/.storybook -p 6007\"",
"dev": "yarn workspace aksel.nav.no dev",
"docgen": "yarn workspaces foreach -p run docgen",
"changelog": "deno run --allow-read --allow-write --no-config scripts/deno/createMainChangelog.ts",
"changelog": "deno run --allow-read --allow-write --no-config scripts/changelog/createMainChangelog.ts",
"updateArticleViews": "deno run --allow-net --allow-env --allow-read --no-config scripts/article-views/update-article-views/main.ts",
"chromatic": "npx chromatic --only-changed --project-token x3xqdfgkujg --build-script-name build:storybook",
"build:storybook": "storybook build",
"test": "yarn workspaces foreach -p run test",
@@ -0,0 +1,16 @@
FROM denoland/deno:1.40.2
WORKDIR /app
RUN chown -R deno:deno /app
USER deno
COPY scripts/article-views/deps.ts scripts/article-views/deps.ts
RUN deno cache scripts/article-views/deps.ts
# this COPY should copy over .env created in github action
# only copies over what exists in the docker context
# check out the accompanying .dockerignore
COPY . .
RUN deno cache scripts/article-views/update-article-views/main.ts
CMD ["run", "--allow-net", "--allow-env", "--allow-read", "scripts/article-views/update-article-views/main.ts"]
@@ -0,0 +1,3 @@
*
!aksel.nav.no/website/sanity/config.ts
!scripts/article-views/*
@@ -0,0 +1,45 @@
import * as path from "https://deno.land/std@0.102.0/path/mod.ts";
import { load } from "https://deno.land/std@0.212.0/dotenv/mod.ts";
import { createClient } from "npm:next-sanity";
import { clientConfig } from "../../../aksel.nav.no/website/sanity/config.ts";
import { queryArticleViews } from "../queries.ts";
/*
this part is a bit silly: script "plumbing" essentially. ModuleDir is the root of this
current file, it's used so relative paths from this file into the rest of the repo will
work as expected regardless of where it is called from (disregarding CWD of caller)
it's a WEB-first API, so we get files in URL format, these must be converted to a path
Currently the script is located `scripts/deno/`, so we go up ../../ to get to the project root
*/
const env_file = `${path.dirname(path.fromFileUrl(Deno.mainModule))}/../.env`;
await load({
envPath: `${env_file}`,
export: true,
});
const token = Deno.env.get("SANITY_WRITE_KEY");
if (!token) {
throw new Error("Missing SANITY_WRITE_KEY");
}
const noCdnClient = createClient({
...clientConfig,
maxRetries: 5,
token,
});
const transactionClient = noCdnClient.transaction();
const document_ids = [];
const articleViewDocs = await noCdnClient.fetch(queryArticleViews);
for (const articleViewDoc of articleViewDocs) {
document_ids.push(articleViewDoc._id);
}
document_ids.forEach(async (doc) => {
await transactionClient.delete(doc);
});
const res_commit = await transactionClient.commit({ dryRun: false });
console.log({ res_commit });
+3
View File
@@ -0,0 +1,3 @@
export * as path from "https://deno.land/std@0.102.0/path/mod.ts";
export { load } from "https://deno.land/std@0.212.0/dotenv/mod.ts";
export { createClient } from "npm:@sanity/client";
@@ -0,0 +1,23 @@
apiVersion: nais.io/v1
kind: Naisjob
metadata:
name: update-views-job
namespace: designsystem
labels:
team: designsystem
spec:
image: {{ image }}
schedule: "0 * * * *"
command:
- deno
- run
- --allow-net
- --allow-env
- --allow-read
- scripts/article-views/update-article-views/main.ts
restartPolicy: Never
accessPolicy:
outbound:
external:
- host: hnbe3yhs.api.sanity.io
- host: reops-proxy.intern.nav.no
+12
View File
@@ -0,0 +1,12 @@
export const queryArticleURLs = `
*[_type == "aksel_artikkel" && !(_id in path("drafts.**"))] {
_id,
"slug": slug.current
}
`;
export const queryArticleViews = `
*[_type == "article_views"] {
_id,
}
`;
@@ -0,0 +1,137 @@
import { clientConfig } from "../../../aksel.nav.no/website/sanity/config.ts";
import { createClient, load, path } from "../deps.ts";
import { queryArticleURLs, queryArticleViews } from "../queries.ts";
import { amplitudeFetchJSON, hashString, sum_last_n } from "./utils.ts";
/*
this part is a bit silly: script "plumbing" essentially. ModuleDir is the root of this
current file, it's used so relative paths from this file into the rest of the repo will
work as expected regardless of where it is called from (disregarding CWD of caller)
it's a WEB-first API, so we get files in URL format, these must be converted to a path
Currently the script is located `scripts/deno/`, so we go up ../../ to get to the project root
*/
const env_file = `${path.dirname(path.fromFileUrl(Deno.mainModule))}/../.env`;
await load({
envPath: `${env_file}`,
export: true,
});
type ViewData = {
views_day: number;
views_week: number;
views_month: number;
views_year: number;
};
const view_datas = new Map<string, Partial<ViewData>>();
const views_config = {
views_day: {
chart_id: "e-f5vcqiqk",
sum_last_n: 24, // 24 hours in a day
},
views_week: {
chart_id: "e-69mzf301",
sum_last_n: 7, // 7 days in a week
},
views_month: {
chart_id: "e-wwh3n9l1",
sum_last_n: 30, // 30 days in a month
},
views_year: {
chart_id: "e-rzw8jk6j",
sum_last_n: 4, // 4 quarters in a year
},
};
for (const [view, config] of Object.entries(views_config)) {
const chartResult = await amplitudeFetchJSON(config.chart_id);
for (const [idx, view_entry] of chartResult.data.series.entries()) {
const url = chartResult.data.seriesLabels[idx][1];
const viewsN = sum_last_n(view_entry, config.sum_last_n);
const existing_data = view_datas.get(url) ?? {};
view_datas.set(url, {
...existing_data,
[view]: viewsN,
});
}
}
// strip and aggregate all fragments (.../some/url#1234...) from the URL,
// we count all the fragment views as views towards the URL without the fragment
const merged_fragments_view_datas = new Map<string, ViewData>();
for (const view_data of view_datas) {
let url = view_data[0];
if (view_data[0].includes("#")) {
url = view_data[0].split("#")[0];
}
const existing_data = merged_fragments_view_datas.get(url);
merged_fragments_view_datas.set(url, {
views_day: (existing_data?.views_day ?? 0) + (view_data[1]?.views_day ?? 0),
views_week:
(existing_data?.views_week ?? 0) + (view_data[1].views_week ?? 0),
views_month:
(existing_data?.views_month ?? 0) + (view_data[1].views_month ?? 0),
views_year:
(existing_data?.views_year ?? 0) + (view_data[1].views_year ?? 0),
});
}
const token = Deno.env.get("SANITY_WRITE_KEY");
if (!token) {
throw new Error("Missing SANITY_WRITE_KEY");
}
const noCdnClient = createClient({
...clientConfig,
maxRetries: 5,
token,
});
const transactionClient = noCdnClient.transaction();
const document_ids = [];
// delete all the article views (old data)
const articleViewDocs = await noCdnClient.fetch(queryArticleViews);
for (const articleViewDoc of articleViewDocs) {
document_ids.push(articleViewDoc._id);
}
document_ids.forEach(async (doc) => {
await transactionClient.delete(doc);
});
const documents = [];
// re-build the article views
const articles = await noCdnClient.fetch(queryArticleURLs);
for (const article of articles) {
const url = `https://aksel.nav.no/${article.slug}`;
const data = merged_fragments_view_datas.get(url);
if (data) {
documents.push({
_id: `${hashString(url)}`,
_type: "article_views",
article_ref: {
_ref: article._id,
_type: "reference",
_weak: true,
},
url,
views_day: data?.views_day,
views_week: data?.views_week,
views_month: data?.views_month,
views_year: data?.views_year,
});
}
}
documents.forEach(async (doc) => {
await transactionClient.createOrReplace(doc);
});
const res_commit = await transactionClient.commit({ dryRun: false });
console.log({ res_commit });
@@ -0,0 +1,25 @@
export const hashString = (str: string) => {
let output = 1;
for (let i = 0; i < str.length; i++) {
output *= str[i].charCodeAt(0);
output %= Number.MAX_SAFE_INTEGER;
}
return output;
};
export const amplitudeFetchJSON = async (chart_id: string) => {
const url = `https://reops-proxy.intern.nav.no/amplitude/100002016/api/3/chart/${chart_id}/query`;
console.log({ url });
return await fetch(url)
.then((res) => res.json())
.catch((e) => {
throw new Error(e);
});
};
export const sum_last_n = (view_entry: { value: number }[], last_n: number) => {
return view_entry
.slice(-last_n) // the query holds more than 24 hours of data, but we only want the last 24
.reduce((a: number, b: { value: number }) => a + b.value, 0);
};
File renamed without changes.
File renamed without changes.
+11 -25
View File
@@ -7,20 +7,12 @@ const options: docgen.ParserOptions = {
shouldRemoveUndefinedFromOptional: true,
propFilter: (prop) => {
if (prop.name === "className") return true;
if (prop.declarations !== undefined && prop.declarations.length > 0) {
const hasPropAdditionalDescription = prop.declarations.some(
(declaration) => {
return (
!declaration.fileName.includes("node_modules") ||
declaration.name === "RefAttributes"
);
},
);
return hasPropAdditionalDescription;
if (prop.name === "className" || prop.parent?.name === "RefAttributes") {
return true;
}
if (prop.parent?.fileName.includes("/node_modules/@types/react/")) {
return false;
}
return true;
},
};
@@ -36,7 +28,7 @@ const genDocs = () => {
!x.toLowerCase().includes("pictogram"),
);
const res: any[] = [];
const res: docgen.ComponentDoc[][] = [];
const fails: string[] = [];
files.forEach((file) => {
@@ -50,17 +42,11 @@ const genDocs = () => {
console.log({ Documented: res.length, fails });
const cleaned = res.flat().reduce(
(old, cur) => [
...old,
{
filePath: cur.filePath,
displayName: cur.displayName,
props: cur.props,
},
],
[],
);
const cleaned = res.flat().map((file) => ({
filePath: file.filePath,
displayName: file.displayName,
props: file.props,
}));
writeFileSync(`_docs.json`, JSON.stringify(cleaned, null, 2));
};
+17 -17
View File
@@ -3449,7 +3449,7 @@ __metadata:
languageName: node
linkType: hard
"@navikt/aksel-icons@^5.17.2, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
"@navikt/aksel-icons@^5.18.0, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
version: 0.0.0-use.local
resolution: "@navikt/aksel-icons@workspace:@navikt/aksel-icons"
dependencies:
@@ -3476,8 +3476,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@navikt/aksel-stylelint@workspace:@navikt/aksel-stylelint"
dependencies:
"@navikt/ds-css": ^5.17.2
"@navikt/ds-tokens": ^5.17.2
"@navikt/ds-css": ^5.18.0
"@navikt/ds-tokens": ^5.18.0
"@types/jest": ^29.0.0
concurrently: 7.2.1
copyfiles: 2.4.1
@@ -3495,7 +3495,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@navikt/aksel@workspace:@navikt/aksel"
dependencies:
"@navikt/ds-css": 5.17.2
"@navikt/ds-css": 5.18.0
"@types/inquirer": ^9.0.3
"@types/jest": ^29.0.0
axios: 1.6.0
@@ -3519,11 +3519,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css@*, @navikt/ds-css@5.17.2, @navikt/ds-css@^5.17.2, @navikt/ds-css@^5.9.2, @navikt/ds-css@workspace:@navikt/core/css":
"@navikt/ds-css@*, @navikt/ds-css@5.18.0, @navikt/ds-css@^5.18.0, @navikt/ds-css@^5.9.2, @navikt/ds-css@workspace:@navikt/core/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css@workspace:@navikt/core/css"
dependencies:
"@navikt/ds-tokens": ^5.17.2
"@navikt/ds-tokens": ^5.18.0
cssnano: 6.0.0
fast-glob: 3.2.11
lodash: 4.17.21
@@ -3536,13 +3536,13 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react@*, @navikt/ds-react@^5.17.2, @navikt/ds-react@^5.9.2, @navikt/ds-react@workspace:@navikt/core/react":
"@navikt/ds-react@*, @navikt/ds-react@^5.18.0, @navikt/ds-react@^5.9.2, @navikt/ds-react@workspace:@navikt/core/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react@workspace:@navikt/core/react"
dependencies:
"@floating-ui/react": 0.25.4
"@navikt/aksel-icons": ^5.17.2
"@navikt/ds-tokens": ^5.17.2
"@navikt/aksel-icons": ^5.18.0
"@navikt/ds-tokens": ^5.18.0
"@radix-ui/react-tabs": 1.0.0
"@radix-ui/react-toggle-group": 1.0.0
"@testing-library/dom": 8.13.0
@@ -3576,11 +3576,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tailwind@^5.17.2, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
"@navikt/ds-tailwind@^5.18.0, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
version: 0.0.0-use.local
resolution: "@navikt/ds-tailwind@workspace:@navikt/core/tailwind"
dependencies:
"@navikt/ds-tokens": ^5.17.2
"@navikt/ds-tokens": ^5.18.0
"@types/jest": ^29.0.0
color: 4.2.3
jest: ^29.0.0
@@ -3592,7 +3592,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tokens@^5.17.2, @navikt/ds-tokens@workspace:@navikt/core/tokens":
"@navikt/ds-tokens@^5.18.0, @navikt/ds-tokens@workspace:@navikt/core/tokens":
version: 0.0.0-use.local
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
dependencies:
@@ -8842,11 +8842,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "aksel.nav.no@workspace:aksel.nav.no"
dependencies:
"@navikt/aksel-icons": ^5.17.2
"@navikt/ds-css": ^5.17.2
"@navikt/ds-react": ^5.17.2
"@navikt/ds-tailwind": ^5.17.2
"@navikt/ds-tokens": ^5.17.2
"@navikt/aksel-icons": ^5.18.0
"@navikt/ds-css": ^5.18.0
"@navikt/ds-react": ^5.18.0
"@navikt/ds-tailwind": ^5.18.0
"@navikt/ds-tokens": ^5.18.0
languageName: unknown
linkType: soft