mirror of
https://github.com/navikt/aksel.git
synced 2026-10-13 09:12:03 +00:00
Compare commits
112
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44671abb5f | ||
|
|
2eb358ad88 | ||
|
|
6bdc02761b | ||
|
|
f52ef19be2 | ||
|
|
989a97a8bc | ||
|
|
8de6ba22c3 | ||
|
|
f664370826 | ||
|
|
55b5856183 | ||
|
|
5a72a62190 | ||
|
|
d89eaccd44 | ||
|
|
7cffc0bf12 | ||
|
|
8d4966c83f | ||
|
|
edcc4e5071 | ||
|
|
a5821578a0 | ||
|
|
7ff8ce7e3b | ||
|
|
fa0c07e04a | ||
|
|
e97b31ea94 | ||
|
|
d1549cb5ff | ||
|
|
01bcbbf1ff | ||
|
|
41fd9e7b25 | ||
|
|
e468f9d93e | ||
|
|
ccd9e73446 | ||
|
|
eb2c7ab777 | ||
|
|
0ccee41b7c | ||
|
|
865a19c681 | ||
|
|
eabad5af35 | ||
|
|
7ab07f3f46 | ||
|
|
5ead5f9cde | ||
|
|
1fb56a32d0 | ||
|
|
1609604073 | ||
|
|
f862aa9c2e | ||
|
|
c88632d92c | ||
|
|
70bf09a4d6 | ||
|
|
0cce29182b | ||
|
|
a7b619dd18 | ||
|
|
945ea68414 | ||
|
|
9e5b5a461f | ||
|
|
66dc7e41ed | ||
|
|
8fce648c79 | ||
|
|
f85a2bd834 | ||
|
|
6812a18a34 | ||
|
|
34f421835c | ||
|
|
9c495cf503 | ||
|
|
721a315f67 | ||
|
|
d508423406 | ||
|
|
c9c8bf72e8 | ||
|
|
d9bb32ace0 | ||
|
|
6082485287 | ||
|
|
2b2b3aa819 | ||
|
|
5628f1c4dd | ||
|
|
b5666ed040 | ||
|
|
72aa6325ed | ||
|
|
e1f2a46ae0 | ||
|
|
489c6678d2 | ||
|
|
be4a951962 | ||
|
|
1276b4d7ef | ||
|
|
8880b0dfb5 | ||
|
|
bfe60a9a62 | ||
|
|
9c70200962 | ||
|
|
33aef230b0 | ||
|
|
88243f76de | ||
|
|
c00112e3e6 | ||
|
|
3c66b00c24 | ||
|
|
db8303af42 | ||
|
|
5fbd2e1814 | ||
|
|
c1360da7d7 | ||
|
|
de2a3990dc | ||
|
|
46433118b2 | ||
|
|
de861e469c | ||
|
|
85697be305 | ||
|
|
ae64920a34 | ||
|
|
36fb35533d | ||
|
|
3709e432bb | ||
|
|
c6077a03fa | ||
|
|
c6d51a0190 | ||
|
|
777d94b3d4 | ||
|
|
7ace69f215 | ||
|
|
6724bb8f71 | ||
|
|
59253e992f | ||
|
|
91b6e0be18 | ||
|
|
02f5c29723 | ||
|
|
2221b2e01d | ||
|
|
b31b1b3533 | ||
|
|
ff8bcb870e | ||
|
|
0a7e6311de | ||
|
|
961d97ef0d | ||
|
|
f2477e772d | ||
|
|
bad960be56 | ||
|
|
c53e3a050b | ||
|
|
d9e40b71b1 | ||
|
|
c1828f992f | ||
|
|
522bb95ddb | ||
|
|
7ab690d210 | ||
|
|
859d5d6407 | ||
|
|
de741ce8a8 | ||
|
|
918d21c3ba | ||
|
|
121a678fa0 | ||
|
|
576790a2ff | ||
|
|
6609631f46 | ||
|
|
7c37e3af56 | ||
|
|
9703f082f1 | ||
|
|
18005f89a2 | ||
|
|
8a4321ebd3 | ||
|
|
28938dd4a6 | ||
|
|
bb3a431e2a | ||
|
|
00e787a400 | ||
|
|
04215daf7e | ||
|
|
2c722e3a7d | ||
|
|
8d511c90f1 | ||
|
|
8be270c8c5 | ||
|
|
426f4d54a1 | ||
|
|
8ff68266c8 |
No files matched your search
@@ -3,7 +3,7 @@ description: Send et ønske om en eller flere nye komponenter
|
||||
title: "[Ny komponent]: "
|
||||
labels: ["nytt ✨", "forespørsel 🥰", "komponenter 🧩"]
|
||||
assignees:
|
||||
- olejorgenbakken
|
||||
- KenAJoh
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Send et ønske om et eller flere nye ikoner
|
||||
title: "[Nytt ikon]: "
|
||||
labels: ["nytt ✨", "ikoner 🖼", "forespørsel 🥰"]
|
||||
assignees:
|
||||
- olejorgenbakken
|
||||
- KenAJoh
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Send inn innspill til komponent
|
||||
title: "[Innspill til komponent]: "
|
||||
labels: ["forespørsel 🥰", "komponenter 🧩", "nytt ✨", "beta 🧪"]
|
||||
assignees:
|
||||
- olejorgenbakken
|
||||
- KenAJoh
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -3,7 +3,7 @@ description: Send inn innspill til ikon
|
||||
title: "[Tilbakemelding på ikon]: "
|
||||
labels: ["forespørsel 🥰", "ikoner 🖼️"]
|
||||
assignees:
|
||||
- olejorgenbakken
|
||||
- KenAJoh
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -54,6 +54,10 @@ jobs:
|
||||
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
|
||||
echo "USE_CDN_ASSETS=true" >> aksel.nav.no/website/.env
|
||||
|
||||
- name: Hide page from search engines
|
||||
run: |
|
||||
echo "User-agent: *\nDisallow: /" > aksel.nav.no/website/public/robots.txt
|
||||
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
||||
@@ -23,6 +23,8 @@ module.exports = {
|
||||
addons: [
|
||||
"@storybook/addon-a11y",
|
||||
"@whitespace/storybook-addon-html",
|
||||
"storybook-addon-next-router",
|
||||
|
||||
{
|
||||
name: "@storybook/addon-storysource",
|
||||
options: {
|
||||
@@ -74,8 +76,31 @@ module.exports = {
|
||||
"../aksel.nav.no/website/components"
|
||||
),
|
||||
},
|
||||
{
|
||||
find: "@utils",
|
||||
replacement: path.resolve(
|
||||
__dirname,
|
||||
"../aksel.nav.no/website/components/website-modules/utils/index.ts"
|
||||
),
|
||||
},
|
||||
{
|
||||
find: "@lib",
|
||||
replacement: path.resolve(
|
||||
__dirname,
|
||||
"../aksel.nav.no/website/lib/index.ts"
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
/* "@/components": ["components/index.ts"],
|
||||
"@/lib": ["lib/index.ts"],
|
||||
"@/pages/*": ["pages/*"],
|
||||
"@/sanity-block": ["components/SanityBlockContent.tsx"],
|
||||
"@/utils": ["components/website-modules/utils/index.ts"],
|
||||
"@/layout": ["components/layout/index.ts"],
|
||||
"@/error-boundary": ["components/website-modules/ErrorBoundary.tsx"],
|
||||
"@/sanity-client": ["lib/sanity/sanity.server"] */
|
||||
@@ -1,3 +1,4 @@
|
||||
import { RouterContext } from "next/dist/shared/lib/router-context";
|
||||
import "@navikt/ds-css/index.css";
|
||||
import "@navikt/ds-css-internal/index.css";
|
||||
import "./layout.css";
|
||||
@@ -23,6 +24,9 @@ export const parameters = {
|
||||
},
|
||||
],
|
||||
},
|
||||
nextRouter: {
|
||||
Provider: RouterContext.Provider,
|
||||
},
|
||||
};
|
||||
|
||||
export const globalTypes = {
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# @navikt/aksel-icons
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fikset Sourcemap-bug i Aksel-icons
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel-icons",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"author": "Aksel | NAV",
|
||||
"homepage": "https://aksel.nav.no/ikoner",
|
||||
"repository": {
|
||||
@@ -53,9 +53,9 @@
|
||||
"create-icons": "svgr --silent --index-template config/index-template.js --out-dir src icons",
|
||||
"copy-util": "copyfiles util/* src",
|
||||
"copy-svg": "copyfiles -f icons/*.svg dist/svg/",
|
||||
"copy": "yarn copy-util && yarn copy-svg",
|
||||
"update-metadata": "node config/metadata.js",
|
||||
"build": "yarn copy-util && yarn copy-svg && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && node config/cleanTypes.js && yarn update-metadata",
|
||||
"build:old": "copyfiles util/* src && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && node cleanTypes.js && yarn create-package-json-pointers-to-esm",
|
||||
"build": "yarn copy && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && node config/cleanTypes.js && yarn update-metadata",
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
||||
"fetch-new:icons": "node config/figma/index.mjs",
|
||||
"zip:icons": "node config/zip.js"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/react/esm",
|
||||
"module": "esnext",
|
||||
"sourceMap": true,
|
||||
"sourceMap": false,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
# @navikt/ds-codemod
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-codemod",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Aksel codemods for NAVs designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
"build-pict": "svgr --silent --index-template index-template.js --out-dir src/pictograms pictograms"
|
||||
},
|
||||
"dependencies": {
|
||||
"@navikt/ds-icons": "^2.7.7",
|
||||
"@navikt/ds-react": "^2.7.7",
|
||||
"@navikt/ds-icons": "^2.8.6",
|
||||
"@navikt/ds-react": "^2.8.6",
|
||||
"clsx": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* import React from "react";
|
||||
import { PageHeader } from ".";
|
||||
|
||||
export default {
|
||||
@@ -14,11 +13,3 @@ export default {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Default = {
|
||||
render: (props) => <PageHeader>{props.children}</PageHeader>,
|
||||
|
||||
args: {
|
||||
children: "Id elit esse enim reprehenderit enim nisi veniam nostrud.",
|
||||
},
|
||||
}; */
|
||||
@@ -1,5 +1,43 @@
|
||||
# @navikt/ds-css
|
||||
|
||||
## 2.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`2eb358ad8`](https://github.com/navikt/aksel/commit/2eb358ad888979d21c385b3900973946f3f466be) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Alert, Chips og ErrorSummary har nå bedre utvalg av tokens
|
||||
|
||||
## 2.8.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`f66437082`](https://github.com/navikt/aksel/commit/f664370826ed51bda7ad681e1f1799c26d2c1f0a) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :art: Accordion-tokens for header bakgrunn
|
||||
|
||||
- [#1879](https://github.com/navikt/aksel/pull/1879) [`55b585618`](https://github.com/navikt/aksel/commit/55b585618341a4d8bf26ed9b9e129d897b1600dc) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :bug: Fikset tekstfarge i select på iphone
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1870](https://github.com/navikt/aksel/pull/1870) [`9c495cf50`](https://github.com/navikt/aksel/commit/9c495cf5037a7453e51e273ab93e4232576f4958) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert typografi for ExpansioCard
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1820](https://github.com/navikt/aksel/pull/1820) [`c6d51a019`](https://github.com/navikt/aksel/commit/c6d51a01902e4fd7916a422e17ed175f39acd458) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :tada: Ny komponent! ExpansionCard. Oppfølger fra gammel Ekspanderbartpanel.
|
||||
|
||||
## 2.7.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1863](https://github.com/navikt/aksel/pull/1863) [`7ace69f21`](https://github.com/navikt/aksel/commit/7ace69f215760bbb5bf997670c897403d8ee558d) Thanks [@it-vegard](https://github.com/it-vegard)! - Added focus indicator for tabpanel
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
padding: 14px var(--a-spacing-3) var(--a-spacing-3);
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
background: var(--ac-accordion-header-bg, var(--a-surface-transparent));
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--ac-accordion-header-border, var(--a-border-divider));
|
||||
@@ -25,6 +25,7 @@
|
||||
.navds-accordion__header:hover {
|
||||
color: var(--ac-accordion-header-text-hover, var(--a-text-action-on-action-subtle));
|
||||
border-color: var(--ac-accordion-header-border-hover, var(--a-border-default));
|
||||
background: var(--ac-accordion-header-bg-hover, var(--a-surface-transparent));
|
||||
}
|
||||
|
||||
.navds-accordion__header-content {
|
||||
@@ -33,10 +34,14 @@
|
||||
}
|
||||
|
||||
.navds-accordion__item--open > .navds-accordion__header {
|
||||
background-color: var(--ac-accordion-item-bg-open, var(--a-surface-action-subtle));
|
||||
background-color: var(--ac-accordion-header-bg-open, var(--ac-accordion-item-bg-open, var(--a-surface-action-subtle)));
|
||||
border-color: var(--ac-accordion-item-border-open, var(--a-surface-action-subtle));
|
||||
}
|
||||
|
||||
.navds-accordion__item--open > :where(.navds-accordion__header:hover) {
|
||||
background-color: var(--ac-accordion-header-bg-open-hover, var(--a-surface-action-subtle));
|
||||
}
|
||||
|
||||
.navds-accordion__content {
|
||||
padding: var(--a-spacing-3) var(--a-spacing-3) 18px;
|
||||
border-bottom: 2px solid var(--ac-accordion-content-border, var(--a-border-divider));
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
background-color: var(--ac-alert-error-bg, var(--a-surface-danger-subtle));
|
||||
}
|
||||
|
||||
.navds-alert--error > .navds-alert__icon {
|
||||
color: var(--ac-alert-icon-error-color, var(--a-icon-danger));
|
||||
}
|
||||
|
||||
.navds-alert--warning {
|
||||
border-color: var(--ac-alert-warning-border, var(--a-border-warning));
|
||||
background-color: var(--ac-alert-warning-bg, var(--a-surface-warning-subtle));
|
||||
@@ -44,6 +48,7 @@
|
||||
|
||||
.navds-alert--warning > .navds-alert__icon {
|
||||
background: radial-gradient(circle at 50% 57%, var(--a-surface-default) 32%, 0, transparent);
|
||||
color: var(--ac-alert-icon-warning-color, var(--a-icon-warning));
|
||||
}
|
||||
|
||||
.navds-alert--info {
|
||||
@@ -51,11 +56,19 @@
|
||||
background-color: var(--ac-alert-info-bg, var(--a-surface-info-subtle));
|
||||
}
|
||||
|
||||
.navds-alert--info > .navds-alert__icon {
|
||||
color: var(--ac-alert-icon-info-color, var(--a-icon-info));
|
||||
}
|
||||
|
||||
.navds-alert--success {
|
||||
border-color: var(--ac-alert-success-border, var(--a-border-success));
|
||||
background-color: var(--ac-alert-success-bg, var(--a-surface-success-subtle));
|
||||
}
|
||||
|
||||
.navds-alert--success > .navds-alert__icon {
|
||||
color: var(--ac-alert-icon-success-color, var(--a-icon-success));
|
||||
}
|
||||
|
||||
.navds-alert--inline {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
.navds-chips__toggle {
|
||||
box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border, var(--a-border-default));
|
||||
background-color: var(--ac-chip-toggle-bg, var(--a-surface-neutral-subtle));
|
||||
color: var(--ac-chip-toggle-text, var(--a-text-default));
|
||||
}
|
||||
|
||||
.navds-chips__toggle:hover {
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
.navds-expansioncard {
|
||||
--__ac-expansioncard-border-color: var(--ac-expansioncard-border-color, var(--a-border-default));
|
||||
--__ac-expansioncard-border-radius: var(--ac-expansioncard-border-radius, var(--a-border-radius-large));
|
||||
--__ac-expansioncard-border-width: 1px;
|
||||
|
||||
border-radius: var(--__ac-expansioncard-border-radius);
|
||||
background-color: var(--ac-expansioncard-bg, var(--a-surface-default));
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.navds-expansioncard--open {
|
||||
--__ac-expansioncard-border-color: var(
|
||||
--ac-expansioncard-border-open-color,
|
||||
var(--ac-expansioncard-border-color, var(--a-border-default))
|
||||
);
|
||||
}
|
||||
|
||||
.navds-expansioncard:hover {
|
||||
--__ac-expansioncard-border-color: var(--ac-expansioncard-border-hover-color, var(--a-border-strong));
|
||||
}
|
||||
|
||||
:where(.navds-expansioncard.navds-expansioncard--open):hover {
|
||||
--__ac-expansioncard-border-color: var(--ac-expansioncard-border-hover-color, var(--a-border-strong));
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Header *
|
||||
*************************/
|
||||
.navds-expansioncard__header {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
gap: var(--a-spacing-4);
|
||||
padding: var(--a-spacing-4) var(--a-spacing-6);
|
||||
border-radius: var(--__ac-expansioncard-border-radius);
|
||||
background-color: var(--ac-expansioncard-header-bg, var(--a-surface-transparent));
|
||||
position: relative;
|
||||
border: var(--__ac-expansioncard-border-width) solid var(--__ac-expansioncard-border-color);
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.navds-expansioncard--small > :where(.navds-expansioncard__header) {
|
||||
padding: var(--a-spacing-3) var(--a-spacing-4);
|
||||
}
|
||||
|
||||
.navds-expansioncard__header:hover {
|
||||
background-color: var(--ac-expansioncard-header-bg-hover, var(--a-surface-hover));
|
||||
box-shadow: 0 0 0 1px var(--__ac-expansioncard-border-color);
|
||||
}
|
||||
|
||||
.navds-expansioncard--open > :where(.navds-expansioncard__header) {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border: var(--__ac-expansioncard-border-width) solid var(--__ac-expansioncard-border-color);
|
||||
border-bottom: none;
|
||||
background-color: var(--ac-expansioncard-header-open-bg, var(--a-surface-transparent));
|
||||
}
|
||||
|
||||
.navds-expansioncard--open > :where(.navds-expansioncard__header):hover {
|
||||
background-color: var(--ac-expansioncard-header-bg-hover, var(--a-surface-hover));
|
||||
box-shadow: 1px 0 0 0 var(--__ac-expansioncard-border-color), -1px 0 0 0 var(--__ac-expansioncard-border-color),
|
||||
0 -1px 0 0 var(--__ac-expansioncard-border-color);
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Header/Typography *
|
||||
*************************/
|
||||
|
||||
.navds-expansioncard__title--small {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.navds-expansioncard__title--medium {
|
||||
margin-top: var(--a-spacing-2);
|
||||
}
|
||||
|
||||
.navds-expansioncard__title--large {
|
||||
margin-top: var(--a-spacing-1);
|
||||
}
|
||||
|
||||
.navds-expansioncard--small :where(.navds-expansioncard__title--small) {
|
||||
margin-top: var(--a-spacing-05);
|
||||
}
|
||||
|
||||
.navds-expansioncard--small :where(.navds-expansioncard__title--medium, .navds-expansioncard__title--large) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Header/Button *
|
||||
*************************/
|
||||
.navds-expansioncard__header-button {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: var(--ac-expansioncard-button-border-radius, var(--a-border-radius-medium));
|
||||
min-height: 3rem;
|
||||
min-width: 3rem;
|
||||
font-size: 1.5rem;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.navds-expansioncard--small > :where(.navds-expansioncard__header) > :where(.navds-expansioncard__header-button) {
|
||||
min-height: 2rem;
|
||||
min-width: 2rem;
|
||||
}
|
||||
|
||||
:where(.navds-expansioncard__header):hover > :where(.navds-expansioncard__header-button) {
|
||||
background-color: var(--a-surface-hover);
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-chevron {
|
||||
transition: transform 150ms ease-in-out;
|
||||
}
|
||||
|
||||
.navds-expansioncard--open :where(.navds-expansioncard__header-chevron) {
|
||||
transform: translateY(0) rotate(180deg);
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-button:hover > :where(.navds-expansioncard__header-chevron) {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-button:focus-visible {
|
||||
box-shadow: var(--a-shadow-focus);
|
||||
}
|
||||
|
||||
.navds-expansioncard--open :where(.navds-expansioncard__header-button):hover :where(.navds-expansioncard__header-chevron) {
|
||||
transform: translateY(-1px) rotate(180deg);
|
||||
}
|
||||
|
||||
.navds-expansioncard__header-button::after {
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*************************
|
||||
* Content *
|
||||
*************************/
|
||||
.navds-expansioncard__content {
|
||||
border-end-end-radius: var(--__ac-expansioncard-border-radius);
|
||||
border-end-start-radius: var(--__ac-expansioncard-border-radius);
|
||||
padding: var(--a-spacing-3) var(--a-spacing-6) var(--a-spacing-6);
|
||||
border: var(--__ac-expansioncard-border-width) solid var(--__ac-expansioncard-border-color);
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.navds-expansioncard--small > :where(.navds-expansioncard__content) {
|
||||
padding: var(--a-spacing-3) var(--a-spacing-4) var(--a-spacing-4);
|
||||
}
|
||||
|
||||
.navds-expansioncard__content--closed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:where(.navds-expansioncard__header):hover + .navds-expansioncard__content {
|
||||
box-shadow: 1px 0 0 0 var(--__ac-expansioncard-border-color), -1px 0 0 0 var(--__ac-expansioncard-border-color),
|
||||
0 1px 0 0 var(--__ac-expansioncard-border-color);
|
||||
}
|
||||
|
||||
.navds-expansioncard__content-inner {
|
||||
animation: fadeExpansionCard 250ms ease;
|
||||
}
|
||||
|
||||
.navds-expansioncard--no-fade :where(.navds-expansioncard__content-inner) {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
@keyframes fadeExpansionCard {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
40% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
}
|
||||
|
||||
.navds-error-summary__list > * {
|
||||
color: var(--a-blue-500);
|
||||
color: var(--ac-error-summary-list-dot, var(--a-text-action));
|
||||
}
|
||||
|
||||
.navds-error-summary--small > .navds-error-summary__list {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
background-color: var(--ac-select-bg, var(--a-surface-default));
|
||||
border-radius: var(--a-border-radius-medium);
|
||||
border: 1px solid var(--ac-select-border, var(--a-border-default));
|
||||
color: var(--ac-select-text, var(--a-text-default));
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
min-height: 48px;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
@import "content-container.css";
|
||||
@import "chat.css";
|
||||
@import "chips.css";
|
||||
@import "expansioncard.css";
|
||||
@import "guide-panel.css";
|
||||
@import "form/index.css";
|
||||
@import "help-text.css";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "CSS for NAV Designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
@@ -20,7 +20,7 @@
|
||||
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^2.7.7",
|
||||
"@navikt/ds-tokens": "^2.8.6",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.4.0",
|
||||
"postcss-cli": "^9.0.0",
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.navds-tabs__tabpanel:focus {
|
||||
.navds-tabs__tabpanel:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: inset 0 0 0 2px var(--a-border-focus);
|
||||
}
|
||||
@@ -2,18 +2,26 @@
|
||||
"alert": {
|
||||
"--ac-alert-error-border": "--a-border-danger",
|
||||
"--ac-alert-error-bg": "--a-surface-danger-subtle",
|
||||
"--ac-alert-icon-error-color": "--a-icon-danger",
|
||||
"--ac-alert-warning-border": "--a-border-warning",
|
||||
"--ac-alert-warning-bg": "--a-surface-warning-subtle",
|
||||
"--ac-alert-icon-warning-color": "--a-icon-warning",
|
||||
"--ac-alert-info-border": "--a-border-info",
|
||||
"--ac-alert-info-bg": "--a-surface-info-subtle",
|
||||
"--ac-alert-icon-info-color": "--a-icon-info",
|
||||
"--ac-alert-success-border": "--a-border-success",
|
||||
"--ac-alert-success-bg": "--a-surface-success-subtle"
|
||||
"--ac-alert-success-bg": "--a-surface-success-subtle",
|
||||
"--ac-alert-icon-success-color": "--a-icon-success"
|
||||
},
|
||||
"accordion": {
|
||||
"--ac-accordion-header-bg": "--ac-surface-transparent",
|
||||
"--ac-accordion-header-bg-hover": "--ac-surface-transparent",
|
||||
"--ac-accordion-header-border": "--a-border-divider",
|
||||
"--ac-accordion-header-text-hover": "--a-text-action-on-action-subtle",
|
||||
"--ac-accordion-header-border-hover": "--a-border-default",
|
||||
"--ac-accordion-item-bg-open": "--a-surface-action-subtle",
|
||||
"--ac-accordion-header-bg-open": "--ac-accordion-item-bg-open",
|
||||
"--ac-accordion-header-bg-open-hover": "--a-surface-action-subtle",
|
||||
"--ac-accordion-item-border-open": "--a-surface-action-subtle",
|
||||
"--ac-accordion-content-border": "--a-border-divider",
|
||||
"--ac-accordion-content-border-open": "--a-border-default"
|
||||
@@ -76,6 +84,7 @@
|
||||
"chips": {
|
||||
"--ac-chip-toggle-border": "--a-border-default",
|
||||
"--ac-chip-toggle-bg": "--a-surface-neutral-subtle",
|
||||
"--ac-chip-toggle-text": "--a-text-default",
|
||||
"--ac-chip-toggle-hover-border": "--a-border-strong",
|
||||
"--ac-chip-toggle-hover-bg": "--a-surface-neutral-subtle-hover",
|
||||
"--ac-chip-toggle-pressed-bg": "--a-surface-action-selected",
|
||||
@@ -106,6 +115,17 @@
|
||||
"--ac-date-input-error-border": "--a-border-danger",
|
||||
"--ac-date-input-button-text": "--a-text-default"
|
||||
},
|
||||
"expansioncard": {
|
||||
"--ac-expansioncard-bg": "--a-surface-default",
|
||||
"--ac-expansioncard-header-bg": "--a-surface-transparent",
|
||||
"--ac-expansioncard-header-bg-hover": "--a-surface-hover",
|
||||
"--ac-expansioncard-header-open-bg": "--a-surface-transparent",
|
||||
"--ac-expansioncard-border-color": "--a-border-default",
|
||||
"--ac-expansioncard-border-open-color": "--a-border-default",
|
||||
"--ac-expansioncard-border-radius": "--a-border-radius-large",
|
||||
"--ac-expansioncard-button-border-radius": "--a-border-radius-medium",
|
||||
"--ac-expansioncard-border-hover-color": "--a-border-strong"
|
||||
},
|
||||
"guidepanel": {
|
||||
"--ac-guide-panel-bg": "--a-surface-default",
|
||||
"--ac-guide-panel-border": "--a-border-action",
|
||||
@@ -281,7 +301,8 @@
|
||||
},
|
||||
"errorsummary": {
|
||||
"--ac-error-summary-bg": "--a-surface-default",
|
||||
"--ac-error-summary-border": "--a-border-danger"
|
||||
"--ac-error-summary-border": "--a-border-danger",
|
||||
"--ac-error-summary-list-dot": "--a-text-action"
|
||||
},
|
||||
"checkbox-radio": {
|
||||
"--ac-radio-checkbox-bg": "--a-surface-default",
|
||||
@@ -301,6 +322,7 @@
|
||||
},
|
||||
"select": {
|
||||
"--ac-select-bg": "--a-surface-default",
|
||||
"--ac-select-text": "--a-text-default",
|
||||
"--ac-select-border": "--a-border-default",
|
||||
"--ac-select-hover-bg": "--a-border-action",
|
||||
"--ac-select-error-border": "--a-surface-danger"
|
||||
|
||||
@@ -1,5 +1,80 @@
|
||||
# @navikt/ds-react
|
||||
|
||||
## 2.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`2eb358ad8`](https://github.com/navikt/aksel/commit/2eb358ad888979d21c385b3900973946f3f466be) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Alert, Chips og ErrorSummary har nå bedre utvalg av tokens
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.6
|
||||
- @navikt/ds-icons@2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.5
|
||||
- @navikt/ds-icons@2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.4
|
||||
- @navikt/ds-icons@2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1875](https://github.com/navikt/aksel/pull/1875) [`f862aa9c2`](https://github.com/navikt/aksel/commit/f862aa9c2ec71ffdb295708dc6dad6b77af9519e) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Textarea har oppdatert counter-tekst + mulighet for lokalisering
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.3
|
||||
- @navikt/ds-icons@2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#1870](https://github.com/navikt/aksel/pull/1870) [`9c495cf50`](https://github.com/navikt/aksel/commit/9c495cf5037a7453e51e273ab93e4232576f4958) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert typografi for ExpansioCard
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.2
|
||||
- @navikt/ds-icons@2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [`1276b4d7e`](https://github.com/navikt/aksel/commit/1276b4d7efd831d20345292dbb21a11d100a0ddd) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :bug: Endret default title-size til medium for ExpansionCard
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.1
|
||||
- @navikt/ds-icons@2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1820](https://github.com/navikt/aksel/pull/1820) [`c6d51a019`](https://github.com/navikt/aksel/commit/c6d51a01902e4fd7916a422e17ed175f39acd458) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :tada: Ny komponent! ExpansionCard. Oppfølger fra gammel Ekspanderbartpanel.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/aksel-icons@2.8.0
|
||||
- @navikt/ds-icons@2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Aksel react-components for NAV designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -37,7 +37,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "0.17.0",
|
||||
"@navikt/ds-icons": "^2.7.7",
|
||||
"@navikt/aksel-icons": "^2.8.6",
|
||||
"@navikt/ds-icons": "^2.8.6",
|
||||
"@radix-ui/react-tabs": "1.0.0",
|
||||
"@radix-ui/react-toggle-group": "1.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
ErrorColored,
|
||||
InformationColored,
|
||||
SuccessColored,
|
||||
WarningColored,
|
||||
ErrorFilled,
|
||||
InformationFilled,
|
||||
SuccessFilled,
|
||||
WarningFilled,
|
||||
} from "@navikt/ds-icons";
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
@@ -37,13 +37,13 @@ export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
const Icon = ({ variant, ...props }) => {
|
||||
switch (variant) {
|
||||
case "error":
|
||||
return <ErrorColored title="Feil" {...props} />;
|
||||
return <ErrorFilled title="Feil" {...props} />;
|
||||
case "warning":
|
||||
return <WarningColored title="Advarsel" {...props} />;
|
||||
return <WarningFilled title="Advarsel" {...props} />;
|
||||
case "info":
|
||||
return <InformationColored title="Informasjon" {...props} />;
|
||||
return <InformationFilled title="Informasjon" {...props} />;
|
||||
case "success":
|
||||
return <SuccessColored title="Suksess" {...props} />;
|
||||
return <SuccessFilled title="Suksess" {...props} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import cl from "clsx";
|
||||
import React, { createContext, forwardRef, useRef, useState } from "react";
|
||||
import ExpansionCardContent, {
|
||||
ExpansionCardContentType,
|
||||
} from "./ExpansionCardContent";
|
||||
import {
|
||||
ExpansionCardDescription,
|
||||
ExpansionCardDescriptionType,
|
||||
} from "./ExpansionCardDescription";
|
||||
import ExpansionCardHeader, {
|
||||
ExpansionCardHeaderType,
|
||||
} from "./ExpansionCardHeader";
|
||||
import {
|
||||
ExpansionCardTitle,
|
||||
ExpansionCardTitleType,
|
||||
} from "./ExpansionCardTitle";
|
||||
|
||||
interface ExpansionCardComponent
|
||||
extends React.ForwardRefExoticComponent<
|
||||
ExpansionCardProps & React.RefAttributes<HTMLDivElement>
|
||||
> {
|
||||
Header: ExpansionCardHeaderType;
|
||||
Title: ExpansionCardTitleType;
|
||||
Description: ExpansionCardDescriptionType;
|
||||
Content: ExpansionCardContentType;
|
||||
}
|
||||
|
||||
export interface ExpansionCardProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Callback for when Card is toggled open/closed
|
||||
*/
|
||||
onToggle?: (open: boolean) => void;
|
||||
/**
|
||||
* Controlled open-state
|
||||
* Using this removes automatic control of open-state
|
||||
*/
|
||||
open?: boolean;
|
||||
/**
|
||||
* Defaults to open if not controlled
|
||||
* @default false
|
||||
*/
|
||||
defaultOpen?: boolean;
|
||||
/**
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
/**
|
||||
* Since ExpansionCard is a section-element, accessible name is required.
|
||||
*/
|
||||
["aria-label"]: string;
|
||||
}
|
||||
|
||||
export type ExpansionCardContextProps = {
|
||||
open: boolean;
|
||||
toggleOpen: () => void;
|
||||
size: "medium" | "small";
|
||||
};
|
||||
|
||||
export const ExpansionCardContext = createContext<ExpansionCardContextProps>({
|
||||
open: false,
|
||||
toggleOpen: () => {},
|
||||
size: "medium",
|
||||
});
|
||||
|
||||
export const ExpansionCard = forwardRef<HTMLDivElement, ExpansionCardProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
onToggle,
|
||||
open,
|
||||
defaultOpen = false,
|
||||
size = "medium",
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [_open, _setOpen] = useState(defaultOpen);
|
||||
|
||||
const shouldFade = useRef<boolean>(!(Boolean(open) || defaultOpen));
|
||||
|
||||
const handleOpen = () => {
|
||||
if (open === undefined) {
|
||||
const newOpen = !_open;
|
||||
_setOpen(newOpen);
|
||||
onToggle?.(newOpen);
|
||||
} else {
|
||||
onToggle?.(!open);
|
||||
}
|
||||
shouldFade.current = true;
|
||||
};
|
||||
|
||||
return (
|
||||
<ExpansionCardContext.Provider
|
||||
value={{ open: open ?? _open, toggleOpen: handleOpen, size }}
|
||||
>
|
||||
<section
|
||||
{...rest}
|
||||
className={cl(
|
||||
"navds-expansioncard",
|
||||
className,
|
||||
`navds-expansioncard--${size}`,
|
||||
{
|
||||
"navds-expansioncard--open": open ?? _open,
|
||||
"navds-expansioncard--no-fade": !shouldFade.current,
|
||||
}
|
||||
)}
|
||||
ref={ref}
|
||||
/>
|
||||
</ExpansionCardContext.Provider>
|
||||
);
|
||||
}
|
||||
) as ExpansionCardComponent;
|
||||
|
||||
ExpansionCard.Header = ExpansionCardHeader;
|
||||
ExpansionCard.Content = ExpansionCardContent;
|
||||
ExpansionCard.Title = ExpansionCardTitle;
|
||||
ExpansionCard.Description = ExpansionCardDescription;
|
||||
|
||||
export default ExpansionCard;
|
||||
@@ -0,0 +1,43 @@
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import { BodyLong } from "../typography/BodyLong";
|
||||
import { ExpansionCardContext } from "./ExpansionCard";
|
||||
|
||||
export interface ExpansionCardContentProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export type ExpansionCardContentType = React.ForwardRefExoticComponent<
|
||||
ExpansionCardContentProps & React.RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
const ExpansionCardContent: ExpansionCardContentType = forwardRef(
|
||||
({ children, className, ...rest }, ref) => {
|
||||
const panelContext = useContext(ExpansionCardContext);
|
||||
|
||||
if (panelContext === null) {
|
||||
console.error(
|
||||
"<ExpansionCard.Content> has to be used within an <ExpansionCard>"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<BodyLong
|
||||
{...rest}
|
||||
ref={ref}
|
||||
as="div"
|
||||
className={cl("navds-expansioncard__content", {
|
||||
"navds-expansioncard__content--closed": !panelContext.open,
|
||||
})}
|
||||
aria-hidden={!panelContext.open}
|
||||
size={panelContext.size}
|
||||
>
|
||||
<div className="navds-expansioncard__content-inner">{children}</div>
|
||||
</BodyLong>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ExpansionCardContent;
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import cl from "clsx";
|
||||
import { BodyLong } from "../typography/BodyLong";
|
||||
import { ExpansionCardContext } from "./ExpansionCard";
|
||||
|
||||
interface ExpansionCardDescriptionProps
|
||||
extends React.HTMLAttributes<HTMLParagraphElement> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export type ExpansionCardDescriptionType = React.ForwardRefExoticComponent<
|
||||
ExpansionCardDescriptionProps & React.RefAttributes<HTMLParagraphElement>
|
||||
>;
|
||||
|
||||
export const ExpansionCardDescription: ExpansionCardDescriptionType =
|
||||
forwardRef(({ className, ...rest }, ref) => {
|
||||
const panelContext = useContext(ExpansionCardContext);
|
||||
|
||||
if (panelContext === null) {
|
||||
console.error(
|
||||
"<ExpansionCard.Header> has to be used within an <ExpansionCard>"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<BodyLong
|
||||
{...rest}
|
||||
as="p"
|
||||
ref={ref}
|
||||
className={cl("navds-link-panel__description", className)}
|
||||
size={panelContext.size}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import { ExpansionCardContext } from "./ExpansionCard";
|
||||
import { ChevronDownIcon } from "@navikt/aksel-icons";
|
||||
|
||||
export interface ExpansionCardHeaderProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export type ExpansionCardHeaderType = React.ForwardRefExoticComponent<
|
||||
ExpansionCardHeaderProps & React.RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
const ExpansionCardHeader: ExpansionCardHeaderType = forwardRef(
|
||||
({ children, className, ...rest }, ref) => {
|
||||
const panelContext = useContext(ExpansionCardContext);
|
||||
|
||||
if (panelContext === null) {
|
||||
console.error(
|
||||
"<ExpansionCard.Header> has to be used within an <ExpansionCard>"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
{...rest}
|
||||
className={cl("navds-expansioncard__header", className)}
|
||||
>
|
||||
<div className="navds-expansioncard__header-content">{children}</div>
|
||||
|
||||
<button
|
||||
className="navds-expansioncard__header-button"
|
||||
onClick={() => panelContext.toggleOpen()}
|
||||
type="button"
|
||||
aria-expanded={panelContext.open}
|
||||
>
|
||||
<ChevronDownIcon
|
||||
className="navds-expansioncard__header-chevron"
|
||||
title="Vis mer"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ExpansionCardHeader;
|
||||
@@ -0,0 +1,34 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "clsx";
|
||||
import { OverridableComponent } from "../util/OverridableComponent";
|
||||
|
||||
interface ExpansionCardTitleProps
|
||||
extends React.HTMLAttributes<HTMLHeadingElement> {
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes text-sizing
|
||||
* @default medium
|
||||
*/
|
||||
size?: "large" | "medium" | "small";
|
||||
}
|
||||
|
||||
export type ExpansionCardTitleType = OverridableComponent<
|
||||
ExpansionCardTitleProps,
|
||||
HTMLHeadingElement
|
||||
>;
|
||||
|
||||
export const ExpansionCardTitle: ExpansionCardTitleType = forwardRef(
|
||||
({ className, as: Component = "h3", size = "medium", ...rest }, ref) => (
|
||||
<Component
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-expansioncard__title",
|
||||
`navds-expansioncard__title--${size}`,
|
||||
"navds-heading",
|
||||
`navds-heading--${size}`,
|
||||
className
|
||||
)}
|
||||
/>
|
||||
)
|
||||
);
|
||||
@@ -0,0 +1,269 @@
|
||||
import { PlantIcon } from "@navikt/aksel-icons";
|
||||
import React, { useState } from "react";
|
||||
import { ExpansionCard } from ".";
|
||||
import { BodyLong } from "../typography";
|
||||
import ExpansionCardContent from "./ExpansionCardContent";
|
||||
import ExpansionCardHeader from "./ExpansionCardHeader";
|
||||
|
||||
export default {
|
||||
title: "ds-react/ExpansionCard",
|
||||
component: ExpansionCard,
|
||||
subcomponents: [ExpansionCardHeader, ExpansionCardContent],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div
|
||||
style={{
|
||||
width: "600px",
|
||||
minHeight: "100vh",
|
||||
padding: "10rem 0",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
const Content = () => (
|
||||
<ExpansionCard.Content>
|
||||
<BodyLong spacing>
|
||||
På ditt faste arbeidssted vil du ha yrkesskadedekning også i hvilepauser,
|
||||
lunsjpauser, trimaktiviteter og lignende i arbeidstiden.
|
||||
</BodyLong>
|
||||
<BodyLong spacing>
|
||||
Som hovedregel er du som arbeidstaker ikke yrkesskadedekket på veien til
|
||||
og fra arbeid eller første og siste oppdragssted. Du er heller ikke
|
||||
yrkesskadedekket på fritiden eller under private gjøremål i arbeidstiden.
|
||||
</BodyLong>
|
||||
<BodyLong spacing>
|
||||
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga suscipit
|
||||
voluptatum expedita earum id, aperiam deleniti molestiae eveniet
|
||||
doloremque explicabo perspiciatis quasi repellendus! Est dolore a nemo
|
||||
aspernatur obcaecati dicta.
|
||||
</BodyLong>
|
||||
<BodyLong spacing>
|
||||
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga suscipit
|
||||
voluptatum expedita earum id, aperiam deleniti molestiae eveniet
|
||||
doloremque explicabo perspiciatis quasi repellendus! Est dolore a nemo
|
||||
aspernatur obcaecati dicta.
|
||||
</BodyLong>
|
||||
<BodyLong>
|
||||
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fuga suscipit
|
||||
voluptatum expedita earum id, aperiam deleniti molestiae eveniet
|
||||
doloremque explicabo perspiciatis quasi repellendus! Est dolore a nemo
|
||||
aspernatur obcaecati dicta.
|
||||
</BodyLong>
|
||||
</ExpansionCard.Content>
|
||||
);
|
||||
|
||||
export const Default = {
|
||||
render: (props) => {
|
||||
return (
|
||||
<ExpansionCard
|
||||
{...props}
|
||||
open={props?.open || undefined}
|
||||
size={props.size}
|
||||
aria-label="default-demo"
|
||||
>
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
{props.description && (
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
)}
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
);
|
||||
},
|
||||
args: {
|
||||
open: false,
|
||||
size: "medium",
|
||||
description: false,
|
||||
variant: "neutral",
|
||||
},
|
||||
argTypes: {
|
||||
size: { control: "select", options: ["medium", "small"] },
|
||||
},
|
||||
};
|
||||
|
||||
export const Description = {
|
||||
render: () => (
|
||||
<ExpansionCard aria-label="bare description">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav til
|
||||
tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
),
|
||||
};
|
||||
|
||||
export const Sizes = {
|
||||
render: () => (
|
||||
<>
|
||||
<h2>Medium</h2>
|
||||
<ExpansionCard aria-label="Demo med description">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
<ExpansionCard aria-label="Demo">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
<h2>Small</h2>
|
||||
<ExpansionCard size="small" aria-label="small-demo">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
<ExpansionCard
|
||||
size="small"
|
||||
aria-label="small-demo med avatar uten description"
|
||||
>
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
export const HeadingSizing = {
|
||||
render: () => (
|
||||
<>
|
||||
{(["large", "medium", "small"] as const).map((x) => (
|
||||
<ExpansionCard aria-label={`demo-${x}`}>
|
||||
<ExpansionCard.Header key={x}>
|
||||
<ExpansionCard.Title size={x}>{x}</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
))}
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
export const DefaultOpen = {
|
||||
render: () => (
|
||||
<ExpansionCard defaultOpen aria-label="defaultOpen demo">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav til
|
||||
tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
),
|
||||
};
|
||||
|
||||
export const ControlledState = {
|
||||
render: () => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<ExpansionCard
|
||||
open={open}
|
||||
onToggle={setOpen}
|
||||
aria-label="Controlled-state demo"
|
||||
>
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const Customization = {
|
||||
render: () => (
|
||||
<div className="subtle-card">
|
||||
<ExpansionCard aria-label="custom-styling demo">
|
||||
<ExpansionCard.Header>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel krav
|
||||
til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
|
||||
<style>{`
|
||||
.subtle-card {
|
||||
--ac-expansioncard-bg: var(--a-surface-subtle);
|
||||
--ac-expansioncard-border-open-color: var(--a-border-alt-3);
|
||||
}`}</style>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const Icon = {
|
||||
render: () => (
|
||||
<div>
|
||||
<ExpansionCard aria-label="custom-styling demo">
|
||||
<ExpansionCard.Header>
|
||||
<div className="with-icon">
|
||||
<div className="icon">
|
||||
<PlantIcon aria-hidden />
|
||||
</div>
|
||||
<div>
|
||||
<ExpansionCard.Title>Arbeidstakere</ExpansionCard.Title>
|
||||
<ExpansionCard.Description>
|
||||
For at yrkesskadedekningen skal gjelde, er det som hovedregel
|
||||
krav til tid, sted og arbeidsoppgaver
|
||||
</ExpansionCard.Description>
|
||||
</div>
|
||||
</div>
|
||||
</ExpansionCard.Header>
|
||||
<Content />
|
||||
</ExpansionCard>
|
||||
|
||||
<style>{`
|
||||
.with-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.icon {
|
||||
font-size: 3rem;
|
||||
flex-shrink: 0;
|
||||
display: grid;
|
||||
place-content: center;
|
||||
}`}</style>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export {
|
||||
type ExpansionCardProps,
|
||||
default as ExpansionCard,
|
||||
} from "./ExpansionCard";
|
||||
@@ -45,6 +45,15 @@ export interface TextareaProps
|
||||
* Enables resizing of field
|
||||
*/
|
||||
resize?: boolean;
|
||||
/**
|
||||
* i18n-translations for counter-text
|
||||
*/
|
||||
i18n?: {
|
||||
/** @default Antall tegn igjen */
|
||||
counterLeft?: string;
|
||||
/** @default tegn for mye */
|
||||
counterTooMuch?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
@@ -65,6 +74,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
maxLength,
|
||||
hideLabel = false,
|
||||
resize,
|
||||
i18n,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@@ -166,6 +176,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
maxLength={maxLength}
|
||||
currentLength={props.value?.length ?? controlledValue?.length}
|
||||
size={size}
|
||||
i18n={i18n}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -185,7 +196,7 @@ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
|
||||
}
|
||||
);
|
||||
|
||||
export const Counter = ({ maxLength, currentLength, size }) => {
|
||||
export const Counter = ({ maxLength, currentLength, size, i18n }) => {
|
||||
const difference = maxLength - currentLength;
|
||||
|
||||
return (
|
||||
@@ -197,8 +208,8 @@ export const Counter = ({ maxLength, currentLength, size }) => {
|
||||
size={size}
|
||||
>
|
||||
{difference < 0
|
||||
? `Antall tegn for mye ${Math.abs(difference)}`
|
||||
: `Antall tegn igjen ${difference}`}
|
||||
? `${Math.abs(difference)} ${i18n?.counterLeft ?? "tegn for mye"}`
|
||||
: `${difference} ${i18n?.counterTooMuch ?? "tegn igjen"}`}
|
||||
</BodyShort>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ export * from "./chat";
|
||||
export * from "./chips";
|
||||
export * from "./date";
|
||||
export * from "./form";
|
||||
export * from "./expansion-card";
|
||||
export * from "./grid";
|
||||
export * from "./guide-panel";
|
||||
export * from "./help-text";
|
||||
|
||||
@@ -3,9 +3,6 @@ import cl from "clsx";
|
||||
|
||||
export interface PopoverContentProps
|
||||
extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Modal.Content content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @navikt/ds-tailwind
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tailwind",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Tailwind config based on @navikt/ds-tokens",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
@@ -22,7 +22,7 @@
|
||||
"directory": "@navikt/core/tailwind"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^2.7.7",
|
||||
"@navikt/ds-tokens": "^2.8.6",
|
||||
"@types/jest": "^29.0.0",
|
||||
"color": "4.2.3",
|
||||
"jest": "^29.0.0",
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @navikt/ds-tokens
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Design-tokens for NAV designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @navikt/ds-icons
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-icons",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Aksel icons for NAV",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# @navikt/ds-css-internal
|
||||
|
||||
## 2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
## 2.7.6
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css-internal",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "CSS for NAV internal Designsystem-components",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,5 +1,69 @@
|
||||
# @navikt/ds-react-internal
|
||||
|
||||
## 2.8.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`2eb358ad8`](https://github.com/navikt/aksel/commit/2eb358ad888979d21c385b3900973946f3f466be)]:
|
||||
- @navikt/ds-react@2.8.6
|
||||
- @navikt/ds-icons@2.8.6
|
||||
|
||||
## 2.8.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@2.8.5
|
||||
- @navikt/ds-icons@2.8.5
|
||||
|
||||
## 2.8.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@2.8.4
|
||||
- @navikt/ds-icons@2.8.4
|
||||
|
||||
## 2.8.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f862aa9c2`](https://github.com/navikt/aksel/commit/f862aa9c2ec71ffdb295708dc6dad6b77af9519e)]:
|
||||
- @navikt/ds-react@2.8.3
|
||||
- @navikt/ds-icons@2.8.3
|
||||
|
||||
## 2.8.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`9c495cf50`](https://github.com/navikt/aksel/commit/9c495cf5037a7453e51e273ab93e4232576f4958)]:
|
||||
- @navikt/ds-react@2.8.2
|
||||
- @navikt/ds-icons@2.8.2
|
||||
|
||||
## 2.8.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`1276b4d7e`](https://github.com/navikt/aksel/commit/1276b4d7efd831d20345292dbb21a11d100a0ddd)]:
|
||||
- @navikt/ds-react@2.8.1
|
||||
- @navikt/ds-icons@2.8.1
|
||||
|
||||
## 2.8.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`c6d51a019`](https://github.com/navikt/aksel/commit/c6d51a01902e4fd7916a422e17ed175f39acd458)]:
|
||||
- @navikt/ds-react@2.8.0
|
||||
- @navikt/ds-icons@2.8.0
|
||||
|
||||
## 2.7.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@2.7.8
|
||||
- @navikt/ds-icons@2.7.8
|
||||
|
||||
## 2.7.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react-internal",
|
||||
"version": "2.7.7",
|
||||
"version": "2.8.6",
|
||||
"description": "Aksel react components for internal UIs in NAV",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -35,8 +35,8 @@
|
||||
"watch": "tsc --watch -p tsconfig.esm.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@navikt/ds-icons": "^2.7.7",
|
||||
"@navikt/ds-react": "^2.7.7",
|
||||
"@navikt/ds-icons": "^2.8.6",
|
||||
"@navikt/ds-react": "^2.8.6",
|
||||
"clsx": "^1.1.1",
|
||||
"copy-to-clipboard": "^3.3.1"
|
||||
},
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
"website"
|
||||
],
|
||||
"dependencies": {
|
||||
"@navikt/aksel-icons": "^2.7.7",
|
||||
"@navikt/ds-codemod": "^2.7.7",
|
||||
"@navikt/ds-css": "^2.7.7",
|
||||
"@navikt/ds-css-internal": "^2.7.7",
|
||||
"@navikt/ds-icons": "^2.7.7",
|
||||
"@navikt/ds-react": "^2.7.7",
|
||||
"@navikt/ds-react-internal": "^2.7.7",
|
||||
"@navikt/ds-tailwind": "^2.7.7",
|
||||
"@navikt/ds-tokens": "^2.7.7"
|
||||
"@navikt/aksel-icons": "^2.8.6",
|
||||
"@navikt/ds-codemod": "^2.8.6",
|
||||
"@navikt/ds-css": "^2.8.6",
|
||||
"@navikt/ds-css-internal": "^2.8.6",
|
||||
"@navikt/ds-icons": "^2.8.6",
|
||||
"@navikt/ds-react": "^2.8.6",
|
||||
"@navikt/ds-react-internal": "^2.8.6",
|
||||
"@navikt/ds-tailwind": "^2.8.6",
|
||||
"@navikt/ds-tokens": "^2.8.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier-plugin-tailwindcss": "^0.2.3"
|
||||
|
||||
@@ -3,6 +3,7 @@ import { BodyLong, Detail, Heading, Ingress, Link } from "@navikt/ds-react";
|
||||
import BlockContent from "@sanity/block-content-to-react";
|
||||
import cl from "clsx";
|
||||
import InnholdsKort from "components/sanity-modules/cards/InnholdsKort";
|
||||
import ExpansionCard from "components/sanity-modules/ExpansionCard";
|
||||
import NextLink from "next/link";
|
||||
import React, { createContext, useContext } from "react";
|
||||
import {
|
||||
@@ -49,6 +50,7 @@ const serializers = {
|
||||
do_dont: ({ node }) => <DoDont node={node} />,
|
||||
bilde: ({ node }) => <Bilde node={node} />,
|
||||
alert: ({ node }) => <Alert node={node} />,
|
||||
expansioncard: ({ node }) => <ExpansionCard node={node} />,
|
||||
kode: ({ node }) => <Kode node={node} />,
|
||||
tabell_v2: ({ node }) => <Tabell node={node} />,
|
||||
accordion: ({ node }) => <Accordion node={node} />,
|
||||
|
||||
@@ -83,6 +83,52 @@ export const GithubIcon = ({ ...props }) => (
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const SlackIcon = ({ ...props }) => (
|
||||
<svg
|
||||
width="20"
|
||||
height="21"
|
||||
viewBox="0 0 20 21"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
focusable={false}
|
||||
aria-hidden
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M4.92656 12.8086C4.92625 13.1721 4.81818 13.5274 4.616 13.8295C4.41382 14.1316 4.12661 14.3669 3.79068 14.5058C3.45475 14.6447 3.08518 14.6809 2.72869 14.6098C2.37221 14.5387 2.0448 14.3635 1.78787 14.1063C1.53094 13.8492 1.35601 13.5216 1.28521 13.1651C1.2144 12.8085 1.2509 12.439 1.39008 12.1032C1.52926 11.7674 1.76488 11.4804 2.06715 11.2784C2.36942 11.0765 2.72477 10.9688 3.08828 10.9688H4.92656V12.8086Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M5.85303 12.8086C5.85303 12.3211 6.0467 11.8535 6.39145 11.5088C6.73619 11.164 7.20377 10.9703 7.69131 10.9703C8.17885 10.9703 8.64643 11.164 8.99117 11.5088C9.33591 11.8535 9.52959 12.3211 9.52959 12.8086V17.4117C9.52959 17.8993 9.33591 18.3669 8.99117 18.7116C8.64643 19.0563 8.17885 19.25 7.69131 19.25C7.20377 19.25 6.73619 19.0563 6.39145 18.7116C6.0467 18.3669 5.85303 17.8993 5.85303 17.4117V12.8086Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M7.69146 5.42656C7.32794 5.42625 6.97269 5.31818 6.67059 5.116C6.36849 4.91382 6.13312 4.62661 5.99422 4.29068C5.85532 3.95475 5.81914 3.58518 5.89025 3.22869C5.96136 2.87221 6.13656 2.5448 6.39371 2.28787C6.65086 2.03094 6.97841 1.85601 7.33496 1.78521C7.69151 1.7144 8.06105 1.7509 8.39686 1.89008C8.73267 2.02926 9.01968 2.26488 9.2216 2.56715C9.42353 2.86942 9.5313 3.22477 9.5313 3.58828V5.42656H7.69146Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M7.69141 6.35315C8.17895 6.35315 8.64652 6.54682 8.99127 6.89157C9.33601 7.23631 9.52969 7.70389 9.52969 8.19143C9.52969 8.67897 9.33601 9.14655 8.99127 9.49129C8.64652 9.83604 8.17895 10.0297 7.69141 10.0297H3.08828C2.60074 10.0297 2.13316 9.83604 1.78842 9.49129C1.44368 9.14655 1.25 8.67897 1.25 8.19143C1.25 7.70389 1.44368 7.23631 1.78842 6.89157C2.13316 6.54682 2.60074 6.35315 3.08828 6.35315H7.69141Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M15.0735 8.19139C15.0738 7.82788 15.1819 7.47263 15.3841 7.17053C15.5862 6.86843 15.8734 6.63305 16.2094 6.49416C16.5453 6.35526 16.9149 6.31908 17.2714 6.39019C17.6278 6.4613 17.9552 6.6365 18.2122 6.89365C18.4691 7.1508 18.644 7.47835 18.7148 7.8349C18.7856 8.19145 18.7491 8.56099 18.61 8.8968C18.4708 9.23261 18.2352 9.51962 17.9329 9.72154C17.6306 9.92346 17.2753 10.0312 16.9118 10.0312H15.0735V8.19139Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M14.1468 8.19141C14.1468 8.67895 13.9531 9.14652 13.6084 9.49127C13.2636 9.83601 12.796 10.0297 12.3085 10.0297C11.821 10.0297 11.3534 9.83601 11.0086 9.49127C10.6639 9.14652 10.4702 8.67895 10.4702 8.19141V3.58828C10.4702 3.10074 10.6639 2.63316 11.0086 2.28842C11.3534 1.94368 11.821 1.75 12.3085 1.75C12.796 1.75 13.2636 1.94368 13.6084 2.28842C13.9531 2.63316 14.1468 3.10074 14.1468 3.58828V8.19141Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M12.3086 15.5734C12.6721 15.5737 13.0274 15.6818 13.3295 15.884C13.6316 16.0862 13.8669 16.3734 14.0058 16.7093C14.1447 17.0452 14.1809 17.4148 14.1098 17.7713C14.0387 18.1278 13.8635 18.4552 13.6063 18.7121C13.3492 18.9691 13.0216 19.144 12.6651 19.2148C12.3085 19.2856 11.939 19.2491 11.6032 19.1099C11.2674 18.9707 10.9804 18.7351 10.7784 18.4328C10.5765 18.1306 10.4688 17.7752 10.4688 17.4117V15.5734H12.3086Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M12.3085 14.6469C11.821 14.6469 11.3534 14.4532 11.0086 14.1085C10.6639 13.7637 10.4702 13.2962 10.4702 12.8086C10.4702 12.3211 10.6639 11.8535 11.0086 11.5088C11.3534 11.164 11.821 10.9703 12.3085 10.9703H16.9116C17.3992 10.9703 17.8667 11.164 18.2115 11.5088C18.5562 11.8535 18.7499 12.3211 18.7499 12.8086C18.7499 13.2962 18.5562 13.7637 18.2115 14.1085C17.8667 14.4532 17.3992 14.6469 16.9116 14.6469H12.3085Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const YarnIcon = () => (
|
||||
<svg
|
||||
width="20"
|
||||
@@ -128,23 +174,26 @@ export const StorybookIcon = ({ ...props }) => (
|
||||
<g id="storybook-icon" transform="translate(1.000000, 1.000000)">
|
||||
<path
|
||||
id="Combined-Shape"
|
||||
fill="var(--a-gray-600)"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
d="M50.2729096,2.92285771 C50.2769973,2.98759391 50.2790429,3.05244063 50.2790429,3.11730315 L50.2790429,58.8828028 C50.2790429,60.6043831 48.8689636,62 47.1295431,62 C47.0824212,62 47.0353056,61.9989534 46.9882313,61.9968606 L4.94876437,60.1280997 C3.31149338,60.0553189 2.00425692,58.751918 1.94279175,57.1309472 L0.0022554267,5.95476663 C-0.0618328758,4.26461814 1.24754196,2.83223697 2.95307926,2.72673418 L37.427,0.594 L37.1272753,7.62078766 C37.1238721,7.70179664 37.1419373,7.78178731 37.179031,7.85305525 L37.2223772,7.92113026 C37.3791917,8.12573637 37.6738999,8.16578288 37.880626,8.0105767 L37.880626,8.0105767 L40.6382617,5.94019678 L42.9673936,7.75618537 C43.0546693,7.82423279 43.1634862,7.85946584 43.2745216,7.85562813 C43.5338374,7.84666553 43.7367132,7.6313391 43.7276576,7.37468316 L43.7276576,7.37468316 L43.467,0.22 L46.9330824,0.00617628491 C48.6691159,-0.10121296 50.1644074,1.2046298 50.2729096,2.92285771 Z"
|
||||
className="group-focus:text-surface-inverted text-surface-default"
|
||||
/>
|
||||
<path
|
||||
id="S"
|
||||
fill="#fff"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
d="M29.4029796,23.368648 C29.4029796,24.58142 37.6567008,24.00017 38.7646901,23.1482813 C38.7646901,14.8895929 34.2873503,10.5497821 26.0885852,10.5497821 C17.88982,10.5497821 13.2961856,14.9571143 13.2961856,21.5681161 C13.2961856,33.0822778 28.9959487,33.3026444 28.9959487,39.5830962 C28.9959487,41.3460299 28.1237396,42.3927719 26.2048797,42.3927719 C23.7045471,42.3927719 22.7160434,41.1289316 22.832338,36.8317805 C22.832338,35.8995698 13.2961856,35.6089448 13.0054493,36.8317805 C12.2651161,47.2453073 18.8201763,50.248968 26.3211742,50.248968 C33.5895831,50.248968 39.2880157,46.4144645 39.2880157,39.4729126 C39.2880157,27.132376 23.3556634,27.4629261 23.3556634,21.3477494 C23.3556634,18.8686237 25.2163761,18.5380737 26.3211742,18.5380737 C27.4841196,18.5380737 29.5774214,18.7409467 29.4029796,23.368648 Z"
|
||||
mask="url(#mask-2)"
|
||||
className="text-deepblue-700 group-focus:text-text-on-inverted"
|
||||
/>
|
||||
<path
|
||||
id="bookmark"
|
||||
fill="#fff"
|
||||
fill="currentColor"
|
||||
fillRule="nonzero"
|
||||
d="M37.1272753,7.62078766 L37.4276823,0.591583333 L43.4674595,0.218291667 L43.7276576,7.37468316 C43.7367132,7.6313391 43.5338374,7.84666553 43.2745216,7.85562813 C43.1634862,7.85946584 43.0546693,7.82423279 42.9673936,7.75618537 L40.6382617,5.94019678 L37.880626,8.0105767 C37.6738999,8.16578288 37.3791917,8.12573637 37.2223772,7.92113026 C37.1563661,7.83500129 37.1227378,7.72879963 37.1272753,7.62078766 Z"
|
||||
mask="url(#mask-2)"
|
||||
className="text-deepblue-700 group-focus:text-text-on-inverted"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const Logo = (props): JSX.Element => (
|
||||
const Logo = (props) => (
|
||||
<svg
|
||||
width="119"
|
||||
height="26"
|
||||
@@ -13,33 +13,33 @@ const Logo = (props): JSX.Element => (
|
||||
>
|
||||
<path
|
||||
d="M56.9682 23.3413L48.1959 1.94542C47.9106 1.30354 47.2687 0.839966 46.5199 0.839966C45.8067 0.839966 45.1292 1.30354 44.8795 1.94542L36.1072 23.3413C36.0359 23.5196 36.0002 23.6623 36.0002 23.7692C36.0002 24.3398 36.4638 24.839 37.07 24.839C37.498 24.839 37.9259 24.5537 38.0685 24.1615L40.1724 18.8838H52.903L55.0069 24.1615C55.1496 24.5537 55.5418 24.839 56.0054 24.839C56.6116 24.839 57.0752 24.3398 57.0752 23.7692C57.0752 23.5909 57.0039 23.4483 56.9682 23.3413ZM40.9213 17.0295L46.5199 2.9439L52.1541 17.0295H40.9213Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M75.0623 23.2343L68.1086 15.3179L74.884 8.93474C75.0623 8.75645 75.1693 8.50683 75.1693 8.29287C75.1693 7.82929 74.8127 7.40137 74.3135 7.40137C74.0995 7.40137 73.8855 7.47269 73.7072 7.61533L63.4729 17.3148V1.76712C63.4729 1.26788 63.045 0.839966 62.5457 0.839966C62.0465 0.839966 61.6186 1.26788 61.6186 1.76712V23.9119C61.6186 24.4111 62.0465 24.839 62.5457 24.839C63.045 24.839 63.4729 24.4111 63.4729 23.9119V19.5614L66.6823 16.5303L73.6003 24.5181C73.7786 24.732 74.0282 24.839 74.3491 24.839C74.884 24.839 75.2763 24.4111 75.2763 23.8762C75.2763 23.6266 75.205 23.4126 75.0623 23.2343Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M79.0353 22.9491C80.747 24.5181 82.6726 25.16 85.1331 25.16C89.448 25.16 91.5876 22.8777 91.5876 20.0963C91.5876 16.4233 88.2712 15.6031 85.3114 14.8543C82.9222 14.2481 80.7113 13.7132 80.7113 11.7519C80.7113 9.96888 82.3517 8.64947 85.0262 8.64947C86.9518 8.64947 88.5565 9.327 89.6619 10.3968C89.7689 10.5038 89.9829 10.6108 90.1612 10.6108C90.6247 10.6108 90.9813 10.2185 90.9813 9.79058C90.9813 9.5053 90.8744 9.327 90.6961 9.1487C89.4123 7.93627 87.5937 7.08043 85.0262 7.08043C81.1392 7.08043 78.8927 9.22002 78.8927 11.8589C78.8927 15.2109 82.0664 15.9597 84.9548 16.6729C87.4154 17.3148 89.7689 17.9567 89.7689 20.1676C89.7689 22.1645 88.0572 23.5909 85.1688 23.5909C83.0649 23.5909 81.3532 22.7708 80.1408 21.6296C79.9981 21.487 79.8198 21.4157 79.6059 21.4157C79.1066 21.4157 78.7144 21.8079 78.7144 22.3072C78.7144 22.5568 78.857 22.8064 79.0353 22.9491Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M95.2069 16.1024C95.2069 21.4157 98.8086 25.16 103.837 25.16C106.404 25.16 108.365 24.3398 110.077 22.8421C110.255 22.6638 110.362 22.4855 110.362 22.2359C110.362 21.7723 110.041 21.4513 109.614 21.4513C109.435 21.4513 109.257 21.487 109.15 21.594C107.688 22.9134 105.941 23.5553 103.979 23.5553C99.914 23.5553 97.4179 20.4529 97.2396 16.7086H110.541C111.254 16.7086 111.646 16.3163 111.646 15.6745C111.646 11.2526 108.758 7.08043 103.516 7.08043C98.7373 7.08043 95.2069 11.11 95.2069 16.1024ZM103.48 8.68513C107.795 8.68513 109.72 12.3224 109.756 15.2465H97.2396C97.3822 12.2511 99.4148 8.68513 103.48 8.68513Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M117.365 24.839C117.865 24.839 118.293 24.4111 118.293 23.9119V1.76712C118.293 1.26788 117.865 0.839966 117.365 0.839966C116.866 0.839966 116.438 1.26788 116.438 1.76712V23.9119C116.438 24.4111 116.866 24.839 117.365 24.839Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M0.292684 8.54331C-0.0977248 8.15267 -0.0975372 7.5195 0.293103 7.1291L5.44967 1.97558C5.47463 1.95063 5.4999 1.92606 5.52546 1.90187L5.52289 1.8993C6.03155 1.39065 6.65771 1.07111 7.314 0.9407C7.59976 0.874273 7.89433 0.839967 8.19243 0.839967L20.12 0.839966C22.2629 0.839967 24 2.5771 24 4.71997V16.6435C24 16.9198 23.9705 17.1931 23.9133 17.4591C23.7914 18.1347 23.4693 18.7813 22.9471 19.3035L22.9458 19.3022C22.9189 19.3309 22.8915 19.3592 22.8636 19.3871L17.7071 24.5435C17.3166 24.934 16.6834 24.934 16.2929 24.5435C15.9024 24.153 15.9024 23.5198 16.2929 23.1293L21.4494 17.9728C21.6986 17.7236 21.8706 17.4116 21.9501 17.074C22.0233 16.6182 21.8843 16.1349 21.5329 15.7835L9.06289 3.31352C8.70098 2.95161 8.20044 2.81283 7.73221 2.89716C7.40619 2.97949 7.10531 3.14852 6.86347 3.39021L1.7069 8.54373C1.31626 8.93414 0.683092 8.93395 0.292684 8.54331ZM11.4178 2.83997L22 13.4222V4.71997C22 3.68167 21.1583 2.83997 20.12 2.83997L11.4178 2.83997Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="M0.292893 24.5435C-0.0976311 24.153 -0.0976311 23.5198 0.292893 23.1293L9.29289 14.1293C9.68342 13.7388 10.3166 13.7388 10.7071 14.1293C11.0976 14.5198 11.0976 15.153 10.7071 15.5435L1.70711 24.5435C1.31658 24.934 0.683417 24.934 0.292893 24.5435Z"
|
||||
fill="#004367"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const NAVLogoDark = (props): JSX.Element => (
|
||||
const NAVLogoDark = (props) => (
|
||||
<svg
|
||||
width="3.25em"
|
||||
height="3.25em"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
const NAVLogoWhite = (props): JSX.Element => (
|
||||
const NAVLogoWhite = (props) => (
|
||||
<svg
|
||||
width="3.25em"
|
||||
height="3.25em"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
export * from "./assets";
|
||||
export { default as LayoutPicker } from "./layout/TemplatePicker";
|
||||
export { default as Accordion } from "./sanity-modules/Accordion";
|
||||
export { default as Alert } from "./sanity-modules/Alert";
|
||||
export { default as Bilde } from "./sanity-modules/bilde/Bilde";
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import Error from "next/error";
|
||||
import React from "react";
|
||||
import { SanityT } from "@/lib";
|
||||
import AkselArtikkelTemplate from "./page-templates/AkselArtikkel";
|
||||
import AkselPrinsippTemplate from "./page-templates/AkselPrinsipp";
|
||||
|
||||
type aksel_artikkel = {
|
||||
aksel_artikkel: (props: {
|
||||
data: SanityT.Schema.aksel_artikkel;
|
||||
title: string;
|
||||
}) => JSX.Element;
|
||||
};
|
||||
|
||||
type aksel_prinsipp = {
|
||||
aksel_prinsipp: (props: {
|
||||
data: SanityT.Schema.aksel_prinsipp;
|
||||
title: string;
|
||||
}) => JSX.Element;
|
||||
};
|
||||
|
||||
type templateT = aksel_artikkel | aksel_prinsipp;
|
||||
|
||||
const templates: templateT = {
|
||||
aksel_artikkel: (props) => <AkselArtikkelTemplate {...props} />,
|
||||
aksel_prinsipp: (props) => <AkselPrinsippTemplate {...props} />,
|
||||
};
|
||||
|
||||
const TemplatePicker = ({
|
||||
data,
|
||||
title,
|
||||
}: {
|
||||
data: SanityT.Schema.aksel_artikkel | SanityT.Schema.aksel_prinsipp;
|
||||
title: string;
|
||||
}): JSX.Element => {
|
||||
if (!Object.keys(templates).includes(data?._type)) {
|
||||
console.warn(
|
||||
`${data?._type} does not have a valid template to use, please create one.`
|
||||
);
|
||||
|
||||
return (
|
||||
<Error
|
||||
statusCode={404}
|
||||
title="Sanity-side mangler template, kontakt utvikler"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const Template = templates[data?._type];
|
||||
|
||||
return <Template data={data} title={title} />;
|
||||
};
|
||||
|
||||
export default TemplatePicker;
|
||||
+7
-3
@@ -1,4 +1,4 @@
|
||||
import { PageTypeT, SidebarT, urlFor } from "@/lib";
|
||||
import { urlFor } from "@/lib";
|
||||
import { Detail, Heading, Link } from "@navikt/ds-react";
|
||||
import Footer from "components/layout/footer/Footer";
|
||||
import { Header } from "components/layout/header/Header";
|
||||
@@ -10,6 +10,7 @@ import NextLink from "next/link";
|
||||
import { capitalize } from "@/utils";
|
||||
import Image from "next/legacy/image";
|
||||
import { TableOfContentsv2 } from "components/website-modules/TOCv2";
|
||||
import { AkselSidebarT } from "@/types";
|
||||
|
||||
const HeaderCube = ({ ...props }) => (
|
||||
<svg
|
||||
@@ -59,8 +60,11 @@ export const WithSidebar = ({
|
||||
footer,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
sidebar: SidebarT;
|
||||
pageType: PageTypeT;
|
||||
sidebar: AkselSidebarT;
|
||||
pageType: {
|
||||
type: "Komponenter" | "Grunnleggende";
|
||||
title: string;
|
||||
};
|
||||
pageProps: any;
|
||||
intro?: ReactNode;
|
||||
footer?: ReactNode;
|
||||
@@ -1,7 +1,8 @@
|
||||
import { BodyShort, Heading, Link } from "@navikt/ds-react";
|
||||
|
||||
import NextLink from "next/link";
|
||||
import { EditButton, ScrollTop } from "../..";
|
||||
import { FigmaIcon, GithubIcon, SlackIcon } from "components/assets";
|
||||
import Logo from "components/assets/Logo";
|
||||
import { logNav } from "components/website-modules/utils/amplitude";
|
||||
import { EditButton } from "../..";
|
||||
import FooterForm from "./FooterForm";
|
||||
|
||||
const Footer = () => {
|
||||
@@ -12,164 +13,116 @@ const Footer = () => {
|
||||
data-theme="dark"
|
||||
className="toc-ignore text-text-on-inverted bg-deepblue-800 relative flex w-full justify-center"
|
||||
>
|
||||
<div className="relative z-10 mx-auto grid w-full max-w-screen-2xl gap-16 px-4 pt-12 pb-16 md:px-6">
|
||||
<div className="grid gap-12 xl:grid-cols-3 xl:gap-6">
|
||||
<ScrollTop />
|
||||
<div>
|
||||
<Heading level="2" size="small">
|
||||
Aksel
|
||||
</Heading>
|
||||
<BodyShort as="ul" className="mt-5 grid gap-2">
|
||||
<li>
|
||||
<NextLink
|
||||
href="/god-praksis/artikler/om-aksel"
|
||||
passHref
|
||||
legacyBehavior
|
||||
>
|
||||
<Link className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200">
|
||||
Om Aksel
|
||||
</Link>
|
||||
</NextLink>
|
||||
</li>
|
||||
<li>
|
||||
<NextLink
|
||||
href="/god-praksis/artikler/skriv-for-aksel"
|
||||
passHref
|
||||
legacyBehavior
|
||||
>
|
||||
<Link className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200">
|
||||
Skriv for Aksel
|
||||
</Link>
|
||||
</NextLink>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200"
|
||||
href="https://nav-it.slack.com/archives/C7NE7A8UF"
|
||||
>
|
||||
#Aksel-designsystemet på Slack
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200"
|
||||
href="/prinsipper/brukeropplevelse"
|
||||
>
|
||||
Prinsipper for brukeropplevelse
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200"
|
||||
href="/side/tilgjengelighetserklaring-for-aksel"
|
||||
>
|
||||
Tilgjengelighet
|
||||
</Link>
|
||||
</li>
|
||||
{/* <li>
|
||||
<Link
|
||||
className="text-text-on-inverted focus:shadow-focus focus:text-text-default focus:bg-blue-200 focus:shadow-blue-200"
|
||||
href="https://nav-it.slack.com/archives/C7NE7A8UF"
|
||||
>
|
||||
Designsystemet på Slack
|
||||
</Link>
|
||||
</li> */}
|
||||
</BodyShort>
|
||||
</div>
|
||||
<FooterForm />
|
||||
</div>
|
||||
<div className="grid xl:grid-cols-3 xl:gap-6">
|
||||
<div className="mb-4 grid gap-2 xl:mb-0">
|
||||
<svg
|
||||
width="64"
|
||||
height="20"
|
||||
viewBox="0 0 64 20"
|
||||
fill="none"
|
||||
aria-hidden
|
||||
focusable="false"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clipPath="url(#clip0_2259_53938)">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M63.4798 1H56.8198C56.8198 1 56.3608 1 56.1988 1.406L52.5138 12.693L48.8318 1.406C48.6688 1.001 48.2078 1.001 48.2078 1.001H35.4038C35.2694 1.00203 35.1407 1.05569 35.0454 1.15046C34.9501 1.24523 34.8956 1.37359 34.8938 1.508V5.341C34.8938 2.301 31.6608 1.001 29.7668 1.001C25.5268 1.001 22.6888 3.795 21.8048 8.044C21.7568 5.225 21.5228 4.215 20.7638 3.181C20.4148 2.674 19.9118 2.249 19.3638 1.896C18.2338 1.234 17.2188 1.001 15.0398 1.001H12.4798C12.4798 1.001 12.0178 1.001 11.8548 1.406L9.52582 7.18V1.508C9.52452 1.37411 9.47082 1.24606 9.37624 1.15128C9.28165 1.05651 9.15371 1.00256 9.01982 1.001H3.09682C3.09682 1.001 2.63982 1.001 2.47282 1.406L0.0528186 7.41C0.0528186 7.41 -0.189181 8.01 0.362819 8.01H2.63982V19.45C2.63982 19.734 2.86282 19.96 3.14782 19.96H9.01782C9.08466 19.9599 9.15082 19.9466 9.21253 19.9209C9.27423 19.8952 9.33027 19.8576 9.37744 19.8102C9.42462 19.7629 9.462 19.7067 9.48746 19.6449C9.51291 19.5831 9.52595 19.5168 9.52582 19.45V8.01H11.8148C13.1278 8.01 13.4048 8.046 13.9158 8.284C14.2238 8.401 14.5008 8.636 14.6528 8.907C14.9628 9.49 15.0398 10.19 15.0398 12.255V19.45C15.0398 19.734 15.2678 19.96 15.5498 19.96H21.1758C21.1758 19.96 21.8118 19.96 22.0628 19.33L23.3098 16.247C24.9678 18.571 27.6968 19.959 31.0888 19.959H31.8298C31.8298 19.959 32.4698 19.959 32.7228 19.331L34.8948 13.95V19.45C34.8948 19.5853 34.9485 19.715 35.0442 19.8106C35.1398 19.9063 35.2696 19.96 35.4048 19.96H41.1478C41.1478 19.96 41.7818 19.96 42.0358 19.33C42.0358 19.33 44.3328 13.625 44.3418 13.582H44.3458C44.4338 13.107 43.8348 13.107 43.8348 13.107H41.7848V3.316L48.2348 19.331C48.4858 19.959 49.1208 19.959 49.1208 19.959H55.9068C55.9068 19.959 56.5448 19.959 56.7968 19.331L63.9478 1.615C64.1948 1.001 63.4788 1.001 63.4788 1.001L63.4798 1ZM34.8928 13.108H31.0348C30.2962 13.108 29.5878 12.8146 29.0655 12.2923C28.5432 11.77 28.2498 11.0616 28.2498 10.323C28.2498 9.58437 28.5432 8.876 29.0655 8.35371C29.5878 7.83142 30.2962 7.538 31.0348 7.538H32.1138C32.8517 7.54012 33.5586 7.83465 34.0797 8.35706C34.6008 8.87946 34.8936 9.58713 34.8938 10.325V13.108H34.8928Z"
|
||||
fill="white"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2259_53938">
|
||||
<rect width="63.9997" height="20" fill="white" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
Arbeids- og velferdsetaten
|
||||
</div>
|
||||
<span className="mb-1 self-end xl:mb-0" />
|
||||
<div className="hidden self-end xl:block">
|
||||
<p>© {new Date().getFullYear()} NAV</p>
|
||||
<NextLink
|
||||
href="/side/personvernerklaering"
|
||||
className="focus:bg-border-focus-on-inverted focus:text-text-default focus:ring-border-focus-on-inverted outline-none hover:underline focus:no-underline focus:ring"
|
||||
>
|
||||
Personvernerklæring og informasjonskapsler
|
||||
</NextLink>
|
||||
</div>
|
||||
<div className="block self-end xl:hidden">
|
||||
© {new Date().getFullYear()} NAV |{" "}
|
||||
<NextLink
|
||||
href="/side/personvernerklaering"
|
||||
className="focus:bg-border-focus-on-inverted focus:ring-border-focus-on-inverted outline-none hover:underline focus:no-underline focus:ring"
|
||||
>
|
||||
Personvernerklæring og informasjonskapsler
|
||||
</NextLink>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative z-10 mx-auto grid w-full max-w-screen-2xl gap-12 px-4 pt-12 pb-16 md:grid-cols-2 md:px-6 lg:grid-cols-4 xl:grid-cols-5 xl:gap-6">
|
||||
<LogoBlock />
|
||||
<Snarveier />
|
||||
<SideLenker />
|
||||
<Kontakt />
|
||||
<FooterForm />
|
||||
</div>
|
||||
|
||||
<EditButton />
|
||||
<svg
|
||||
width="548"
|
||||
height="422"
|
||||
viewBox="0 0 548 422"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="absolute right-0 bottom-0 z-0"
|
||||
aria-hidden
|
||||
focusable={false}
|
||||
>
|
||||
<path
|
||||
d="M664.991 350.212L431.631 116.852L664.64 116.852L898 350.212L664.991 350.212Z"
|
||||
stroke="#004367"
|
||||
strokeWidth="2.9687"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M625.456 156.037L392.097 389.396L625.456 622.756L858.816 389.396L625.456 156.037Z"
|
||||
stroke="#004367"
|
||||
strokeWidth="2.9687"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M353.262 195.222L119.903 428.581H352.912L586.271 195.222H353.262Z"
|
||||
stroke="#004367"
|
||||
strokeWidth="2.9687"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M314.076 234.407L80.7169 467.767L314.076 701.126L547.436 467.767L314.076 234.407Z"
|
||||
stroke="#004367"
|
||||
strokeWidth="2.9687"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M508.251 506.951L274.892 740.31H507.901L741.261 506.951H508.251Z"
|
||||
stroke="#004367"
|
||||
strokeWidth="2.9687"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
function LogoBlock() {
|
||||
return (
|
||||
<div>
|
||||
<Logo className="fill-white" />
|
||||
<p className="mt-4">© {new Date().getFullYear()} NAV</p>
|
||||
<p>Arbeids- og velferdsetaten</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Snarveier() {
|
||||
return (
|
||||
<div>
|
||||
<Heading level="2" size="xsmall">
|
||||
Snarveier
|
||||
</Heading>
|
||||
<BodyShort as="ul" className="mt-3 grid gap-3">
|
||||
<FooterLink href="/god-praksis/artikler/om-aksel">
|
||||
Hva er Aksel?
|
||||
</FooterLink>
|
||||
<FooterLink href="/god-praksis/artikler/skriv-for-aksel">
|
||||
Skriv for Aksel
|
||||
</FooterLink>
|
||||
<FooterLink href="/prinsipper/brukeropplevelse">
|
||||
Prinsipper for brukeropplevelse
|
||||
</FooterLink>
|
||||
<FooterLink href="https://identitet.nav.no/">Identitet</FooterLink>
|
||||
<FooterLink href="https://sikkerhet.nav.no/">
|
||||
Security Playbook
|
||||
</FooterLink>
|
||||
<FooterLink href="https://etterlevelse.intern.nav.no/">
|
||||
Etterlevelse
|
||||
</FooterLink>
|
||||
</BodyShort>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Kontakt() {
|
||||
return (
|
||||
<div>
|
||||
<Heading level="2" size="xsmall">
|
||||
Finn oss
|
||||
</Heading>
|
||||
<BodyShort as="ul" className="mt-3 grid gap-3">
|
||||
<FooterLink href="https://www.figma.com/@nav_aksel">
|
||||
<FigmaIcon />
|
||||
Figma
|
||||
</FooterLink>
|
||||
<FooterLink href="https://github.com/navikt/aksel">
|
||||
<GithubIcon />
|
||||
Github
|
||||
</FooterLink>
|
||||
<FooterLink href="https://nav-it.slack.com/archives/C7NE7A8UF">
|
||||
<SlackIcon />
|
||||
Slack
|
||||
</FooterLink>
|
||||
</BodyShort>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function SideLenker() {
|
||||
return (
|
||||
<div>
|
||||
<Heading level="2" size="xsmall">
|
||||
Om nettstedet
|
||||
</Heading>
|
||||
<BodyShort as="ul" className="mt-3 grid gap-3">
|
||||
<FooterLink href="/side/personvernerklaering">
|
||||
Personvernserklæring
|
||||
</FooterLink>
|
||||
<FooterLink href="/side/tilgjengelighetserklaring-for-aksel">
|
||||
Tilgjengelighetserklæring
|
||||
</FooterLink>
|
||||
</BodyShort>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterLink({ children, href }) {
|
||||
return (
|
||||
<li>
|
||||
<Link
|
||||
className="text-text-on-inverted focus:shadow-focus focus:text-text-default flex w-fit items-center gap-1 no-underline hover:underline focus:bg-blue-200 focus:shadow-blue-200"
|
||||
href={href}
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"footer",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FeedbackT } from "@/lib";
|
||||
import { IdContext } from "@/utils";
|
||||
import { Button, Heading, Label, Textarea } from "@navikt/ds-react";
|
||||
import { Button, Label, Textarea } from "@navikt/ds-react";
|
||||
import { IdContext } from "components/website-modules/utils/contexts/id-context";
|
||||
import { FeedbackT } from "@/types";
|
||||
import { useRouter } from "next/router";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
|
||||
@@ -55,7 +55,10 @@ const FooterForm = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex w-full max-w-md flex-col gap-8" data-theme="dark">
|
||||
<div
|
||||
className="flex w-full max-w-md flex-col lg:col-span-2 xl:col-span-1"
|
||||
data-theme="dark"
|
||||
>
|
||||
<div aria-live="polite">
|
||||
{sent.status && (
|
||||
<Label spacing as="p">
|
||||
@@ -65,15 +68,12 @@ const FooterForm = () => {
|
||||
</div>
|
||||
{!sent.status && (
|
||||
<form onSubmit={(e) => handleSubmit(e)} className="w-full">
|
||||
<div className="mb-4 flex flex-col gap-4">
|
||||
<Heading level="2" size="small">
|
||||
Gi en tilbakemelding
|
||||
</Heading>
|
||||
<div className="mb-3 flex flex-col gap-4">
|
||||
<Textarea
|
||||
className="textarea-override"
|
||||
error={contentError.content}
|
||||
autoComplete="off"
|
||||
label="Melding"
|
||||
label="Gi oss en tilbakemelding"
|
||||
value={contactForm.content}
|
||||
onChange={(e) => {
|
||||
setContactForm({
|
||||
@@ -85,13 +85,14 @@ const FooterForm = () => {
|
||||
e.target.value.trim().length !== 0 &&
|
||||
setContentError({ ...contentError, content: "" });
|
||||
}}
|
||||
description="Ikke skriv inn navn eller andre personopplysninger"
|
||||
description="Ikke skriv inn personopplysninger"
|
||||
minRows={2}
|
||||
/>
|
||||
</div>
|
||||
{contactForm.hasWritten && <Button>Send melding</Button>}
|
||||
<Button size="small">Send melding</Button>
|
||||
<style>{`.textarea-override {
|
||||
--ac-textarea-bg: var(--a-deepblue-800);
|
||||
--ac-textarea-bg: var(--a-surface-default);
|
||||
--ac-textarea-text: var(--a-text-default);
|
||||
}`}</style>
|
||||
</form>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import Footer from "./Footer";
|
||||
import { Meta } from "@storybook/react";
|
||||
import { NextDecorator } from "../../StoryDecorator";
|
||||
|
||||
const MetaData: Meta = {
|
||||
component: Footer,
|
||||
tags: ["autodocs"],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<NextDecorator>
|
||||
<Story />
|
||||
</NextDecorator>
|
||||
),
|
||||
],
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
};
|
||||
|
||||
export default MetaData;
|
||||
|
||||
export const FooterDemo = {
|
||||
render: () => <Footer />,
|
||||
nextRouter: {
|
||||
path: "/profile/[id]",
|
||||
asPath: "/profile/lifeiscontent",
|
||||
query: {
|
||||
id: "lifeiscontent",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -72,7 +72,7 @@ export const Header = ({
|
||||
}
|
||||
className="focus-visible:shadow-focus grid h-full place-items-center rounded px-2 focus:outline-none"
|
||||
>
|
||||
<Logo />
|
||||
<Logo className="text-deepblue-800" />
|
||||
<span className="sr-only">Aksel</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Label } from "@navikt/ds-react";
|
||||
import { GroupedHits, SearchHit, options } from "lib/types/search";
|
||||
import { GroupedHitsT, SearchHitT, searchOptions } from "@/types";
|
||||
import { Hit, IconHit, IconPageHit } from "./Hit";
|
||||
import React from "react";
|
||||
|
||||
@@ -9,7 +9,7 @@ export function Group({
|
||||
startIndex,
|
||||
logSuccess,
|
||||
}: {
|
||||
groups: GroupedHits;
|
||||
groups: GroupedHitsT;
|
||||
query: string;
|
||||
startIndex: number;
|
||||
logSuccess: (index: number, url: string) => void;
|
||||
@@ -21,7 +21,7 @@ export function Group({
|
||||
return (
|
||||
<>
|
||||
{Object.entries(groups)
|
||||
.sort((a, b) => options[a[0]].index - options[b[0]].index)
|
||||
.sort((a, b) => searchOptions[a[0]].index - searchOptions[b[0]].index)
|
||||
.map(([key, val], index, arr) => {
|
||||
const prev = arr.slice(0, index);
|
||||
const total =
|
||||
@@ -32,7 +32,7 @@ export function Group({
|
||||
logSuccess={logSuccess}
|
||||
startIndex={total}
|
||||
key={key}
|
||||
heading={`${options[key].display} (${val.length})`}
|
||||
heading={`${searchOptions[key].display} (${val.length})`}
|
||||
hits={val}
|
||||
query={query}
|
||||
/>
|
||||
@@ -50,7 +50,7 @@ export function GroupComponent({
|
||||
logSuccess,
|
||||
}: {
|
||||
heading: React.ReactNode;
|
||||
hits: SearchHit[];
|
||||
hits: SearchHitT[];
|
||||
query: string;
|
||||
startIndex: number;
|
||||
logSuccess: (index: number, url: string) => void;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Tag } from "@navikt/ds-react";
|
||||
import cl from "classnames";
|
||||
import Image from "next/legacy/image";
|
||||
import { StatusTag } from "components/website-modules/StatusTag";
|
||||
import { SearchHit } from "lib/types/search";
|
||||
import { SearchHitT } from "@/types";
|
||||
import NextLink from "next/link";
|
||||
|
||||
export function Hit({
|
||||
@@ -13,7 +13,7 @@ export function Hit({
|
||||
index,
|
||||
logSuccess,
|
||||
}: {
|
||||
hit: SearchHit;
|
||||
hit: SearchHitT;
|
||||
query: string;
|
||||
index: number;
|
||||
logSuccess: (index: number, url: string) => void;
|
||||
@@ -81,7 +81,7 @@ export function IconHit({
|
||||
index,
|
||||
logSuccess,
|
||||
}: {
|
||||
hit: SearchHit;
|
||||
hit: SearchHitT;
|
||||
query: string;
|
||||
index: number;
|
||||
logSuccess: (index: number, url: string) => void;
|
||||
@@ -139,7 +139,7 @@ export function IconPageHit({
|
||||
index,
|
||||
logSuccess,
|
||||
}: {
|
||||
hit: SearchHit;
|
||||
hit: SearchHitT;
|
||||
query: string;
|
||||
index: number;
|
||||
logSuccess: (index: number, url: string) => void;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Search,
|
||||
} from "@navikt/ds-react";
|
||||
import { ChangeLogIconOutline } from "components/assets";
|
||||
import { options, SearchResults } from "lib/types/search";
|
||||
import { searchOptions, SearchResultsT } from "@/types";
|
||||
import { useRouter } from "next/router";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import ReactModal from "react-modal";
|
||||
@@ -24,10 +24,10 @@ import styles from "../header.module.css";
|
||||
|
||||
*/
|
||||
export const GlobalSearch = () => {
|
||||
const [results, setResults] = useState<SearchResults>(null);
|
||||
const [results, setResults] = useState<SearchResultsT>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [activeTags, setTags] = useState<Array<keyof typeof options>>([]);
|
||||
const [activeTags, setTags] = useState<Array<keyof typeof searchOptions>>([]);
|
||||
const [os, setOs] = useState<"mac" | "windows">("windows");
|
||||
const inputRef = useRef(null);
|
||||
|
||||
@@ -104,7 +104,6 @@ export const GlobalSearch = () => {
|
||||
)
|
||||
.then((x) => x.json())
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
setResults(res);
|
||||
logSearchAttempt(res?.hits?.totalHits ?? 0, "standard");
|
||||
setLoading(false);
|
||||
@@ -193,7 +192,7 @@ export const GlobalSearch = () => {
|
||||
<div className="z-[1050] mr-4 ml-auto flex justify-center lg:mr-0 lg:ml-0">
|
||||
<Button
|
||||
variant="primary"
|
||||
className="hover:bg-deepblue-600 bg-deepblue-500 focus-visible:shadow-focus-gap h-11 focus:shadow-none"
|
||||
className="hover:bg-deepblue-700 bg-deepblue-600 focus-visible:shadow-focus-gap h-11 focus:shadow-none"
|
||||
aria-keyshortcuts="Control+b"
|
||||
icon={
|
||||
<SearchIcon
|
||||
@@ -224,7 +223,7 @@ export const GlobalSearch = () => {
|
||||
</button>
|
||||
<div className="search-grid-filter mt-8">
|
||||
<CheckboxGroup legend="Filter" onChange={setTags}>
|
||||
{Object.entries(options)
|
||||
{Object.entries(searchOptions)
|
||||
.filter((x) => !x[1].hidden)
|
||||
.map(([key, val]) => (
|
||||
<Checkbox
|
||||
@@ -285,7 +284,7 @@ export const GlobalSearch = () => {
|
||||
{`${results?.totalHits} treff på "${query}"${
|
||||
activeTags.length > 0
|
||||
? ` i ${activeTags
|
||||
.map((x) => options[x].display.toLowerCase())
|
||||
.map((x) => searchOptions[x].display.toLowerCase())
|
||||
.join(", ")}`
|
||||
: ""
|
||||
}`}
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
import { SanityT, urlFor } from "@/lib";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { Next } from "@navikt/ds-icons";
|
||||
import { BodyShort, Detail, Heading, Ingress, Label } from "@navikt/ds-react";
|
||||
import ArtikkelCard from "components/sanity-modules/cards/ArtikkelCard";
|
||||
import Head from "next/head";
|
||||
import NextLink from "next/link";
|
||||
|
||||
import {
|
||||
abbrName,
|
||||
BreadCrumbs,
|
||||
dateStr,
|
||||
Feedback,
|
||||
TableOfContents,
|
||||
} from "../..";
|
||||
import { NoSidebarLayout } from "./wrappers/NoSidebar";
|
||||
|
||||
const AkselArtikkelTemplate = ({
|
||||
data,
|
||||
title,
|
||||
}: {
|
||||
data: SanityT.Schema.aksel_artikkel;
|
||||
title: string;
|
||||
}): JSX.Element => {
|
||||
if (!data.content || !data.heading) {
|
||||
console.warn(
|
||||
`Artikkelen har ikke ${
|
||||
!data.content ? "innhold" : "overskrift"
|
||||
}, så den kan ikke vises.`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const date = data?.updateInfo?.lastVerified
|
||||
? data?.updateInfo?.lastVerified
|
||||
: data?.publishedAt
|
||||
? data.publishedAt
|
||||
: data._updatedAt;
|
||||
|
||||
const authors = (data?.contributors as any)?.map((x) => x?.title) ?? [];
|
||||
|
||||
const hasTema = "tema" in data && data.tema && data?.tema.length > 0;
|
||||
|
||||
const aside = data?.relevante_artikler?.length > 0 && (
|
||||
<aside
|
||||
className="overflow-x-clip py-8"
|
||||
aria-labelledby="relevante-artikler-aside"
|
||||
>
|
||||
<div className="relativept-12 pb-16">
|
||||
<div className="dynamic-wrapper">
|
||||
<Heading
|
||||
level="2"
|
||||
size="medium"
|
||||
className="text-deepblue-700 px-4"
|
||||
id="relevante-artikler-aside"
|
||||
>
|
||||
{data?.relevante_artikler?.length === 1
|
||||
? `Les også`
|
||||
: `Relevante artikler`}
|
||||
</Heading>
|
||||
<div className="card-grid-3-1 mt-6 px-4">
|
||||
{data.relevante_artikler.map((x: any) =>
|
||||
x && x?._id ? <ArtikkelCard level="3" {...x} key={x._id} /> : null
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
|
||||
const filteredTema =
|
||||
hasTema && data?.tema?.filter((x: any) => x?.title && x?.slug);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{`${data?.heading} - ${title}`}</title>
|
||||
<meta
|
||||
property="og:title"
|
||||
content={`${data?.heading} - ${title}`}
|
||||
key="ogtitle"
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content={data?.seo?.meta ?? data?.ingress}
|
||||
key="desc"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content={data?.seo?.meta ?? data?.ingress}
|
||||
key="ogdesc"
|
||||
/>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content={
|
||||
data?.seo?.image
|
||||
? urlFor(data?.seo?.image)
|
||||
.width(1200)
|
||||
.height(630)
|
||||
.fit("crop")
|
||||
.quality(100)
|
||||
.url()
|
||||
: hasTema && (data.tema[0] as any)?.seo?.image
|
||||
? urlFor((data.tema[0] as any)?.seo?.image)
|
||||
.width(1200)
|
||||
.height(630)
|
||||
.fit("crop")
|
||||
.quality(100)
|
||||
.url()
|
||||
: ""
|
||||
}
|
||||
key="ogimage"
|
||||
/>
|
||||
</Head>
|
||||
<NoSidebarLayout aside={aside}>
|
||||
<div className="mx-auto mb-16 max-w-prose lg:ml-0">
|
||||
<BreadCrumbs auto />
|
||||
<Heading
|
||||
level="1"
|
||||
size="large"
|
||||
className="text-deepblue-800 mt-4 md:text-5xl"
|
||||
>
|
||||
{data.heading}
|
||||
</Heading>
|
||||
{data?.ingress && (
|
||||
<Ingress className="override-text-700 mt-4 text-2xl">
|
||||
{data?.ingress}
|
||||
</Ingress>
|
||||
)}
|
||||
|
||||
<div className="mt-6 inline-flex flex-wrap items-center gap-2 text-base">
|
||||
<Detail uppercase as="span">
|
||||
{dateStr(date)}
|
||||
</Detail>
|
||||
{authors?.length > 0 && (
|
||||
<>
|
||||
<span className="bg-deepblue-700 h-2 w-2 rotate-45 rounded-[1px] opacity-25" />
|
||||
<BodyShort
|
||||
size="small"
|
||||
as="div"
|
||||
className="flex flex-wrap gap-1"
|
||||
>
|
||||
<address className="not-italic">{authors?.[0]}</address>
|
||||
</BodyShort>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{hasTema && (
|
||||
<div className="mt-8 flex flex-wrap gap-2">
|
||||
{filteredTema.map(({ title, slug }: any) => (
|
||||
<span key={title}>
|
||||
<NextLink
|
||||
key={title}
|
||||
href={`/god-praksis/${slug.current}`}
|
||||
passHref
|
||||
legacyBehavior
|
||||
>
|
||||
<BodyShort
|
||||
size="small"
|
||||
as="a"
|
||||
className="min-h-8 text-deepblue-800 focus-visible:shadow-focus flex items-center justify-center gap-[2px] rounded-full bg-gray-200 pl-4 pr-1 capitalize no-underline hover:underline focus:outline-none"
|
||||
>
|
||||
{title}
|
||||
<Next aria-hidden />
|
||||
</BodyShort>
|
||||
</NextLink>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="relative mx-auto mt-4 max-w-prose lg:ml-0 lg:grid lg:max-w-none lg:grid-flow-row-dense lg:grid-cols-3 lg:items-start lg:gap-x-12">
|
||||
<TableOfContents
|
||||
changedState={data?.content ?? []}
|
||||
hideToc={false}
|
||||
aksel
|
||||
/>
|
||||
<div className="max-w-prose lg:col-span-2 lg:col-start-1">
|
||||
<SanityBlockContent blocks={data?.content ?? []} variant="aksel" />
|
||||
<div className="mt-12">
|
||||
{authors?.length > 0 && (
|
||||
<Label className="text-deepblue-700 mb-2" as="p">
|
||||
Bidragsytere
|
||||
</Label>
|
||||
)}
|
||||
{authors?.length > 0 && (
|
||||
<BodyShort
|
||||
as="div"
|
||||
className="text-text-subtle mb-1 flex flex-wrap gap-1"
|
||||
>
|
||||
{authors.map(abbrName).map((x, y) => (
|
||||
<address className="not-italic" key={x}>
|
||||
{x}
|
||||
{y !== authors.length - 1 && ", "}
|
||||
</address>
|
||||
))}
|
||||
</BodyShort>
|
||||
)}
|
||||
<BodyShort as="span" className="text-text-subtle">
|
||||
Publisert: {dateStr(data?.publishedAt ?? data?._updatedAt)}
|
||||
</BodyShort>
|
||||
</div>
|
||||
<div className="mt-12 md:mt-16">
|
||||
<Feedback akselFeedback docId={data?._id} docType={data?._type} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NoSidebarLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AkselArtikkelTemplate;
|
||||
@@ -1,189 +0,0 @@
|
||||
import { SanityT, urlFor } from "@/lib";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { BodyShort, Heading, Ingress, Label } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
import { Header } from "components/layout/header/Header";
|
||||
import Head from "next/head";
|
||||
import { Footer } from "..";
|
||||
import {
|
||||
abbrName,
|
||||
Bilde,
|
||||
BreadCrumbs,
|
||||
dateStr,
|
||||
Feedback,
|
||||
TableOfContents,
|
||||
} from "../..";
|
||||
|
||||
const AkselPrinsippTemplate = ({
|
||||
data,
|
||||
title,
|
||||
}: {
|
||||
data: SanityT.Schema.aksel_prinsipp;
|
||||
title: string;
|
||||
}): JSX.Element => {
|
||||
if (!data.content || !data.heading) {
|
||||
console.warn(
|
||||
`Artikkelen har ikke ${
|
||||
!data.content ? "innhold" : "overskrift"
|
||||
}, så den kan ikke vises.`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const authors = (data?.contributors as any)?.map((x) => x?.title) ?? [];
|
||||
const mainPage = data?.prinsipp?.hovedside;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{`${data?.heading} - Prinsipp - ${title}`}</title>
|
||||
<meta
|
||||
property="og:title"
|
||||
content={`${data?.heading} - ${title}`}
|
||||
key="ogtitle"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content={data?.seo?.meta ?? data?.ingress}
|
||||
key="ogdesc"
|
||||
/>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content={
|
||||
data?.seo?.image
|
||||
? urlFor(data?.seo?.image)
|
||||
.width(1200)
|
||||
.height(630)
|
||||
.fit("crop")
|
||||
.quality(100)
|
||||
.url()
|
||||
: ""
|
||||
}
|
||||
key="ogimage"
|
||||
/>
|
||||
</Head>
|
||||
<Header variant={mainPage ? "default" : "subtle"} />
|
||||
<main
|
||||
tabIndex={-1}
|
||||
id="hovedinnhold"
|
||||
className={cl("aksel-artikkel pt-4 focus:outline-none", {
|
||||
"bg-white": mainPage,
|
||||
"bg-surface-subtle": !mainPage,
|
||||
})}
|
||||
>
|
||||
<article className="overflow-x-clip">
|
||||
<div
|
||||
className={cl("max-w-aksel mx-auto px-4 sm:w-[90%]", {
|
||||
"pb-32": mainPage,
|
||||
})}
|
||||
>
|
||||
<div className="pt-12">
|
||||
<div className="mx-auto mb-16 max-w-prose lg:ml-0 ">
|
||||
{!mainPage && (
|
||||
<BreadCrumbs
|
||||
text={`Prinsipper for ${data?.prinsipp?.prinsippvalg}`}
|
||||
href={`/prinsipper/${data?.prinsipp?.prinsippvalg}`}
|
||||
/>
|
||||
)}
|
||||
<Heading
|
||||
level="1"
|
||||
size="large"
|
||||
className="text-deepblue-700 mt-4 md:text-5xl"
|
||||
>
|
||||
{data.heading}
|
||||
</Heading>
|
||||
{data?.ingress && (
|
||||
<Ingress className="override-text-700 mt-5 text-2xl">
|
||||
{data?.ingress}
|
||||
</Ingress>
|
||||
)}
|
||||
<div className="mt-6 flex gap-3 text-base">
|
||||
<BodyShort
|
||||
size="small"
|
||||
as="span"
|
||||
className="text-text-subtle "
|
||||
>
|
||||
{dateStr(data?._updatedAt)}
|
||||
</BodyShort>
|
||||
{authors?.length > 0 && (
|
||||
<BodyShort
|
||||
size="small"
|
||||
as="div"
|
||||
className="flex flex-wrap gap-1"
|
||||
>
|
||||
<address className="not-italic">{authors[0]}</address>
|
||||
</BodyShort>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={cl("pt-32", {
|
||||
"bg-gray-100": mainPage,
|
||||
})}
|
||||
>
|
||||
<div className="max-w-aksel mx-auto px-4 sm:w-[90%]">
|
||||
<div className="pb-16 md:pb-32">
|
||||
<div className="relative mx-auto mt-4 max-w-prose lg:ml-0 lg:grid lg:max-w-none lg:grid-flow-row-dense lg:grid-cols-3 lg:items-start lg:gap-x-12">
|
||||
<TableOfContents
|
||||
changedState={data?.content ?? []}
|
||||
hideToc={false}
|
||||
aksel
|
||||
/>
|
||||
<div className="max-w-prose lg:col-span-2 lg:col-start-1">
|
||||
{data?.hero_bilde && (
|
||||
<Bilde
|
||||
node={data.hero_bilde as any}
|
||||
className="-mt-36 mb-10 sm:-mt-72"
|
||||
/>
|
||||
)}
|
||||
<SanityBlockContent
|
||||
blocks={data?.content ?? []}
|
||||
variant="aksel"
|
||||
/>
|
||||
<div className="mt-12">
|
||||
{authors?.length > 0 && (
|
||||
<Label className="text-deepblue-700 mb-2" as="p">
|
||||
Bidragsytere
|
||||
</Label>
|
||||
)}
|
||||
{authors?.length > 0 && (
|
||||
<BodyShort
|
||||
as="div"
|
||||
className="text-text-subtle mb-1 flex flex-wrap gap-1"
|
||||
>
|
||||
{authors.map(abbrName).map((x, y) => (
|
||||
<address className="not-italic" key={x}>
|
||||
{x}
|
||||
{y !== authors.length - 1 && ", "}
|
||||
</address>
|
||||
))}
|
||||
</BodyShort>
|
||||
)}
|
||||
<BodyShort as="span" className="text-text-subtle ">
|
||||
Publisert:{" "}
|
||||
{dateStr(data?.publishedAt ?? data?._updatedAt)}
|
||||
</BodyShort>
|
||||
</div>
|
||||
<div className="mt-12 md:mt-16">
|
||||
<Feedback
|
||||
akselFeedback
|
||||
docId={data?._id}
|
||||
docType={data?._type}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</main>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AkselPrinsippTemplate;
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Footer } from "@/layout";
|
||||
import { Header } from "components/layout/header/Header";
|
||||
import React from "react";
|
||||
|
||||
export const NoSidebarLayout = ({
|
||||
children,
|
||||
aside = null,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
aside?: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Header variant="subtle" />
|
||||
<main
|
||||
tabIndex={-1}
|
||||
id="hovedinnhold"
|
||||
className="aksel-artikkel bg-surface-subtle pt-4 focus:outline-none"
|
||||
>
|
||||
<div className="max-w-aksel mx-auto px-4 sm:w-[90%]">
|
||||
<article className="pt-12 pb-16 md:pb-32">{children}</article>
|
||||
</div>
|
||||
{aside}
|
||||
</main>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SidebarT } from "@/lib";
|
||||
import { AkselSidebarT } from "@/types";
|
||||
import { logNav } from "@/utils";
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import { ChevronDownIcon } from "@navikt/aksel-icons";
|
||||
import { BodyShort, Detail, Tag } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
import Link from "next/link";
|
||||
@@ -26,7 +26,7 @@ const NavItem = ({
|
||||
{
|
||||
"before:border-l-border-action-selected before:top-1/2 before:h-6 before:-translate-y-1/2 before:rounded-full before:border-l-[4px]":
|
||||
isActive,
|
||||
"before:h-full before:rounded-full before:border-l before:border-l-gray-200 hover:before:top-1/2 hover:before:h-6 hover:before:-translate-y-1/2 hover:before:border-l-2 hover:before:border-l-gray-400":
|
||||
"before:h-full before:rounded-full before:border-l before:border-l-gray-200 hover:before:top-1/2 hover:before:h-6 hover:before:-translate-y-1/2 hover:before:border-l-2 hover:before:border-l-gray-400":
|
||||
!isActive,
|
||||
}
|
||||
)}
|
||||
@@ -80,7 +80,13 @@ const NavItem = ({
|
||||
);
|
||||
};
|
||||
|
||||
const Dropdown = ({ title, links }: { title: string; links: SidebarT }) => {
|
||||
const Dropdown = ({
|
||||
title,
|
||||
links,
|
||||
}: {
|
||||
title: string;
|
||||
links: AkselSidebarT;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const { asPath } = useRouter();
|
||||
|
||||
@@ -93,11 +99,11 @@ const Dropdown = ({ title, links }: { title: string; links: SidebarT }) => {
|
||||
>
|
||||
<Detail
|
||||
as="span"
|
||||
className="group-focus-visible:shadow-focus group-hover:bg-surface-neutral-subtle group-active:bg-bg-surface-neutral-subtle-hover mt-6 flex w-full items-center justify-between rounded-sm pl-2 font-semibold first:mt-0"
|
||||
className="group-focus-visible:shadow-focus group-hover:bg-surface-neutral-subtle group-active:bg-bg-surface-neutral-subtle-hover mt-6 flex w-full items-center justify-between rounded-sm pl-2 font-semibold transition first:mt-0"
|
||||
>
|
||||
{title}
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded">
|
||||
<Expand
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded">
|
||||
<ChevronDownIcon
|
||||
className={cl("text-base", { "rotate-180": open })}
|
||||
aria-hidden
|
||||
title={!open ? `åpne ${title}` : `lukk ${title}`}
|
||||
@@ -125,7 +131,7 @@ export const Sidebar = ({
|
||||
links,
|
||||
}: {
|
||||
kategori: "Komponenter" | "Grunnleggende";
|
||||
links: SidebarT;
|
||||
links: AkselSidebarT;
|
||||
}) => {
|
||||
const sections = useMemo(
|
||||
() =>
|
||||
|
||||
@@ -4,11 +4,7 @@ import { SanityT } from "@/lib";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
|
||||
const Accordion = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.accordion;
|
||||
}): JSX.Element => {
|
||||
const Accordion = ({ node }: { node: SanityT.Schema.accordion }) => {
|
||||
if (!node || node.list.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@ import React from "react";
|
||||
import { SanityT } from "@/lib";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
|
||||
const Alert = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.alert & { _key: string };
|
||||
}): JSX.Element => {
|
||||
const Alert = ({ node }: { node: SanityT.Schema.alert & { _key: string } }) => {
|
||||
return (
|
||||
<div className="mb-7 max-w-2xl">
|
||||
<DsAlert variant={node.variant}>
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import { SanityT, urlFor } from "@/lib";
|
||||
import { urlFor } from "@/lib";
|
||||
import { Heading } from "@navikt/ds-react";
|
||||
import Nextlink from "next/link";
|
||||
import cl from "clsx";
|
||||
import Image from "next/legacy/image";
|
||||
import { StatusTag } from "components/website-modules/StatusTag";
|
||||
import { ArticleListT } from "@/types";
|
||||
|
||||
const ComponentOverview = ({
|
||||
node,
|
||||
}: {
|
||||
node: {
|
||||
_id: string;
|
||||
heading: string;
|
||||
slug: { current: string };
|
||||
status?: SanityT.Schema.komponent_artikkel["status"];
|
||||
}[];
|
||||
}): JSX.Element => {
|
||||
const ComponentOverview = ({ node }: { node: ArticleListT }) => {
|
||||
if (!node || node.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -40,7 +32,7 @@ const ComponentOverview = ({
|
||||
|
||||
return (
|
||||
<div className="mb-8">
|
||||
<ul className="component-card-grid">
|
||||
<ul className="grid grid-cols-[repeat(auto-fill,_minmax(min(17rem,_100%),_1fr))] gap-6">
|
||||
{sorted.map((x) => (
|
||||
<li key={x._id}>
|
||||
<div className="bg-surface-subtle focus-within:ring-border-focus ring-border-subtle hover:shadow-medium min-h-56 group relative rounded-2xl focus-within:ring-[3px] hover:ring-1">
|
||||
|
||||
@@ -38,20 +38,17 @@ const Element = ({
|
||||
block,
|
||||
}: {
|
||||
block: Sanity.Keyed<SanityT.Schema.do_dont_block>;
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
if (!block.picture) return null;
|
||||
return (
|
||||
<figure
|
||||
className={cl(
|
||||
"flex min-w-full flex-1 flex-col rounded-t sm:min-w-[320px]",
|
||||
{
|
||||
"basis-full": block?.fullwidth,
|
||||
"max-w-sm": !block?.fullwidth,
|
||||
}
|
||||
)}
|
||||
className={cl("sm:min-w-80 flex min-w-full flex-1 flex-col rounded-t", {
|
||||
"basis-full": block?.fullwidth,
|
||||
"max-w-sm": !block?.fullwidth,
|
||||
})}
|
||||
>
|
||||
<img
|
||||
className="rounded-t bg-gray-50 shadow-[0_0_0_1px_var(--a-border-divider)]"
|
||||
className="ring-border-subtle rounded-t bg-gray-50 ring-1"
|
||||
alt={block.alt}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
@@ -61,9 +58,9 @@ const Element = ({
|
||||
className={cl(
|
||||
"z-10 -ml-[1px] w-[calc(100%_+_2px)] rounded-b border-t-8",
|
||||
{
|
||||
"border-t-green-400": block.variant === "do",
|
||||
"border-t-red-400": block.variant === "dont",
|
||||
"border-t-orange-500": block.variant === "warning",
|
||||
"border-t-border-success": block.variant === "do",
|
||||
"border-t-border-danger": block.variant === "dont",
|
||||
"border-t-border-warning": block.variant === "warning",
|
||||
}
|
||||
)}
|
||||
/>
|
||||
@@ -87,7 +84,7 @@ const DoDont = ({ node }: { node: SanityT.Schema.do_dont }) => {
|
||||
return (
|
||||
<div className="mb-8 last:mb-0">
|
||||
{node?.blokker?.length > 0 && (
|
||||
<div className="last flex flex-wrap justify-start gap-8">
|
||||
<div className="last flex flex-wrap justify-start gap-6">
|
||||
{node.blokker.map((x) => (
|
||||
<Element key={x._key} block={x} />
|
||||
))}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { ExpansionCard as DsExpansionCard } from "@navikt/ds-react";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
|
||||
const ExpansionCard = ({
|
||||
node,
|
||||
}: {
|
||||
node: {
|
||||
heading: string;
|
||||
heading_level: "h3" | "h4";
|
||||
description?: string;
|
||||
body: any[];
|
||||
};
|
||||
}) => {
|
||||
if (!node.heading || !node.body || !node.heading_level) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<DsExpansionCard className="mb-7 max-w-2xl" aria-label={node.heading}>
|
||||
<DsExpansionCard.Header>
|
||||
<DsExpansionCard.Title
|
||||
as={node.heading_level}
|
||||
size={node.heading_level === "h3" ? "medium" : "small"}
|
||||
>
|
||||
{node.heading}
|
||||
</DsExpansionCard.Title>
|
||||
{node?.description && (
|
||||
<DsExpansionCard.Description>
|
||||
{node.description}
|
||||
</DsExpansionCard.Description>
|
||||
)}
|
||||
</DsExpansionCard.Header>
|
||||
<DsExpansionCard.Content>
|
||||
<SanityBlockContent blocks={node.body} noLastMargin />
|
||||
</DsExpansionCard.Content>
|
||||
</DsExpansionCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(ExpansionCard, "ExpansionCard");
|
||||
@@ -1,15 +1,15 @@
|
||||
import { LevelTwoHeading } from "@/components";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { AkselGrunnleggendeDocT, AkselKomponentDocT } from "@/types";
|
||||
import { Label } from "@navikt/ds-react";
|
||||
import React from "react";
|
||||
|
||||
const Intro = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.intro_komponent;
|
||||
}): JSX.Element => {
|
||||
node: AkselKomponentDocT["intro"] | AkselGrunnleggendeDocT["intro"];
|
||||
}) => {
|
||||
if (!node || !node.body || !node.brukes_til) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Snippet } from "@/components";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
|
||||
const Kode = ({ node }: { node: SanityT.Schema.kode }): JSX.Element => {
|
||||
const Kode = ({ node }: { node: SanityT.Schema.kode }) => {
|
||||
if (!node || !node.code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ type SpesialT = {
|
||||
token?: { title: string; kategori: string };
|
||||
};
|
||||
|
||||
const SideModul = ({ node }: { node: SpesialT }): JSX.Element => {
|
||||
const SideModul = ({ node }: { node: SpesialT }) => {
|
||||
if (!node || !node.modul) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@ import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
import { Table } from "@navikt/ds-react";
|
||||
|
||||
const TableComponent = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.tabell_v2;
|
||||
}): JSX.Element => {
|
||||
const TableComponent = ({ node }: { node: SanityT.Schema.tabell_v2 }) => {
|
||||
if (!node || !node.rows || node.rows.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,7 @@ const KBD = (props: React.HTMLAttributes<HTMLElement>) => (
|
||||
/>
|
||||
);
|
||||
|
||||
const UuSeksjon = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.tastatur_modul;
|
||||
}): JSX.Element => {
|
||||
const UuSeksjon = ({ node }: { node: SanityT.Schema.tastatur_modul }) => {
|
||||
if (!node || !node?.tastatur) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,16 @@
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
import { ClipboardIcon } from "@navikt/aksel-icons";
|
||||
import internal from "@navikt/ds-css-internal/tokens.json";
|
||||
import core from "@navikt/ds-css/tokens.json";
|
||||
import { Expand, SuccessStroke } from "@navikt/ds-icons";
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import { BodyLong, Label, Link } from "@navikt/ds-react";
|
||||
import cl from "classnames";
|
||||
import copy from "copy-to-clipboard";
|
||||
import CopyButton from "components/sanity-modules/code/CopyButton";
|
||||
import NextLink from "next/link";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
const TokenTable = ({ node }: { node: SanityT.Schema.token_kategori }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const handleCopy = () => {
|
||||
setActive(true);
|
||||
timeoutRef.current && clearTimeout(timeoutRef.current);
|
||||
timeoutRef.current = setTimeout(() => setActive(false), 2000);
|
||||
const str = Object.entries(tokens).reduce(
|
||||
(prev, cur) =>
|
||||
prev +
|
||||
`${cur[0]}: ${
|
||||
cur[1].startsWith("--") ? `var(${cur[1]})` : `${cur[1]}`
|
||||
};\n`,
|
||||
""
|
||||
);
|
||||
copy(str);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
return () => timeoutRef.current && clearTimeout(timeoutRef.current);
|
||||
}, []);
|
||||
|
||||
const tokens: { [key: string]: string } | null =
|
||||
node.title in core
|
||||
@@ -77,22 +54,17 @@ const TokenTable = ({ node }: { node: SanityT.Schema.token_kategori }) => {
|
||||
</table>
|
||||
{(open || !showMore) && (
|
||||
<div className="border-border-divider bg-surface-neutral-subtle relative w-full rounded-b border border-t-0 p-2">
|
||||
<button
|
||||
onClick={handleCopy}
|
||||
className="text-text-default hover:bg-surface-neutral-subtle-hover focus-visible:shadow-focus absolute top-2 right-2 rounded px-1 py-1 text-2xl focus:outline-none"
|
||||
>
|
||||
{active ? (
|
||||
<>
|
||||
<SuccessStroke className="text-[1.5rem]" aria-hidden />
|
||||
<span className="sr-only">Kopier formarterte tokens</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ClipboardIcon aria-hidden />
|
||||
<span className="sr-only">Kopier formarterte tokens</span>
|
||||
</>
|
||||
<CopyButton
|
||||
variant="tokentable"
|
||||
content={Object.entries(tokens).reduce(
|
||||
(prev, cur) =>
|
||||
prev +
|
||||
`${cur[0]}: ${
|
||||
cur[1].startsWith("--") ? `var(${cur[1]})` : `${cur[1]}`
|
||||
};\n`,
|
||||
""
|
||||
)}
|
||||
</button>
|
||||
/>
|
||||
<Label size="small" as="span" spacing>
|
||||
Hva er dette?
|
||||
</Label>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FeedbackT } from "@/lib";
|
||||
import { FeedbackT } from "@/types";
|
||||
import { IdContext } from "@/utils";
|
||||
import { Button, Heading, Textarea } from "@navikt/ds-react";
|
||||
import cl from "classnames";
|
||||
|
||||
@@ -16,7 +16,7 @@ const Video = ({
|
||||
transkripsjon?: string;
|
||||
caption?: string;
|
||||
};
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
if (
|
||||
|
||||
@@ -19,7 +19,7 @@ const Bilde = ({
|
||||
dekorativt?: boolean;
|
||||
};
|
||||
className?: string;
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
if (!node || !node.asset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
|
||||
import {
|
||||
ResolveContributorsSingleT,
|
||||
ResolveTemaT,
|
||||
ResolveSlugT,
|
||||
AkselGodPraksisDocT,
|
||||
} from "@/types";
|
||||
import { BodyShort, Detail, Heading } from "@navikt/ds-react";
|
||||
import NextLink from "next/link";
|
||||
import { abbrName, dateStr, logNav } from "../..";
|
||||
@@ -16,16 +22,9 @@ const ArtikkelCard = ({
|
||||
tema,
|
||||
level = "2",
|
||||
...rest
|
||||
}: Partial<
|
||||
(SanityT.Schema.aksel_artikkel | SanityT.Schema.aksel_blogg) & {
|
||||
slug: string;
|
||||
tema: string[];
|
||||
source?: string;
|
||||
contributor: { title: string } | null;
|
||||
variant?: "god-praksis" | "tema";
|
||||
level?: "2" | "3" | "4";
|
||||
}
|
||||
>) => {
|
||||
}: ResolveContributorsSingleT<
|
||||
ResolveTemaT<ResolveSlugT<AkselGodPraksisDocT>>
|
||||
> & { source: string; variant: string; level?: "2" | "3" }) => {
|
||||
const date = (rest as any)?.updateInfo?.lastVerified
|
||||
? (rest as any)?.updateInfo?.lastVerified
|
||||
: publishedAt
|
||||
@@ -33,7 +32,7 @@ const ArtikkelCard = ({
|
||||
: _updatedAt;
|
||||
|
||||
return (
|
||||
<div className="hover:shadow-small focus-within:ring-border-focus bg-surface-default ring-border-subtle group relative rounded-lg p-5 pb-16 ring-1 focus-within:ring-[3px]">
|
||||
<div className="hover:shadow-small focus-within:ring-border-focus bg-surface-default ring-border-subtle group relative rounded-lg p-3 pb-16 ring-1 focus-within:ring-[3px] sm:p-5 sm:pb-16">
|
||||
<NextLink
|
||||
href={{
|
||||
pathname: `/${slug}`,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
import { AkselBloggDocT, ResolveContributorsT, ResolveSlugT } from "@/types";
|
||||
import { BodyLong, BodyShort, Heading, Link } from "@navikt/ds-react";
|
||||
import { getAuthors } from "components/website-modules/LatestBloggs";
|
||||
import NextLink from "next/link";
|
||||
@@ -8,17 +8,13 @@ import { dateStr, logNav } from "../..";
|
||||
const BloggCard = ({
|
||||
blog,
|
||||
}: {
|
||||
blog: Partial<
|
||||
SanityT.Schema.aksel_blogg & {
|
||||
slug: string;
|
||||
contributors?: {
|
||||
title?: string;
|
||||
}[];
|
||||
}
|
||||
>;
|
||||
blog: ResolveContributorsT<ResolveSlugT<AkselBloggDocT>>;
|
||||
}) => {
|
||||
return (
|
||||
<li key={blog._id} className="border-b-border-subtle h-fit border-b pb-8">
|
||||
<li
|
||||
key={blog._id}
|
||||
className="border-b-border-subtle flex h-full flex-col place-content-start border-b pb-8"
|
||||
>
|
||||
<Heading size="medium" as="div">
|
||||
<NextLink href={`/${blog.slug}`} passHref legacyBehavior>
|
||||
<Link
|
||||
@@ -35,9 +31,12 @@ const BloggCard = ({
|
||||
</Link>
|
||||
</NextLink>
|
||||
</Heading>
|
||||
<BodyLong className="mt-2">{blog?.ingress}</BodyLong>
|
||||
<BodyLong className="my-2">{blog?.ingress}</BodyLong>
|
||||
{getAuthors(blog).length > 0 && (
|
||||
<BodyShort size="small" className="text-text-subtle mt-6 flex gap-2">
|
||||
<BodyShort
|
||||
size="small"
|
||||
className="text-text-subtle mt-auto flex gap-2 justify-self-end"
|
||||
>
|
||||
<span className="font-semibold">{getAuthors(blog)[0]}</span>
|
||||
<span>{dateStr(blog?.publishedAt ?? blog._createdAt)}</span>
|
||||
</BodyShort>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { urlFor } from "@/lib";
|
||||
import { AkselTemaT } from "@/types";
|
||||
import { logNav } from "@/utils";
|
||||
import { BodyShort } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
import NextLink from "next/link";
|
||||
import Image from "next/legacy/image";
|
||||
import { logNav } from "@/utils";
|
||||
import { SanityT, urlFor } from "@/lib";
|
||||
|
||||
interface AkselTemaT extends SanityT.Schema.aksel_tema {
|
||||
refCount: number;
|
||||
}
|
||||
import NextLink from "next/link";
|
||||
|
||||
const GodPraksisCard = ({ node }: { node: AkselTemaT }) => {
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { urlFor } from "@/lib";
|
||||
import { AkselTemaT } from "@/types";
|
||||
import { logNav } from "@/utils";
|
||||
import Image from "next/legacy/image";
|
||||
import NextLink from "next/link";
|
||||
|
||||
const GodPraksisCardSimple = ({ node }: { node: Partial<AkselTemaT> }) => {
|
||||
if (!node?.pictogram || !node?.slug?.current || !node?.title) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<li className="flex items-center gap-2 px-2 py-4 sm:gap-4 sm:px-6">
|
||||
<div className="relative h-8 w-8 shrink-0 sm:h-12 sm:w-12">
|
||||
<Image
|
||||
src={urlFor(node?.pictogram).auto("format").url()}
|
||||
decoding="sync"
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
aria-hidden
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<NextLink
|
||||
href={`/god-praksis/${node.slug.current}`}
|
||||
passHref
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"card",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
className="navds-heading--small navds-link text-deepblue-700 navds-heading flex-wrap break-all no-underline hover:underline focus:outline-none"
|
||||
>
|
||||
{node.title}
|
||||
</NextLink>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(GodPraksisCardSimple, "GodPraksisCardSimple");
|
||||
@@ -10,7 +10,7 @@ const RelatertInnhold = ({
|
||||
node,
|
||||
}: {
|
||||
node: SanityT.Schema.relatert_innhold;
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
if (!node || node?.lenker?.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ const ComponentExamples = ({
|
||||
dir?: SanityT.Schema.kode_eksempler_fil;
|
||||
filnavn?: SanityT.Schema.kode_eksempler_fil;
|
||||
};
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
const [activeExample, setActiveExample] = useState(null);
|
||||
const [frameState, setFrameState] = useState(300);
|
||||
const [unloaded, setUnloaded] = useState(true);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { SuccessStroke } from "@navikt/ds-icons";
|
||||
import { useRef, useState, useEffect } from "react";
|
||||
import copy from "copy-to-clipboard";
|
||||
import React from "react";
|
||||
import cl from "clsx";
|
||||
import style from "./index.module.css";
|
||||
import { ClipboardIcon } from "@navikt/aksel-icons";
|
||||
import { CheckmarkIcon, ClipboardIcon } from "@navikt/aksel-icons";
|
||||
|
||||
const copyCode = (content: string) =>
|
||||
copy(content, {
|
||||
@@ -13,12 +12,11 @@ const copyCode = (content: string) =>
|
||||
|
||||
interface CopyButtonProps {
|
||||
content: string;
|
||||
inTabs?: boolean;
|
||||
inverted?: boolean;
|
||||
variant?: "tokentable" | "codeblock";
|
||||
}
|
||||
|
||||
const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(
|
||||
({ content, inTabs, inverted = false }, ref) => {
|
||||
({ content, variant = "codeblock" }, ref) => {
|
||||
const [active, setActive] = useState(false);
|
||||
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
@@ -31,7 +29,7 @@ const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(
|
||||
copyCode(content);
|
||||
setActive(true);
|
||||
timeoutRef.current && clearTimeout(timeoutRef.current);
|
||||
timeoutRef.current = setTimeout(() => setActive(false), 3000);
|
||||
timeoutRef.current = setTimeout(() => setActive(false), 1000);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -39,25 +37,39 @@ const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(
|
||||
ref={ref}
|
||||
aria-live={active ? "polite" : "off"}
|
||||
role={active ? "alert" : undefined}
|
||||
className={cl(style.copybutton, "navds-body-short group z-10", {
|
||||
"flex w-16 items-center justify-center hover:bg-blue-50 focus:outline-none focus-visible:shadow-[inset_0_0_0_2px_var(--a-border-focus)]":
|
||||
inTabs,
|
||||
"text-text-default focus-visible:outline-focus absolute top-2 right-2 rounded bg-gray-100 px-2 py-1 hover:bg-gray-900/10 hover:underline focus-visible:outline-2":
|
||||
!inTabs && inverted,
|
||||
"text-text-on-inverted focus-visible:shadow-focus-inverted absolute top-2 right-2 flex h-10 w-10 items-center justify-center rounded bg-gray-900 hover:bg-gray-800 focus:outline-none":
|
||||
!inTabs && !inverted,
|
||||
})}
|
||||
className={cl(
|
||||
style.copybutton,
|
||||
"navds-body-short group/button absolute top-2 right-2 z-10 flex h-10 w-10 items-center justify-center overflow-hidden rounded backdrop-blur transition duration-75 focus:outline-none",
|
||||
{
|
||||
"hover:text-text-on-inverted focus-visible:shadow-focus-inverted text-3xl text-gray-100 hover:bg-white/20 ":
|
||||
variant === "codeblock",
|
||||
"hover:text-deepblue-800 focus-visible:shadow-focus text-text-subtle hover:bg-surface-hover text-2xl":
|
||||
variant === "tokentable",
|
||||
}
|
||||
)}
|
||||
onClick={handleCopy}
|
||||
>
|
||||
{active ? (
|
||||
<SuccessStroke className="text-[1.5rem]" title="Kopierte kodesnutt" />
|
||||
) : (
|
||||
<ClipboardIcon
|
||||
fontSize="2rem"
|
||||
className="opacity-90 group-hover:opacity-100"
|
||||
title="Kopier kodesnutt"
|
||||
/>
|
||||
)}
|
||||
<span
|
||||
aria-hidden={!active}
|
||||
className={cl(
|
||||
"absolute inset-0 grid place-content-center transition duration-300",
|
||||
{
|
||||
"pointer-events-none translate-y-1.5 opacity-0": !active,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<CheckmarkIcon title="Kopierte kodesnutt" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
aria-hidden={active}
|
||||
className={cl("flex items-center transition duration-300", {
|
||||
"pointer-events-none -translate-y-1.5 opacity-0": active,
|
||||
"group-hover/button:opacity-100": !active,
|
||||
})}
|
||||
>
|
||||
<ClipboardIcon title="Kopier kodesnutt" />
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const CodeSnippet = ({
|
||||
node: SanityT.Schema.kode;
|
||||
className?: string;
|
||||
style?: any;
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
if (!code || !code.code) {
|
||||
return null;
|
||||
}
|
||||
@@ -27,7 +27,7 @@ const CodeSnippet = ({
|
||||
<div
|
||||
className={cl(
|
||||
className,
|
||||
"relative mb-8 grid max-h-96 overflow-x-auto rounded bg-gray-900"
|
||||
"relative mb-8 grid max-h-96 overflow-x-auto rounded bg-[#0f172a]"
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
@@ -39,7 +39,7 @@ const CodeSnippet = ({
|
||||
theme={undefined}
|
||||
>
|
||||
{({ tokens, getLineProps, getTokenProps }) => (
|
||||
<pre className="text-text-on-inverted relative m-0 overflow-x-auto overflow-y-auto rounded-lg bg-gray-900 p-4 pr-16 font-mono">
|
||||
<pre className="text-text-on-inverted relative m-0 overflow-x-auto overflow-y-auto rounded-lg bg-[#0f172a] p-4 pr-16 font-mono">
|
||||
{tokens.map((line, i) => (
|
||||
<div
|
||||
key={i}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import { abbrName, dateStr } from "@/utils";
|
||||
import { BodyShort, Detail, Heading } from "@navikt/ds-react";
|
||||
import { logNav } from "components/website-modules/utils/amplitude";
|
||||
import NextLink from "next/link";
|
||||
import NextImage from "next/legacy/image";
|
||||
import { Tag } from "./Tag";
|
||||
import cl from "clsx";
|
||||
import { urlFor } from "lib/sanity/santiy";
|
||||
import { getImage } from "components/website-modules/utils/get-image";
|
||||
|
||||
export type ArticleT = {
|
||||
_key: string;
|
||||
_type: string;
|
||||
_createdAt: string;
|
||||
_updatedAt: string;
|
||||
_id: string;
|
||||
heading: string;
|
||||
ingress?: string;
|
||||
slug: { current: string };
|
||||
seo?: {
|
||||
meta?: string;
|
||||
image?: any;
|
||||
};
|
||||
tema?: string[];
|
||||
status?: { tag: string; bilde?: any };
|
||||
publishedAt: string;
|
||||
contributors?: { title: string }[];
|
||||
};
|
||||
|
||||
export const Card = ({ article }: { article: ArticleT }) => {
|
||||
const date = article.publishedAt ? article.publishedAt : article._updatedAt;
|
||||
|
||||
const showFooter = ["aksel_artikkel", "aksel_blogg"].includes(article._type);
|
||||
const showImage = [
|
||||
"ds_artikkel",
|
||||
"komponent_artikkel",
|
||||
"aksel_blogg",
|
||||
].includes(article._type);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cl(
|
||||
"bg-surface-default group relative rounded-lg",
|
||||
"focus-within:ring-border-focus ring-border-subtle-hover focus-within:ring-[3px]",
|
||||
"shadow-[0_0_1px_rgb(0_0_0/0.3),0_1px_3px_rgb(0_0_0/0.15)]"
|
||||
)}
|
||||
>
|
||||
{showImage && (
|
||||
<div
|
||||
className={cl(
|
||||
"flex max-h-80 items-center justify-center overflow-hidden rounded-t-lg",
|
||||
"bg-deepblue-200 filter",
|
||||
{
|
||||
"hue-rotate-[65deg]": article?.status?.tag === "beta",
|
||||
}
|
||||
)}
|
||||
>
|
||||
{article.status?.bilde ?? article.seo?.image ? (
|
||||
article.status?.bilde ? (
|
||||
<NextImage
|
||||
src={urlFor(article.status?.bilde).auto("format").url()}
|
||||
width="200"
|
||||
height="200"
|
||||
alt={article.heading + " thumbnail"}
|
||||
aria-hidden
|
||||
/>
|
||||
) : (
|
||||
<div className="relative h-[200px] w-full">
|
||||
<NextImage
|
||||
src={urlFor(article.seo?.image).auto("format").url()}
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
alt={article.heading + " thumbnail"}
|
||||
aria-hidden
|
||||
className="rounded-t-lg"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="relative h-[200px] w-full">
|
||||
<NextImage
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
src={getImage(article?.heading ?? "", "thumbnail")}
|
||||
alt={article.heading + " thumbnail"}
|
||||
aria-hidden
|
||||
className="rounded-t-lg"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={cl("p-3 sm:p-5", showFooter && "pb-16 sm:pb-16")}>
|
||||
<div className="flex flex-col-reverse">
|
||||
<NextLink
|
||||
href={`/${article.slug}`}
|
||||
passHref
|
||||
className="after:absolute after:inset-0 after:z-10 after:rounded-lg focus:outline-none"
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"forside-masonary",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
>
|
||||
<Heading level="3" size="small" className="group-hover:underline">
|
||||
{article.heading}
|
||||
</Heading>
|
||||
</NextLink>
|
||||
<Tag
|
||||
type={article._type}
|
||||
text={article.tema ? article.tema[0] : undefined}
|
||||
size="small"
|
||||
beta={article.status?.tag === "beta"}
|
||||
/>
|
||||
</div>
|
||||
{article.ingress ? (
|
||||
<BodyShort className="mt-2">{article.ingress}</BodyShort>
|
||||
) : article.seo.meta ? (
|
||||
<BodyShort className="mt-2">{article.seo.meta}</BodyShort>
|
||||
) : null}
|
||||
{showFooter && (
|
||||
<span className="text-text-subtle absolute bottom-5 flex gap-2">
|
||||
{article?.contributors && (
|
||||
<Detail as="span" className="font-semibold">
|
||||
{abbrName(article?.contributors[0]?.title)}
|
||||
</Detail>
|
||||
)}
|
||||
<Detail as="span">{dateStr(date)}</Detail>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import Latest, { LatestT } from "./Latest";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
export type BlocksT = LatestT;
|
||||
|
||||
export const FrontpageBlock = ({ blocks }: { blocks: BlocksT[] }) => {
|
||||
if (!blocks || !blocks.length) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="lg:px-18 px-2">
|
||||
{blocks.map((x) => {
|
||||
switch (x._type) {
|
||||
case "nytt_fra_aksel":
|
||||
return <Latest block={x} key={x._key} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withErrorBoundary(FrontpageBlock, "FrontpageBlock");
|
||||
@@ -0,0 +1,166 @@
|
||||
import { BodyLong, BodyShort, Heading, Link } from "@navikt/ds-react";
|
||||
import Masonry, { ResponsiveMasonry } from "react-responsive-masonry";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import Image from "next/legacy/image";
|
||||
import NextLink from "next/link";
|
||||
import { urlFor } from "lib/sanity/santiy";
|
||||
import { getImage } from "components/website-modules/utils/get-image";
|
||||
import { getAuthors } from "components/website-modules/LatestBloggs";
|
||||
import { dateStr, logNav } from "@/utils";
|
||||
import { Tag } from "./Tag";
|
||||
import { Card, ArticleT } from "./Card";
|
||||
import cl from "clsx";
|
||||
|
||||
export type LatestT = {
|
||||
_type: "nytt_fra_aksel";
|
||||
_key: string;
|
||||
highlights: ArticleT[];
|
||||
curatedResent: {
|
||||
artikler: ArticleT[];
|
||||
bloggposts: ArticleT[];
|
||||
komponenter: ArticleT[];
|
||||
};
|
||||
};
|
||||
|
||||
const Latest = ({ block }: { block: LatestT }) => {
|
||||
const highlights = block.highlights?.length;
|
||||
|
||||
const articles = getList(block);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Heading level="2" size="xlarge" className="text-deepblue-800 mb-10">
|
||||
Siste fra Aksel
|
||||
</Heading>
|
||||
|
||||
{highlights && <Highlights highlights={block.highlights} />}
|
||||
<section aria-label="Nyeste artikler fra Aksel" className="mt-20">
|
||||
<ResponsiveMasonry
|
||||
columnsCountBreakPoints={{ 480: 1, 768: 2, 1024: 3 }}
|
||||
>
|
||||
<Masonry gutter="1.5rem">
|
||||
{articles.map((x) => (
|
||||
<Card key={x._id} article={x} />
|
||||
))}
|
||||
</Masonry>
|
||||
</ResponsiveMasonry>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function Highlights({ highlights }: { highlights: ArticleT[] }) {
|
||||
return (
|
||||
<div
|
||||
className={cl({ "grid gap-8 md:grid-cols-2": highlights?.length === 2 })}
|
||||
>
|
||||
{highlights.map((x, idx) => {
|
||||
const showFooter = ["aksel_artikkel", "aksel_blogg"].includes(x._type);
|
||||
const useStatusImage =
|
||||
["ds_artikkel", "komponent_artikkel"].includes(x._type) &&
|
||||
x.status?.bilde;
|
||||
return (
|
||||
<section
|
||||
aria-label={`Fremhevet artikkel: ${x?.heading}`}
|
||||
key={idx}
|
||||
className={cl({
|
||||
"grid content-start gap-8 md:grid-cols-2":
|
||||
highlights?.length === 1,
|
||||
"grid content-start gap-6": highlights?.length === 2,
|
||||
})}
|
||||
>
|
||||
<div className="relative block aspect-video">
|
||||
{useStatusImage ? (
|
||||
<Image
|
||||
src={urlFor(x.status.bilde).quality(100).auto("format").url()}
|
||||
quality={100}
|
||||
layout="fill"
|
||||
aria-hidden
|
||||
priority
|
||||
className={cl(
|
||||
"bg-deepblue-200 rounded-lg object-cover sm:object-contain",
|
||||
{
|
||||
"hue-rotate-[65deg]": x?.status?.tag === "beta",
|
||||
}
|
||||
)}
|
||||
decoding="sync"
|
||||
/>
|
||||
) : x?.seo?.image ? (
|
||||
<Image
|
||||
src={urlFor(x.seo.image).quality(100).auto("format").url()}
|
||||
quality={100}
|
||||
layout="fill"
|
||||
objectFit="cover"
|
||||
aria-hidden
|
||||
priority
|
||||
className={cl("rounded-lg", {
|
||||
"hue-rotate-[65deg]": x?.status?.tag === "beta",
|
||||
})}
|
||||
decoding="sync"
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
src={getImage(x?.heading ?? "", "thumbnail")}
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
aria-hidden
|
||||
priority
|
||||
className="rounded-lg"
|
||||
decoding="sync"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Tag
|
||||
type={x._type}
|
||||
text={x.tema ? x.tema[0] : undefined}
|
||||
beta={x?.status?.tag === "beta"}
|
||||
/>
|
||||
<NextLink href={`/${x.slug.current}`} passHref legacyBehavior>
|
||||
<Link
|
||||
onClick={(e) =>
|
||||
logNav(
|
||||
"artikkel-kort",
|
||||
window.location.pathname,
|
||||
e.currentTarget.getAttribute("href")
|
||||
)
|
||||
}
|
||||
className="text-text-default mb-5 mt-2 no-underline hover:underline"
|
||||
>
|
||||
<Heading size="large" level="3">
|
||||
{x?.heading}
|
||||
</Heading>
|
||||
</Link>
|
||||
</NextLink>
|
||||
<BodyLong className="mb-4" size="small">
|
||||
{x?.ingress ?? x.seo?.meta}
|
||||
</BodyLong>
|
||||
{showFooter && getAuthors(x as any).length > 0 && (
|
||||
<BodyShort size="small" className="text-text-subtle flex gap-2">
|
||||
<span className="font-semibold">
|
||||
{getAuthors(x as any)[0]}
|
||||
</span>
|
||||
<span>{dateStr(x?.publishedAt ?? x._createdAt)}</span>
|
||||
</BodyShort>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getList(block: LatestT) {
|
||||
return [
|
||||
...block.curatedResent.artikler,
|
||||
...block.curatedResent.bloggposts,
|
||||
...block.curatedResent.komponenter,
|
||||
].sort((a, b) => {
|
||||
return (
|
||||
new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default withErrorBoundary(Latest, "Latest");
|
||||
@@ -0,0 +1,60 @@
|
||||
import { Heading, Label, Tag as DsTag } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
|
||||
export const Tag = ({
|
||||
type,
|
||||
text,
|
||||
size = "medium",
|
||||
beta = false,
|
||||
}: {
|
||||
type: string;
|
||||
text?: string;
|
||||
size?: "medium" | "small";
|
||||
beta?: boolean;
|
||||
}) => {
|
||||
const Comp = ({ ...props }: any) =>
|
||||
size === "medium" ? (
|
||||
<Heading {...props} as="div" size="medium" />
|
||||
) : (
|
||||
<Label
|
||||
{...props}
|
||||
as="div"
|
||||
size="small"
|
||||
className={cl(props?.className, "mb-2")}
|
||||
/>
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case "aksel_artikkel":
|
||||
return (
|
||||
<Comp className="text-teal-600">{text ? text : "God praksis"}</Comp>
|
||||
);
|
||||
case "aksel_blogg":
|
||||
return <Comp className="text-pink-600">Blogg</Comp>;
|
||||
case "komponent_artikkel":
|
||||
return (
|
||||
<Comp className="text-deepblue-600 flex items-center gap-3">
|
||||
Komponent
|
||||
{beta && (
|
||||
<DsTag variant="alt1" size="small">
|
||||
Beta
|
||||
</DsTag>
|
||||
)}
|
||||
</Comp>
|
||||
);
|
||||
case "ds_artikkel":
|
||||
return (
|
||||
<Comp className="text-deepblue-600 flex items-center gap-3">
|
||||
Grunnleggende
|
||||
{beta && (
|
||||
<DsTag variant="alt1" size="small">
|
||||
Beta
|
||||
</DsTag>
|
||||
)}
|
||||
</Comp>
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -4,7 +4,7 @@ export const Highlighter = ({
|
||||
}: {
|
||||
type: string;
|
||||
prev?: string;
|
||||
}): JSX.Element => {
|
||||
}) => {
|
||||
const isString = type === "string" || type.match(/^["][^"]+"$/) !== null;
|
||||
|
||||
const isType =
|
||||
|
||||
@@ -27,7 +27,11 @@ const List = ({ prop, parent }: { prop: any; parent: string }) => {
|
||||
prop?.required ? "" : "?"
|
||||
} `}</span>
|
||||
) : (
|
||||
<Tooltip content={`${prop.defaultValue}`} arrow={false} delay={0}>
|
||||
<Tooltip
|
||||
content={`default: ${prop.defaultValue}`}
|
||||
arrow={false}
|
||||
delay={0}
|
||||
>
|
||||
<span className="mr-2 cursor-pointer border-b border-dashed border-gray-600 font-semibold">{`${
|
||||
prop.name
|
||||
}${prop?.required ? "" : "?"}`}</span>
|
||||
@@ -51,7 +55,7 @@ const List = ({ prop, parent }: { prop: any; parent: string }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const PropTable = ({ komponent }: { komponent: PropT }): JSX.Element => {
|
||||
const PropTable = ({ komponent }: { komponent: PropT }) => {
|
||||
return (
|
||||
<div>
|
||||
<Heading
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import PropTableV2, { PropT } from "./PropTabell";
|
||||
|
||||
const PropsSeksjon = ({ node }: { node: any }): JSX.Element => {
|
||||
const PropsSeksjon = ({ node }: { node: any }) => {
|
||||
if (
|
||||
!node ||
|
||||
(node?.elementer?.length === 0 && node?.komponenter?.length === 0)
|
||||
|
||||
@@ -7,7 +7,7 @@ import cl from "clsx";
|
||||
import React from "react";
|
||||
import style from "./tips.module.css";
|
||||
|
||||
const Tips = ({ node }: { node: SanityT.Schema.tips }): JSX.Element => {
|
||||
const Tips = ({ node }: { node: SanityT.Schema.tips }) => {
|
||||
if (!node || !node.body) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ export const Frame = ({
|
||||
{hasDescription && <th>Beskrivelse</th>}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="component-token-grid">
|
||||
<tbody className="component-token-grid grid grid-cols-[repeat(auto-fill,_minmax(min(20rem,_100%),_1fr))] gap-4">
|
||||
{tokens.map((c) => (
|
||||
<tr
|
||||
key={c.name}
|
||||
|
||||
@@ -57,7 +57,7 @@ const CubeSmall = () => (
|
||||
|
||||
export const BloggAd = () => {
|
||||
return (
|
||||
<div className="full-bleed my-20 flex h-72 items-center bg-[#FBCFE8] px-4 md:rounded-2xl md:px-6 lg:h-80 lg:pl-12">
|
||||
<div className="relative left-1/2 right-1/2 -mx-[50vw] my-20 flex h-72 w-screen items-center bg-[#FBCFE8] px-4 md:left-auto md:right-auto md:mx-auto md:w-full md:max-w-[85%] md:rounded-2xl md:px-6 lg:h-80 lg:pl-12">
|
||||
<div className="z-10 max-w-sm text-[#831843]">
|
||||
<Heading level="2" size="xlarge" spacing>
|
||||
Skriv for bloggen
|
||||
|
||||
Loaded 100 of 196 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user