Compare commits

..
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] ffac16cb05 Version Packages (#1756)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-19 15:53:44 +01:00
Ken 98177d0cd3 📝 changeset 2023-01-19 15:19:46 +01:00
Ken 2c5be718e6 🎨 Fikset hjelp ønskes modul 2023-01-19 10:00:56 +01:00
github-actions[bot]andgithub-actions[bot] 019d92dd7b Version Packages (#1754)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-18 15:24:10 +01:00
Ken 5b72afbb93 Merge branch 'master' of https://github.com/navikt/Designsystemet 2023-01-18 15:14:13 +01:00
Ken 56348cdddf ♿ Aria-labels for sanity riktekst-editor 2023-01-18 15:13:58 +01:00
github-actions[bot]andgithub-actions[bot] 973d79ee99 Version Packages (#1753)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-18 14:56:36 +01:00
Ken 5bfb912531 🎨 Bedre error-handling på akselartikkel templates 2023-01-18 14:55:45 +01:00
Ken 27e3dfee07 📝 Changeset 2023-01-18 13:08:38 +01:00
KenandKenAJoh 20b2bf6f89 Ikonsynk Figma (#1752)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2023-01-18 13:07:48 +01:00
Ken 4b870986c8 🐛 Fikset intentbutton for feddbackløsning 2023-01-18 12:44:48 +01:00
github-actions[bot]andgithub-actions[bot] 8fcf079359 Version Packages (#1751)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-17 14:55:06 +01:00
Ken 54f8b07956 📝 changeset 2023-01-17 14:13:50 +01:00
KenandKenAJoh 9bc251e694 Ikonsynk Figma (#1750)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2023-01-17 14:13:10 +01:00
github-actions[bot]andgithub-actions[bot] e2a9d027dc Version Packages (#1749)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-17 10:32:23 +01:00
Ken 22dfd8e603 :sparkled: Prop for posisjonering av toptekst i Chat (#1748)
* :sparkled: Prop for posisjonering av toptekst i Chat

* 📝 changeset

* 📝 Docs

* 📝 Demo

* 🎨 fliptoptext -> toptextPosition
2023-01-17 10:26:14 +01:00
Ken 53d1947311 📝 Tekstendringer sanity profilside 2023-01-17 09:39:38 +01:00
Ken d4e7c47772 🎨 Sanity feedback preview 2023-01-17 07:37:20 +01:00
Ken e191dffdf8 🔥 Fjernet dårlige editor-navn 2023-01-16 09:12:05 +01:00
Ken 7e0ee60d47 🔥 Fjernet dårlige editor-navn 2023-01-16 08:57:11 +01:00
github-actions[bot]andgithub-actions[bot] 4ecaeb9d04 Version Packages (#1746)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-13 16:03:31 +01:00
Ken 8e5c554431 ⬆️ Bump @floating-ui/react 2023-01-13 15:56:12 +01:00
Ken 727be0a98b 🔥 Fjernet snowfall fra forside 2023-01-13 15:15:47 +01:00
github-actions[bot]andgithub-actions[bot] 4c2e44ced1 Version Packages (#1745)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-13 15:07:11 +01:00
Ken 2fd1dd443f 🔥 Fjernet ubrukt kode forside 2023-01-13 14:41:06 +01:00
Ken a6c3391237 📝 changeset 2023-01-13 14:38:45 +01:00
KenandKenAJoh 5ede88a188 Ikonsynk Figma (#1739)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2023-01-13 14:38:05 +01:00
Ken 2785593d20 ⬆️ Yarn lock update 2023-01-13 12:38:54 +01:00
Ken a37c743547 🐛 Bedre logging av temavisninger 2023-01-12 09:36:02 +01:00
Ken 6f0e18c3cf 🐛 E2E tester feilet grunnet aria-hidden 2023-01-12 09:18:10 +01:00
Ken bdfaa54e81 ♿ Gjemte til-toppen knapp for skjermleser 2023-01-12 08:27:03 +01:00
Ken 595796af6c 📝 Oppdatert grunnleggnde config 2023-01-12 06:50:16 +01:00
Ken c85b34e86f 🐛 Fikset henting av sider for testing i e2e! 2023-01-10 10:41:17 +01:00
Ken fc46b5a97b 🔍 Sitemap har nå lastmod-attr 2023-01-10 09:50:10 +01:00
Ken c7fcf57fdf :map: Google search-index ignorerer priority i sitemap 2023-01-10 08:28:21 +01:00
Ken 560d8bd1e8 🔍 Bedre robots.txt 2023-01-10 08:21:32 +01:00
Ken 7a53de186e 📝 1 Artikler -> 1 Artikkel 2023-01-09 13:48:57 +01:00
Ken 4feb798b25 🐛 God-praksis feilet ved visning av god-praksis sider 2023-01-09 12:53:54 +01:00
Ken c713b469f0 🔥 Fjernet ubrukt import Temaview 2023-01-09 12:40:42 +01:00
Ken 676392a5c4 🐛 Nye tema uten sider brakk sanity 2023-01-09 12:39:02 +01:00
Ken c049e08555 🎨 Sanity config refactor 2023-01-09 11:51:33 +01:00
github-actions[bot]andgithub-actions[bot] d8c898db8c Version Packages (#1738)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-09 11:05:24 +01:00
Ken 8a1ef5e7e2 🐛 Radio fikk ikke error-farge grunnet indeterminate (#1737) 2023-01-09 10:59:01 +01:00
Lars Hansen 293594235a #aksel til #Aksel 2023-01-05 15:28:57 +01:00
Lars Hansen a54d97591e Merge remote-tracking branch 'origin/master' 2023-01-05 15:28:09 +01:00
Lars Hansen dc2e7fb766 endre lenke fra #aksel og #designsystem til #aksel-designsystemet 2023-01-05 15:23:32 +01:00
Ken 53df42df22 📝 Fikset lenker til #aksel slack etter arkivering 2023-01-05 14:53:36 +01:00
Ken 5b9840524c ✅ Fikset date-test 2023-01-03 10:16:36 +01:00
Ken 0d6ddfd95e 🐛 Profilvisning sanity 2023-01-03 10:05:38 +01:00
Ken 0394e819ba ⚰️ Fjernet trello og algolia-integrasjon 2023-01-03 09:50:46 +01:00
Ken 67fc9ad560 🐛 La til kode-lenker igjen 2022-12-22 21:49:44 +01:00
Ken 8fe5c88eba 🐛 Preview låste seg på komponentsider 2022-12-22 17:11:43 +01:00
Ken 1fbcf78745 🎨 Hue-tilpassning i header på komponentsider 2022-12-22 16:35:13 +01:00
Ken 83dc3236e8 🎨 resolver dokument-ref for alle artikkel-sider 2022-12-22 16:12:57 +01:00
Ken 7503c7fa7f ✨ Feedback integrert på artikkelsider i sanity
🎨 Feedback-dokument

🎨 Sender nå feedback til sanity

🎨 Preview for feedback
2022-12-22 15:08:53 +01:00
Ken e668181690 ✨ Intro-lenker komponentsider 2022-12-21 21:07:05 +01:00
Ken 353dff3da5 🎨 localstorage for animasjons-stopp 2022-12-21 19:02:11 +01:00
Ken a11993a155 🔥 2022-12-21 15:23:06 +01:00
Ken 7b53b7670f ♿ play/pause knapp forside 2022-12-21 15:18:08 +01:00
Ken 0aaa0c4e10 📝 Klarspråk 2022-12-21 14:45:11 +01:00
Ken ea5e1f768c 🎨 Feedback-dokument 2022-12-21 14:31:49 +01:00
Ken e6b16e9b31 🐛 Fikset imports i script 2022-12-21 14:24:43 +01:00
Ken 1029d42163 Merge branch 'next' 2022-12-21 13:52:59 +01:00
Ken fba5140d8b 🚚 Flyttet scripts 2022-12-21 13:52:14 +01:00
Kai Erik Schieren fe72f32dbb ✨ moved backup (#1735) 2022-12-21 13:46:13 +01:00
Ken 6a0890b42b 💄 Kube på god-praksis forside 2022-12-21 13:13:24 +01:00
Ken 320f45a775 💄 Bedre beta-visning på komponentoversikt 2022-12-21 12:44:12 +01:00
Ken 3feb2283a4 🐛 Fikset kode-eksempler resizing 2022-12-21 12:16:59 +01:00
Ken c3b416a3cb 🎨 Deprecated-tag i sidebar sist 2022-12-21 10:10:23 +01:00
Ken 36fba1a33b 🐛 Riktig publiserings-logikk 2022-12-21 09:59:37 +01:00
121 changed files with 2577 additions and 5238 deletions

No files matched your search

-3
View File
@@ -22,9 +22,6 @@ jobs:
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
-3
View File
@@ -21,9 +21,6 @@ jobs:
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
+3 -4
View File
@@ -22,18 +22,17 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
restore-keys: |
${{ runner.os }}-build-
- name: Install dependencies
run: cd aksel.nav.no/sanity && yarn
run: cd aksel.nav.no/website && yarn
- name: Export dataset
run: cd aksel.nav.no/sanity && SANITY_TOKEN=${{secrets.SANITY_DATASET_EDITOR_TOKEN}} yarn backup
run: cd aksel.nav.no/website && SANITY_TOKEN=${{secrets.SANITY_DATASET_EDITOR_TOKEN}} yarn backup
- name: Upload GCP bucket
uses: "google-github-actions/auth@v0"
with:
credentials_json: "${{ secrets.gcp_credentials_prod }}"
- uses: "google-github-actions/upload-cloud-storage@v0"
with:
path: ./aksel.nav.no/sanity
path: ./aksel.nav.no/website
destination: "aksel-website-prod/backups"
glob: "backup-*.tar.gz"
-3
View File
@@ -21,9 +21,6 @@ jobs:
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
-25
View File
@@ -1,25 +0,0 @@
name: Indexing search
on:
workflow_dispatch:
schedule:
# 01.00 & 12.00 every day
- cron: "00 01,12 * * *"
jobs:
searchcrawl:
name: Search-indexing aksel.nav.no
runs-on: ubuntu-latest
env:
APPLICATION_ID: ${{ secrets.ALGOLIA_ID}}
API_KEY: ${{ secrets.ALGOLIA_ADMIN }}
steps:
- uses: actions/checkout@v2
- name: Read crawler.json
id: algolia_config
run: echo "::set-output name=config::$(cat ./aksel.nav.no/crawler.json | jq -r tostring)"
- name: Push indices to Algolia
uses: signcl/docsearch-scraper-action@master
env:
APPLICATION_ID: ${{ secrets.ALGOLIA_ID}}
API_KEY: ${{ secrets.ALGOLIA_ADMIN }}
CONFIG: ${{ steps.algolia_config.outputs.config }}
+2 -1
View File
@@ -149,4 +149,5 @@ tmp.json
playwright-report/
/test-results/
backup-*.tar.gz
sitemap-urls.json
sitemap-urls.json
*.tar.gz
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-codemod
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
## 2.0.14
## 2.0.13
## 2.0.12
## 2.0.11
## 2.0.10
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "2.0.11",
"version": "2.0.18",
"description": "Aksel codemods for NAVs designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
+2 -2
View File
@@ -39,8 +39,8 @@
"build-pict": "svgr --silent --index-template index-template.js --out-dir src/pictograms pictograms"
},
"dependencies": {
"@navikt/ds-icons": "^2.0.11",
"@navikt/ds-react": "^2.0.11",
"@navikt/ds-icons": "^2.0.18",
"@navikt/ds-react": "^2.0.18",
"clsx": "^1.1.1"
},
"devDependencies": {
+22
View File
@@ -1,5 +1,27 @@
# @navikt/ds-css
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
### Patch Changes
- [#1748](https://github.com/navikt/Designsystemet/pull/1748) [`22dfd8e60`](https://github.com/navikt/Designsystemet/commit/22dfd8e60315c421749394d35e41f412a00a7593) Thanks [@KenAJoh](https://github.com/KenAJoh)! - toptextPosition prop i Chat for horisontal plassering av navn og dato.
## 2.0.14
## 2.0.13
## 2.0.12
### Patch Changes
- [#1737](https://github.com/navikt/Designsystemet/pull/1737) [`8a1ef5e7e`](https://github.com/navikt/Designsystemet/commit/8a1ef5e7e2c066cb80c13e14329e1585e2c427f8) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :bug: Fikset default visuell error-state for radio
## 2.0.11
## 2.0.10
+16
View File
@@ -77,6 +77,22 @@
align-self: flex-end;
}
.navds-chat--top-text-left .navds-chat__top-text {
align-self: flex-start;
}
.navds-chat--top-text-right .navds-chat__top-text {
align-self: flex-end;
}
.navds-chat--left .navds-chat__top-text--right {
align-self: flex-end;
}
.navds-chat--right .navds-chat__top-text--left {
align-self: flex-start;
}
.navds-chat__name {
font-weight: var(--a-font-weight-bold);
}
+4 -12
View File
@@ -143,27 +143,21 @@
.navds-checkbox--error
> .navds-checkbox__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
.navds-radio--error > .navds-radio__input:not(:hover):not(:disabled):not(:checked) + .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--ac-radio-checkbox-error-border, var(--a-border-danger));
}
.navds-checkbox--error
> .navds-checkbox__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
.navds-radio--error > .navds-radio__input:focus:not(:hover):not(:disabled):not(:checked) + .navds-radio__label::before {
box-shadow: inset 0 0 0 2px var(--ac-radio-checkbox-error-border, var(--a-border-danger)), var(--a-shadow-focus);
}
.navds-checkbox--error
> .navds-checkbox__input:hover:not(:disabled):not(:checked):not(:indeterminate):not(:focus)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:hover:not(:disabled):not(:checked):not(:indeterminate):not(:focus)
+ .navds-radio__label::before {
.navds-radio--error > .navds-radio__input:hover:not(:disabled):not(:checked):not(:focus) + .navds-radio__label::before {
background-color: var(--ac-radio-checkbox-error-hover-bg, var(--a-surface-danger-subtle));
box-shadow: inset 0 0 0 2px var(--ac-radio-checkbox-error-border, var(--a-border-danger));
}
@@ -171,9 +165,7 @@
.navds-checkbox--error
> .navds-checkbox__input:focus:hover:not(:disabled):not(:checked):not(:indeterminate)
+ .navds-checkbox__label::before,
.navds-radio--error
> .navds-radio__input:focus:hover:not(:disabled):not(:checked):not(:indeterminate)
+ .navds-radio__label::before {
.navds-radio--error > .navds-radio__input:focus:hover:not(:disabled):not(:checked) + .navds-radio__label::before {
background-color: var(--ac-radio-checkbox-error-hover-bg, var(--a-surface-danger-subtle));
box-shadow: inset 0 0 0 2px var(--ac-radio-checkbox-error-border, var(--a-border-danger)), var(--a-shadow-focus);
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "2.0.11",
"version": "2.0.18",
"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.0.11",
"@navikt/ds-tokens": "^2.0.18",
"normalize.css": "^8.0.1",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
+55
View File
@@ -1,5 +1,60 @@
# @navikt/ds-react
## 2.0.18
### Patch Changes
- [`98177d0cd`](https://github.com/navikt/Designsystemet/commit/98177d0cd3802029dcf398ce93c1767d3b0860c5) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Bedre typer for ref i datepicker
- Updated dependencies []:
- @navikt/ds-icons@2.0.18
## 2.0.17
### Patch Changes
- Updated dependencies [[`27e3dfee0`](https://github.com/navikt/Designsystemet/commit/27e3dfee07e135893e9f62cd32f80ed83a3510de)]:
- @navikt/ds-icons@2.0.17
## 2.0.16
### Patch Changes
- Updated dependencies [[`54f8b0795`](https://github.com/navikt/Designsystemet/commit/54f8b07956bbfb7de51f6682a5fc64903bfd1bdf)]:
- @navikt/ds-icons@2.0.16
## 2.0.15
### Patch Changes
- [#1748](https://github.com/navikt/Designsystemet/pull/1748) [`22dfd8e60`](https://github.com/navikt/Designsystemet/commit/22dfd8e60315c421749394d35e41f412a00a7593) Thanks [@KenAJoh](https://github.com/KenAJoh)! - toptextPosition prop i Chat for horisontal plassering av navn og dato.
- Updated dependencies []:
- @navikt/ds-icons@2.0.15
## 2.0.14
### Patch Changes
- [`8e5c55443`](https://github.com/navikt/Designsystemet/commit/8e5c554431c98b1b658c5054c0b3cf08b8a65e52) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Bumpet @floating-ui/react
- Updated dependencies []:
- @navikt/ds-icons@2.0.14
## 2.0.13
### Patch Changes
- Updated dependencies [[`a6c339123`](https://github.com/navikt/Designsystemet/commit/a6c3391237f13394063e4c004ac9efb1875fc944)]:
- @navikt/ds-icons@2.0.13
## 2.0.12
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@2.0.12
## 2.0.11
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "2.0.11",
"version": "2.0.18",
"description": "Aksel react-components for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -36,8 +36,8 @@
"test": "TZ=UTC jest"
},
"dependencies": {
"@floating-ui/react-dom-interactions": "0.9.2",
"@navikt/ds-icons": "^2.0.11",
"@floating-ui/react": "0.17.0",
"@navikt/ds-icons": "^2.0.18",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
+22 -2
View File
@@ -19,6 +19,10 @@ export interface BubbleProps extends HTMLAttributes<HTMLDivElement> {
* Background color on bubble
*/
backgroundColor?: string;
/**
* Overrides hoizontal position of toptext
*/
toptextPosition?: "left" | "right";
}
export type BubbleType = React.ForwardRefExoticComponent<
@@ -26,7 +30,18 @@ export type BubbleType = React.ForwardRefExoticComponent<
>;
const Bubble: BubbleType = forwardRef(
({ children, className, name, timestamp, backgroundColor, ...rest }, ref) => {
(
{
children,
className,
name,
timestamp,
backgroundColor,
toptextPosition,
...rest
},
ref
) => {
return (
<div
ref={ref}
@@ -35,7 +50,12 @@ const Bubble: BubbleType = forwardRef(
{...rest}
>
{(timestamp || name) && (
<div className="navds-chat__top-text">
<div
className={cl(
`navds-chat__top-text`,
toptextPosition && `navds-chat__top-text--${toptextPosition}`
)}
>
{name && <Detail className="navds-chat__name">{name}</Detail>}
{timestamp && (
<Detail className="navds-chat__timestamp">{timestamp}</Detail>
+13 -1
View File
@@ -33,6 +33,11 @@ export interface ChatProps extends HTMLAttributes<HTMLDivElement> {
* @default "left"
*/
position?: "left" | "right";
/**
* Hoizontal position of toptext
* @default Same as chat
*/
toptextPosition?: "left" | "right";
}
interface ChatComponent
@@ -53,6 +58,7 @@ export const Chat = forwardRef<HTMLDivElement, ChatProps>(
position = "left",
avatarBgColor,
backgroundColor,
toptextPosition,
...rest
},
ref
@@ -60,7 +66,13 @@ export const Chat = forwardRef<HTMLDivElement, ChatProps>(
return (
<div
ref={ref}
className={cl("navds-chat", className, `navds-chat--${position}`)}
className={cl(
"navds-chat",
className,
`navds-chat--${position} navds-chat--top-text-${
toptextPosition ?? position
}`
)}
{...rest}
>
<BodyShort
@@ -116,6 +116,57 @@ export const Position = () => {
);
};
export const ToptextPosition = () => {
return (
<div className="colgap">
<Chat
avatar="ON"
name="Ola Normann"
timestamp="01.01.21 14:00"
backgroundColor="rgba(255, 249, 240, 1)"
avatarBgColor="rgba(255, 236, 204, 1)"
toptextPosition="right"
>
<Chat.Bubble>
Adipisicing laborum est eu laborum est sit in commodo enim sint
laboris labore nisi ut.
</Chat.Bubble>
</Chat>
<Chat
avatar="KH"
name="Kari Høyli"
timestamp="01.01.21 14:32"
position="right"
backgroundColor="rgba(230, 240, 255, 1)"
avatarBgColor="rgba(204, 225, 255, 1)"
toptextPosition="left"
>
<Chat.Bubble>
Reprehenderit pariatur officia exercitation laboris.
</Chat.Bubble>
<Chat.Bubble>
Enim velit deserunt do quis. Eu fugiat magna esse dolore ad sunt sit
est dolore incididunt. Occaecat cupidatat magna.
</Chat.Bubble>
</Chat>
<Chat
avatar="ON"
name="Ola Normann"
timestamp="01.01.21 15:00"
backgroundColor="rgba(255, 249, 240, 1)"
avatarBgColor="rgba(255, 236, 204, 1)"
>
<Chat.Bubble toptextPosition="right">
Exercitation irure Lorem cupidatat culpa anim cillum esse ullamco qui
dolore laborum et Lorem. Labore sunt duis id Lorem voluptate commodo
ea esse. Dolore esse aliqua proident ea ad commodo ut dolore voluptate
labore sunt aute.
</Chat.Bubble>
</Chat>
</div>
);
};
export const Avatar = () => {
return (
<Chat avatar={<Illustration />} timestamp="01.01.21 14:00">
@@ -59,7 +59,10 @@ interface UseDatepickerValue {
/**
* Use: <DatePicker.Input {...inputProps}/>
*/
inputProps: Pick<DateInputProps, "onChange" | "onFocus" | "onBlur" | "value">;
inputProps: Pick<
DateInputProps,
"onChange" | "onFocus" | "onBlur" | "value"
> & { ref: React.RefObject<HTMLInputElement> };
/**
* Resets all states (callback)
*/
@@ -45,7 +45,9 @@ interface UseMonthPickerValue {
/**
* Use: <MonthPicker.Input {...inputProps} />
*/
inputProps: Pick<DateInputProps, "onChange" | "onFocus" | "value">;
inputProps: Pick<DateInputProps, "onChange" | "onFocus" | "value"> & {
ref: React.RefObject<HTMLInputElement>;
};
/**
* Currently selected Date
* Up to user to validate value and extract month
@@ -101,7 +103,7 @@ export const useMonthpicker = (
const today = new Date();
const locale = getLocaleFromString(_locale);
const inputRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const monthpickerRef = useRef<HTMLDivElement>(null);
// Initialize states
@@ -1,6 +1,6 @@
import differenceInCalendarDays from "date-fns/differenceInCalendarDays";
import isWeekend from "date-fns/isWeekend";
import { useCallback, useEffect, useRef, useState } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { DateRange, isMatch } from "react-day-picker";
import { DateInputProps } from "../DateInput";
import { DatePickerProps } from "../datepicker/DatePicker";
@@ -71,14 +71,14 @@ interface UseRangeDatepickerValue {
fromInputProps: Pick<
DateInputProps,
"onChange" | "onFocus" | "onBlur" | "value"
>;
> & { ref: React.RefObject<HTMLInputElement> };
/**
* Use: <DatePicker.Input label="to" {...toInputProps}/>
*/
toInputProps: Pick<
DateInputProps,
"onChange" | "onFocus" | "onBlur" | "value"
>;
> & { ref: React.RefObject<HTMLInputElement> };
/**
* Resets all states (callback)
*/
@@ -206,8 +206,8 @@ export const useRangeDatepicker = (
const locale = getLocaleFromString(_locale);
const inputRefTo = useRef<HTMLDivElement>(null);
const inputRefFrom = useRef<HTMLDivElement>(null);
const inputRefTo = useRef<HTMLInputElement>(null);
const inputRefFrom = useRef<HTMLInputElement>(null);
const datePickerRef = useRef<HTMLDivElement | null>(null);
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
@@ -36,7 +36,7 @@ describe("Returns if year is at start or end of range", () => {
expect(hasNextYear(new Date(), years, 1)).toBeTruthy();
});
test("Should have previous year (true)", () => {
expect(hasNextYear(new Date("Aug 3 2023"), years, -1)).toBeTruthy();
expect(hasNextYear(new Date("Aug 3 2024"), years, -1)).toBeTruthy();
});
test("Should not have next year (false)", () => {
expect(hasNextYear(new Date("Aug 3 2029"), years, 1)).toBeFalsy();
+1 -1
View File
@@ -1,5 +1,5 @@
import React, { forwardRef, InputHTMLAttributes } from "react";
import cl from "clsx";
import React, { forwardRef, InputHTMLAttributes } from "react";
import { BodyShort, Detail, omit } from "../..";
import { FormFieldProps } from "../useFormField";
import { useRadio } from "./useRadio";
@@ -23,7 +23,7 @@ export const Default = (props) => {
value={props.controlled ? state : undefined}
onChange={props.controlled ? setState : undefined}
hideLegend={props.hideLegend}
error={props.errorGroup ? "Errormelding" : undefined}
error={props.error ? "Errormelding" : undefined}
size={props?.size}
>
<Radio value="radio1">{props.children || "Apple"}</Radio>
@@ -41,6 +41,7 @@ export const Default = (props) => {
Default.args = {
controlled: false,
error: false,
size: "medium",
legend: "Legend-tekst",
radioDescription: false,
+1 -1
View File
@@ -8,7 +8,7 @@ import {
useDismiss,
useFloating,
useInteractions,
} from "@floating-ui/react-dom-interactions";
} from "@floating-ui/react";
import cl from "clsx";
import React, {
forwardRef,
+1 -1
View File
@@ -11,7 +11,7 @@ import {
useFocus,
useHover,
useInteractions,
} from "@floating-ui/react-dom-interactions";
} from "@floating-ui/react";
import cl from "clsx";
import React, {
cloneElement,
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-tailwind
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
## 2.0.14
## 2.0.13
## 2.0.12
## 2.0.11
## 2.0.10
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "2.0.11",
"version": "2.0.18",
"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.0.11",
"@navikt/ds-tokens": "^2.0.18",
"@types/jest": "^29.0.0",
"color": "4.2.3",
"jest": "^29.0.0",
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-tokens
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
## 2.0.14
## 2.0.13
## 2.0.12
## 2.0.11
## 2.0.10
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "2.0.11",
"version": "2.0.18",
"description": "Design-tokens for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
+26
View File
@@ -1,5 +1,31 @@
# @navikt/ds-icons
## 2.0.18
## 2.0.17
### Patch Changes
- [`27e3dfee0`](https://github.com/navikt/Designsystemet/commit/27e3dfee07e135893e9f62cd32f80ed83a3510de) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Translate og Paragraph ikon
## 2.0.16
### Patch Changes
- [`54f8b0795`](https://github.com/navikt/Designsystemet/commit/54f8b07956bbfb7de51f6682a5fc64903bfd1bdf) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert ikoner med feile farger
## 2.0.15
## 2.0.14
## 2.0.13
### Patch Changes
- [`a6c339123`](https://github.com/navikt/Designsystemet/commit/a6c3391237f13394063e4c004ac9efb1875fc944) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Ikonjusteringer sirkleikoner
## 2.0.12
## 2.0.11
### Patch Changes
+26 -14
View File
@@ -867,13 +867,13 @@
"name": "Eu",
"description": "",
"created_at": "2022-02-08T11:45:47.104Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "EuFilled",
"description": "",
"created_at": "2022-02-08T11:45:47.109Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Expand",
@@ -1479,13 +1479,13 @@
"name": "Law",
"description": "",
"created_at": "2020-07-01T10:37:42.819Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "LawFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.330Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Left",
@@ -1551,37 +1551,37 @@
"name": "Locked",
"description": "",
"created_at": "2020-07-01T10:37:43.027Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "LockedFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.325Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Login",
"description": "",
"created_at": "2020-07-01T10:37:43.087Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "LoginFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.531Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Logout",
"description": "",
"created_at": "2020-07-01T10:37:42.931Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "LogoutFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.609Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Male",
@@ -1811,6 +1811,12 @@
"created_at": "2021-12-15T15:16:55.869Z",
"pageName": "People"
},
{
"name": "Paragraph",
"description": "",
"created_at": "2023-01-17T13:24:22.989Z",
"pageName": "Privacy and security"
},
{
"name": "Parking",
"description": "",
@@ -1827,13 +1833,13 @@
"name": "Passport",
"description": "",
"created_at": "2020-07-01T10:37:43.078Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "PassportFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.757Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "PensionBag",
@@ -2615,6 +2621,12 @@
"created_at": "2021-01-28T14:00:38.585Z",
"pageName": "Buildings"
},
{
"name": "Translate",
"description": "",
"created_at": "2023-01-18T10:52:22.311Z",
"pageName": "Interface"
},
{
"name": "Truck",
"description": "",
@@ -2643,13 +2655,13 @@
"name": "Unlocked",
"description": "",
"created_at": "2020-07-01T10:37:42.823Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "UnlockedFilled",
"description": "",
"created_at": "2021-01-11T13:37:55.317Z",
"pageName": "Privacy and secutity"
"pageName": "Privacy and security"
},
{
"name": "Up",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "2.0.11",
"version": "2.0.18",
"description": "Aksel icons for NAV",
"author": "Aksel | NAV designsystem team",
"repository": {
+3 -1
View File
@@ -1,3 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0ZM12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM13 6V11H18V13H13V18H11V13H6V11H11V6H13Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 2.5C6.64137 2.5 2.5 6.64137 2.5 11.75C2.5 16.8586 6.64137 21 11.75 21C16.8586 21 21 16.8586 21 11.75C21 6.64137 16.8586 2.5 11.75 2.5ZM1 11.75C1 5.81294 5.81294 1 11.75 1C17.6871 1 22.5 5.81294 22.5 11.75C22.5 17.6871 17.6871 22.5 11.75 22.5C5.81294 22.5 1 17.6871 1 11.75Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 12.75H7V11.25H17V12.75Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.25 17L11.25 7L12.75 7L12.75 17H11.25Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 435 B

After

Width:  |  Height:  |  Size: 655 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0ZM13 6V11H18V13H13V18H11V13H6V11H11V6H13Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 1C5.81294 1 1 5.81294 1 11.75C1 17.6871 5.81294 22.5 11.75 22.5C17.6871 22.5 22.5 17.6871 22.5 11.75C22.5 5.81294 17.6871 1 11.75 1ZM11.25 12.75V17H12.75V12.75H17V11.25H12.75V7H11.25V11.25H7V12.75H11.25Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 323 B

After

Width:  |  Height:  |  Size: 381 B

+2 -1
View File
@@ -1,3 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 12C2 6.81465 5.94668 2.5511 11 2.04938V12.4142L18.3288 19.743C16.6044 21.1544 14.4017 22 12 22C6.47715 22 2 17.5228 2 12ZM19.7488 21.163C17.6587 22.9321 14.9533 24 12 24C5.37258 24 0 18.6274 0 12C0 5.70934 4.84047 0.549225 11 0.0410738V0H12H13V0.0410738C19.1595 0.549225 24 5.70934 24 12C24 14.9533 22.9321 17.6587 21.163 19.7488L21.1924 19.7782L20.4853 20.4853L19.7782 21.1924L19.7488 21.163ZM19.743 18.3288C21.1543 16.6044 22 14.4017 22 12C22 6.81465 18.0533 2.5511 13 2.04938V11.5858L19.743 18.3288Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75ZM1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.25 2.5H12.75V12.1729L19.5103 18.4504L18.4897 19.5496L11.25 12.8271V2.5Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 676 B

After

Width:  |  Height:  |  Size: 616 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 12V0.0410767C4.84047 0.549228 0 5.70934 0 12C0 18.6274 5.37258 24 12 24C14.9922 24 17.7286 22.9048 19.8303 21.0935L11 12ZM24 12C24 12.9017 23.9005 13.7803 23.712 14.6252C23.297 16.4847 22.4505 18.1814 21.2831 19.6048L13 11V0.0410767C18.2766 0.476386 22.5852 4.32557 23.712 9.37485C23.9005 10.2198 24 11.0983 24 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.25 1.27576C5.66285 1.6608 1.25 6.31506 1.25 12C1.25 17.9371 6.06294 22.75 12 22.75C14.5711 22.75 16.9313 21.8474 18.7812 20.3418L11.25 12.8107V1.27576ZM19.8766 19.3159C21.6596 17.3972 22.75 14.8259 22.75 12C22.75 6.31506 18.3372 1.6608 12.75 1.27576V12.1893L19.8766 19.3159Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 489 B

After

Width:  |  Height:  |  Size: 449 B

+2 -1
View File
@@ -1,3 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0C18.6274 0 24 5.37258 24 12C24 18.6274 18.6274 24 12 24C5.37258 24 0 18.6274 0 12C0 5.37258 5.37258 0 12 0ZM12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM18 11H6V13H18V11Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 2.5C6.64137 2.5 2.5 6.64137 2.5 11.75C2.5 16.8586 6.64137 21 11.75 21C16.8586 21 21 16.8586 21 11.75C21 6.64137 16.8586 2.5 11.75 2.5ZM1 11.75C1 5.81294 5.81294 1 11.75 1C17.6871 1 22.5 5.81294 22.5 11.75C22.5 17.6871 17.6871 22.5 11.75 22.5C5.81294 22.5 1 17.6871 1 11.75Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 12.75H7V11.25H17V12.75Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 413 B

After

Width:  |  Height:  |  Size: 546 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M24 12C24 5.37258 18.6274 0 12 0C5.37258 0 0 5.37258 0 12C0 18.6274 5.37258 24 12 24C18.6274 24 24 18.6274 24 12ZM18 11H6V13H18V11Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.75 1C5.81294 1 1 5.81294 1 11.75C1 17.6871 5.81294 22.5 11.75 22.5C17.6871 22.5 22.5 17.6871 22.5 11.75C22.5 5.81294 17.6871 1 11.75 1ZM7 12.75H17V11.25H7V12.75Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 336 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C9.79085 2 7.99999 3.79086 7.99999 6C7.99999 6.66187 8.16311 7.29714 8.45828 7.85918C6.00646 9.12956 5.6173 13.1739 8.76271 14.4845L12.7692 16.1538C13.5145 16.4644 14 17.1926 14 18C14 19.1046 13.1046 20 12 20C10.8954 20 9.99999 19.1046 9.99999 18H7.99999C7.99999 20.2091 9.79085 22 12 22C14.2091 22 16 20.2091 16 18C16 17.3381 15.8369 16.7029 15.5417 16.1408C17.9935 14.8704 18.3827 10.8261 15.2373 9.51554L11.2308 7.84615C10.4855 7.53561 9.99999 6.8074 9.99999 6C9.99999 4.89543 10.8954 4 12 4C13.1046 4 14 4.89543 14 6H16C16 3.79086 14.2091 2 12 2ZM13.9738 14.5208C15.6075 14.4232 16.1245 12.0519 14.4681 11.3617L10.4615 9.69231C10.311 9.62957 10.1657 9.55832 10.0262 9.47924C8.39252 9.57681 7.87544 11.9481 9.53194 12.6383L13.5385 14.3077C13.689 14.3704 13.8343 14.4417 13.9738 14.5208Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 965 B

+13
View File
@@ -0,0 +1,13 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5 19.5L15.5 10.5L19.5 19.5" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 17H18" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<mask id="mask0_6814_1365" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="2" y="4" width="15" height="17">
<path d="M9.90083 18.7893L13.9008 9.78926C14.1817 9.15728 14.8084 8.75 15.5 8.75C16.1193 8.75 16.6865 9.07657 17.0001 9.59861V4H2.00005V21H10.5983C9.85068 20.5519 9.53784 19.606 9.90083 18.7893Z" fill="black"/>
</mask>
<g mask="url(#mask0_6814_1365)">
<path d="M4 7.5H16" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 7.5V5.5" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 7.5L13.4116 7.78744C12.2005 11.7232 9.30115 14.9162 5.5 16.5" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.5 7.5L6.58844 7.78744C7.79946 11.7232 10.6989 14.9162 14.5 16.5" stroke="#262626" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-css-internal
## 2.0.18
## 2.0.17
## 2.0.16
## 2.0.15
## 2.0.14
## 2.0.13
## 2.0.12
## 2.0.11
## 2.0.10
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "2.0.11",
"version": "2.0.18",
"description": "CSS for NAV internal Designsystem-components",
"author": "Aksel | NAV designsystem team",
"keywords": [
+56
View File
@@ -1,5 +1,61 @@
# @navikt/ds-react-internal
## 2.0.18
### Patch Changes
- Updated dependencies [[`98177d0cd`](https://github.com/navikt/Designsystemet/commit/98177d0cd3802029dcf398ce93c1767d3b0860c5)]:
- @navikt/ds-react@2.0.18
- @navikt/ds-icons@2.0.18
## 2.0.17
### Patch Changes
- Updated dependencies [[`27e3dfee0`](https://github.com/navikt/Designsystemet/commit/27e3dfee07e135893e9f62cd32f80ed83a3510de)]:
- @navikt/ds-icons@2.0.17
- @navikt/ds-react@2.0.17
## 2.0.16
### Patch Changes
- Updated dependencies [[`54f8b0795`](https://github.com/navikt/Designsystemet/commit/54f8b07956bbfb7de51f6682a5fc64903bfd1bdf)]:
- @navikt/ds-icons@2.0.16
- @navikt/ds-react@2.0.16
## 2.0.15
### Patch Changes
- Updated dependencies [[`22dfd8e60`](https://github.com/navikt/Designsystemet/commit/22dfd8e60315c421749394d35e41f412a00a7593)]:
- @navikt/ds-react@2.0.15
- @navikt/ds-icons@2.0.15
## 2.0.14
### Patch Changes
- Updated dependencies [[`8e5c55443`](https://github.com/navikt/Designsystemet/commit/8e5c554431c98b1b658c5054c0b3cf08b8a65e52)]:
- @navikt/ds-react@2.0.14
- @navikt/ds-icons@2.0.14
## 2.0.13
### Patch Changes
- Updated dependencies [[`a6c339123`](https://github.com/navikt/Designsystemet/commit/a6c3391237f13394063e4c004ac9efb1875fc944)]:
- @navikt/ds-icons@2.0.13
- @navikt/ds-react@2.0.13
## 2.0.12
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.12
- @navikt/ds-icons@2.0.12
## 2.0.11
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "2.0.11",
"version": "2.0.18",
"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.0.11",
"@navikt/ds-react": "^2.0.11",
"@navikt/ds-icons": "^2.0.18",
"@navikt/ds-react": "^2.0.18",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
+1 -6
View File
@@ -65,11 +65,6 @@ Blir brukt flere keys i .env under `./website`, men kun `SANITY_PRIVATE_NO_DRAFT
- SANITY_WRITE_KEY:
For å sende dokumenter til sanity, brukt til å oppdatere sandboxes/examples/farger. Trengs bare hvis kode skal synkes fra lokal branch
- ALGOLIA_ADMIN:
For å oppdatere records i søkemotoren. Trengs bare hvis man oppdaterer søkeindexen lokalt.
- ALGOLIA_ID:
Søkemotor index-id for å redigere riktig Index. Trengs bare for at søk skal fungere lokalt
- TRELLO_TOKEN: Sender feedback til et egent trello-board. Ikke nødvendig lokalt hvis man ikke vil teste feedback-modulen.
- SANITY_PREVIEW_TOKEN: Gir appen tilgang til å lese draft innhold fra sanity i "preview"-mode. Trengs for å teste preview-sider
- SANITY_PRIVATE_NO_DRAFTS: Gir appen tilgang til å lese innhold fra Sanity da datasettet er privat
@@ -89,4 +84,4 @@ Kjøres backups hver 3 dag til GCP-bucket under `designsystem-prod`
Spørsmål og kontakt kan rettes til team Aksel
Aksel har også en egen slack-kanal #aksel
Aksel har også en egen Slack-kanal #Aksel-designsystemet
-54
View File
@@ -1,54 +0,0 @@
{
"index_name": "aksel_docsearch",
"start_urls": [
"https://aksel.nav.no/",
{
"url": "https://aksel.nav.no/designsystem",
"tags": ["designsystem", "docs"]
},
{
"url": "https://aksel.nav.no/god-praksis/",
"tags": ["aksel"],
"selectors_key": "aksel"
},
{
"url": "https://aksel.nav.no/produktbloggen/",
"tags": ["aksel"],
"selectors_key": "aksel"
},
{
"url": "https://aksel.nav.no/prinsipper/",
"tags": ["aksel"],
"selectors_key": "aksel"
}
],
"selectors": {
"default": {
"lvl0": {
"selector": "h1.algolia-index-lvl1",
"global": true
},
"lvl1": ".algolia-index-tabs--active",
"lvl2": "h2.algolia-index-lvl2",
"lvl3": "h3.algolia-index-lvl3",
"text": "p.algolia-index-body, p.algolia-index-ingress"
},
"aksel": {
"lvl0": {
"selector": "h1.algolia-index-lvl1",
"global": true
},
"lvl1": "h2.algolia-index-lvl2",
"lvl2": "h3.algolia-index-lvl3",
"text": "p.algolia-index-body, p.algolia-index-ingress"
}
},
"selectors_exclude": [".algolia-ignore-index"],
"stop_urls": [
"https://aksel.nav.no/preview",
"https://old-design-nav.vercel.app",
"https://aksel.nav.no/eksempler"
],
"sitemap_urls": ["https://aksel.nav.no/api/sitemap"],
"js_render": true
}
+8 -8
View File
@@ -15,14 +15,14 @@
"website"
],
"dependencies": {
"@navikt/ds-codemod": "^2.0.11",
"@navikt/ds-css": "^2.0.11",
"@navikt/ds-css-internal": "^2.0.11",
"@navikt/ds-icons": "^2.0.11",
"@navikt/ds-react": "^2.0.11",
"@navikt/ds-react-internal": "^2.0.11",
"@navikt/ds-tailwind": "^2.0.11",
"@navikt/ds-tokens": "^2.0.11"
"@navikt/ds-codemod": "^2.0.18",
"@navikt/ds-css": "^2.0.18",
"@navikt/ds-css-internal": "^2.0.18",
"@navikt/ds-icons": "^2.0.18",
"@navikt/ds-react": "^2.0.18",
"@navikt/ds-react-internal": "^2.0.18",
"@navikt/ds-tailwind": "^2.0.18",
"@navikt/ds-tokens": "^2.0.18"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.1.13"
+1 -1
View File
@@ -1,2 +1,2 @@
.yarn/cache
production.tar.gz
*.tar.gz
@@ -62,8 +62,8 @@ export default function SetPrivateAction(props) {
dele offentlig kan medføre eks omdømmetap og uønsket oppmerksomhet
utenfra. Dobbelsjekk med temaansvarlig og andre som har skrevet
artikkelen før du velger å åpne innholdet for alle. Er du usikker
er det bare å sende en melding på #aksel eller #aksel-redaktører
på slack.
er det bare å sende en melding på #Aksel-designsystemet eller
#aksel-redaktører på Slack.
</BodyLong>
) : (
<>
@@ -75,8 +75,8 @@ const IntroPage = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
>
<ReadMore header="Har du ikke de rollene du trenger?">
Send en melding til oss på{" "}
<Link href="https://nav-it.slack.com/archives/C0370ADS0HX">
#Aksel
<Link href="https://nav-it.slack.com/archives/C7NE7A8UF">
#Aksel-designsystemet
</Link>{" "}
slack så fikser vi det.
</ReadMore>
@@ -1,31 +0,0 @@
import React from "react";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const AkselLogo = (props): JSX.Element => (
<svg
focusable="false"
aria-hidden="true"
viewBox="0 0 28 28"
width="28"
height="28"
fill="none"
{...props}
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m3 9 5.268-5.268A2.5 2.5 0 0 1 10.036 3H22.5A2.5 2.5 0 0 1 25 5.5v12.465a2.5 2.5 0 0 1-.732 1.767L19 25"
></path>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m3 9 5.232-5.232a2.5 2.5 0 0 1 3.536 0l12.464 12.464a2.5 2.5 0 0 1 0 3.536L19 25m-7-9-9 9"
></path>
</svg>
);
export default AkselLogo;
@@ -1,116 +0,0 @@
import React from "react";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const FigmaIcon = ({ ...props }): JSX.Element => (
<svg
{...props}
width="1em"
height="1em"
viewBox="0 0 18 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable="false"
aria-label="Figma"
aria-hidden
>
<path
d="M15.5 4.99999C15.5 6.93299 13.9531 8.49999 12.0449 8.49999H8.5V1.5H12.0449C13.9531 1.5 15.5 3.067 15.5 4.99999Z"
fill="#FF7262"
stroke="#262626"
/>
<path
d="M1.5 4.99999C1.5 6.93299 3.04691 8.49999 4.95513 8.49999H8.5V1.5H4.95513C3.04691 1.5 1.5 3.067 1.5 4.99999Z"
fill="#F24E1E"
stroke="#262626"
/>
<path
d="M1.5 12C1.5 13.933 3.04691 15.5 4.95513 15.5H8.5V8.5H4.95513C3.04691 8.5 1.5 10.067 1.5 12Z"
fill="#A259FF"
stroke="#262626"
/>
<path
d="M1.5 19C1.5 20.933 3.0692 22.5 4.97742 22.5C6.91042 22.5 8.5 20.9126 8.5 18.9545V15.5H4.95513C3.04691 15.5 1.5 17.067 1.5 19Z"
fill="#0ACF83"
stroke="#262626"
/>
<path
d="M8.5 12C8.5 13.933 10.0469 15.5 11.9551 15.5H12.0449C13.9531 15.5 15.5 13.933 15.5 12C15.5 10.067 13.9531 8.5 12.0449 8.5H11.9551C10.0469 8.5 8.5 10.067 8.5 12Z"
fill="#1ABCFE"
stroke="#262626"
/>
</svg>
);
export const FigmaIconNoSync = ({ ...props }): JSX.Element => (
<svg
{...props}
width="1.5rem"
height="1.5rem"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable="false"
aria-label="Figma ikke i sync"
>
<path d="M1.5 22.5L22.5 1.5" stroke="#BA3A26" strokeWidth="2" />
<path
d="M18.5 4.99999C18.5 6.93299 16.9531 8.49999 15.0449 8.49999H11.5V1.5H15.0449C16.9531 1.5 18.5 3.067 18.5 4.99999Z"
stroke="#262626"
/>
<path
d="M4.5 4.99999C4.5 6.93299 6.04691 8.49999 7.95513 8.49999H11.5V1.5H7.95513C6.04691 1.5 4.5 3.067 4.5 4.99999Z"
stroke="#262626"
/>
<path
d="M4.5 12C4.5 13.933 6.04691 15.5 7.95513 15.5H11.5V8.5H7.95513C6.04691 8.5 4.5 10.067 4.5 12Z"
stroke="#262626"
/>
<path
d="M4.5 19C4.5 20.933 6.0692 22.5 7.97742 22.5C9.91042 22.5 11.5 20.9126 11.5 18.9545V15.5H7.95513C6.04691 15.5 4.5 17.067 4.5 19Z"
stroke="#262626"
/>
<path
d="M11.5 12C11.5 13.933 13.0469 15.5 14.9551 15.5H15.0449C16.9531 15.5 18.5 13.933 18.5 12C18.5 10.067 16.9531 8.5 15.0449 8.5H14.9551C13.0469 8.5 11.5 10.067 11.5 12Z"
stroke="#262626"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M15 17.335H16.6664C15.8573 17.9444 15.3333 18.9147 15.3333 20.0081C15.3333 21.319 16.0865 22.453 17.1812 23.0001L17.4786 22.402C16.6014 21.9636 16 21.056 16 20.0081C16 19.0192 16.5357 18.1551 17.3333 17.6925V19.674H18V16.6667H15V17.335ZM22.6667 19.9921C22.6667 21.0855 22.1427 22.0558 21.3336 22.6651H23V23.3334L20 23.3334V20.3262H20.6667V22.3076C21.4643 21.8451 22 20.981 22 19.9921C22 18.9442 21.3986 18.0366 20.5214 17.5982L20.8188 17.0001C21.9135 17.5472 22.6667 18.6811 22.6667 19.9921Z"
fill="#262626"
/>
</svg>
);
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const FigmaIconGrayScale = ({ ...props }): JSX.Element => (
<svg
width="18"
height="26"
viewBox="0 0 18 26"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
aria-label="Figma ikon"
focusable="false"
>
<g clipPath="url(#clip0)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.459473 5.44999C0.459473 2.97008 2.46984 0.959717 4.94975 0.959717H8.06672H9.53756H12.6545C15.1344 0.959717 17.1448 2.97008 17.1448 5.44999C17.1448 7.02029 16.3387 8.40232 15.1178 9.2049C16.3387 10.0075 17.1448 11.3895 17.1448 12.9598C17.1448 15.4397 15.1344 17.4501 12.6545 17.4501H12.557C11.3944 17.4501 10.335 17.0082 9.53756 16.2833V17.4501V20.4207C9.53756 22.9336 7.47466 24.9597 4.97398 24.9597C2.50023 24.9597 0.459473 22.9555 0.459473 20.4694C0.459473 18.8992 1.26547 17.5172 2.48632 16.7146C1.26547 15.912 0.459473 14.53 0.459473 12.9598C0.459473 11.3895 1.26553 10.0075 2.48647 9.2049C1.26553 8.40232 0.459473 7.02029 0.459473 5.44999ZM8.06672 12.9598V9.94037H4.94975C3.28215 9.94037 1.93031 11.2922 1.93031 12.9598C1.93031 14.6214 3.2725 15.9696 4.93186 15.9792L4.94975 15.9792H8.06672V12.9598ZM9.53756 12.9598C9.53756 14.6274 10.8894 15.9792 12.557 15.9792H12.6545C14.3221 15.9792 15.674 14.6274 15.674 12.9598C15.674 11.2922 14.3221 9.94037 12.6545 9.94037H12.557C10.8894 9.94037 9.53756 11.2922 9.53756 12.9598ZM4.94975 17.4501L4.93195 17.45C3.27255 17.4596 1.93031 18.8078 1.93031 20.4694C1.93031 22.1309 3.30021 23.4889 4.97398 23.4889C6.67467 23.4889 8.06672 22.1091 8.06672 20.4207V17.4501H4.94975ZM4.94975 2.43055H8.06672V8.46943H4.94975C3.28215 8.46943 1.93031 7.11758 1.93031 5.44999C1.93031 3.7824 3.28215 2.43055 4.94975 2.43055ZM9.53756 8.46943V2.43055H12.6545C14.3221 2.43055 15.674 3.7824 15.674 5.44999C15.674 7.11758 14.3221 8.46943 12.6545 8.46943H9.53756Z"
fill="var(--a-text-subtle)"
/>
</g>
<defs>
<clipPath id="clip0">
<rect
width="18"
height="25"
fill="white"
transform="translate(0 0.5)"
/>
</clipPath>
</defs>
</svg>
);
@@ -0,0 +1,73 @@
export const ChangelogIcon = () => (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
aria-hidden
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.4688 2.26716C10.3077 1.83185 9.69206 1.83185 9.53098 2.26716L9.26942 2.97401C9.21878 3.11087 9.11087 3.21877 8.97401 3.26942L8.26716 3.53098C7.83185 3.69206 7.83185 4.30775 8.26716 4.46883L8.97401 4.73039C9.11087 4.78103 9.21878 4.88894 9.26942 5.0258L9.53098 5.73265C9.69206 6.16796 10.3077 6.16796 10.4688 5.73265L10.7304 5.0258C10.781 4.88894 10.8889 4.78103 11.0258 4.73039L11.7327 4.46883C12.168 4.30775 12.168 3.69206 11.7327 3.53098L11.0258 3.26942C10.8889 3.21877 10.781 3.11087 10.7304 2.97401L10.4688 2.26716ZM4.53098 5.26715C4.69206 4.83185 5.30775 4.83185 5.46883 5.26716L6.00048 6.70392C6.05112 6.84078 6.15903 6.94868 6.29589 6.99933L7.73265 7.53098C8.16796 7.69206 8.16796 8.30775 7.73265 8.46883L6.29589 9.00048C6.15903 9.05112 6.05112 9.15903 6.00048 9.29589L5.46883 10.7327C5.30775 11.168 4.69206 11.168 4.53098 10.7326L3.99933 9.29589C3.94868 9.15903 3.84078 9.05112 3.70392 9.00048L2.26716 8.46883C1.83185 8.30775 1.83185 7.69206 2.26716 7.53098L3.70392 6.99933C3.84078 6.94868 3.94868 6.84078 3.99933 6.70392L4.53098 5.26715ZM12.531 8.26716C12.6921 7.83185 13.3077 7.83185 13.4688 8.26716L14.5407 11.1637C14.5913 11.3006 14.6992 11.4085 14.8361 11.4591L17.7326 12.531C18.168 12.6921 18.168 13.3077 17.7326 13.4688L14.8361 14.5407C14.6992 14.5913 14.5913 14.6992 14.5407 14.8361L13.4688 17.7326C13.3078 18.168 12.6921 18.168 12.531 17.7326L11.4591 14.8361C11.4085 14.6992 11.3006 14.5913 11.1637 14.5407L8.26716 13.4688C7.83185 13.3077 7.83185 12.6921 8.26716 12.531L11.1637 11.4591C11.3006 11.4085 11.4085 11.3006 11.4591 11.1637L12.531 8.26716Z"
fill="currentColor"
/>
</svg>
);
export const FigmaIcon = () => (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
aria-hidden
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3 4C3 1.80306 4.76151 0 6.96154 0H9H10H11H13.0385C15.2385 0 17 1.80306 17 4C17 5.19041 16.4828 6.26518 15.6589 7.00012C16.4828 7.73506 17 8.80982 17 10.0002C17 12.1972 15.2385 14.0002 13.0385 14.0002H12.9615C12.2462 14.0002 11.5772 13.8096 11 13.4768V14.0002V15.9608C11 18.1876 9.19358 19.9998 6.98065 19.9998C4.78895 19.9998 3 18.2051 3 15.9998C3 14.8095 3.51701 13.7349 4.34067 13C3.51701 12.2651 3 11.1905 3 10.0002C3 8.80983 3.51718 7.73506 4.34108 7.00012C3.51718 6.26518 3 5.19041 3 4ZM9 10.0002V8.00024H6.96154C5.89033 8.00024 5 8.88346 5 10.0002C5 11.1046 5.87059 11.9805 6.92578 11.9999L6.96154 11.9998H9V10.0002ZM11 10.0002C11 11.117 11.8903 12.0002 12.9615 12.0002H13.0385C14.1097 12.0002 15 11.117 15 10.0002C15 8.88346 14.1097 8.00024 13.0385 8.00024H12.9615C11.8903 8.00024 11 8.88346 11 10.0002ZM6.96154 14.0002L6.92578 14.0001C5.87059 14.0195 5 14.8954 5 15.9998C5 17.1081 5.90111 17.9998 6.98065 17.9998C8.08142 17.9998 9 17.0907 9 15.9608V14.0002H6.96154ZM6.96154 2H9V6H6.96154C5.89033 6 5 5.11678 5 4C5 2.88323 5.89033 2 6.96154 2ZM11 6V2H13.0385C14.1097 2 15 2.88323 15 4C15 5.11678 14.1097 6 13.0385 6H11Z"
fill="currentColor"
/>
</svg>
);
export const GithubIcon = () => (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
aria-hidden
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9.9702 0C4.45694 0 0 4.4898 0 10.0443C0 14.4843 2.85571 18.2427 6.81735 19.5729C7.31265 19.6729 7.49408 19.3567 7.49408 19.0908C7.49408 18.858 7.47775 18.0598 7.47775 17.2282C4.70429 17.8269 4.12673 16.0308 4.12673 16.0308C3.68102 14.8667 3.02061 14.5675 3.02061 14.5675C2.11286 13.9522 3.08673 13.9522 3.08673 13.9522C4.09367 14.0188 4.62204 14.9833 4.62204 14.9833C5.51327 16.5131 6.94939 16.0808 7.52714 15.8147C7.60959 15.1661 7.87388 14.7171 8.15449 14.4678C5.94245 14.2349 3.6151 13.3702 3.6151 9.51204C3.6151 8.41449 4.01102 7.51653 4.63837 6.81816C4.53939 6.56878 4.19265 5.53755 4.73755 4.15735C4.73755 4.15735 5.57939 3.89122 7.47755 5.18837C8.29022 4.9685 9.12832 4.85666 9.9702 4.85571C10.812 4.85571 11.6702 4.97224 12.4627 5.18837C14.361 3.89122 15.2029 4.15735 15.2029 4.15735C15.7478 5.53755 15.4008 6.56878 15.3018 6.81816C15.9457 7.51653 16.3253 8.41449 16.3253 9.51204C16.3253 13.3702 13.998 14.2182 11.7694 14.4678C12.1327 14.7837 12.4461 15.3822 12.4461 16.3302C12.4461 17.6771 12.4298 18.7582 12.4298 19.0906C12.4298 19.3567 12.6114 19.6729 13.1065 19.5731C17.0682 18.2424 19.9239 14.4843 19.9239 10.0443C19.9402 4.4898 15.4669 0 9.9702 0Z"
fill="currentColor"
/>
</svg>
);
export const YarnIcon = () => (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
focusable={false}
aria-hidden
>
<path
d="M19.0336 16.0116C18.0026 16.2564 17.4807 16.482 16.2049 17.3131C14.2075 18.6018 12.0297 19.201 12.0297 19.201C12.0297 19.201 11.8493 19.4716 11.3274 19.5941C10.4253 19.8131 7.02969 20 6.72041 20.0064C5.88923 20.0129 5.38021 19.7938 5.23845 19.4523C4.80675 18.4214 5.85701 17.9704 5.85701 17.9704C5.85701 17.9704 5.62505 17.8286 5.48974 17.6997C5.36732 17.5773 5.23845 17.3325 5.19979 17.4227C5.03871 17.8157 4.95495 18.7758 4.52325 19.2075C3.93046 19.8067 2.80933 19.6069 2.14567 19.259C1.41758 18.8724 2.19722 17.9639 2.19722 17.9639C2.19722 17.9639 1.80418 18.1959 1.48845 17.7191C1.20495 17.2809 0.940773 16.5335 1.01165 15.6121C1.10186 14.549 2.27454 13.5309 2.27454 13.5309C2.27454 13.5309 2.06835 11.9781 2.7449 10.3866C3.35701 8.93685 5.00649 7.77061 5.00649 7.77061C5.00649 7.77061 3.62119 6.24355 4.13665 4.85824C4.4717 3.95618 4.60701 3.96262 4.71655 3.92396C5.10314 3.77577 5.47686 3.61468 5.75392 3.31185C7.13923 1.817 8.90469 2.10051 8.90469 2.10051C8.90469 2.10051 9.72943 -0.431708 10.5026 0.0644255C10.741 0.219065 11.598 2.12628 11.598 2.12628C11.598 2.12628 12.5129 1.59149 12.616 1.79123C13.1702 2.86726 13.2346 4.92267 12.9897 6.17267C12.5774 8.23453 11.5464 9.34278 11.1341 10.0387C11.0374 10.1997 12.2423 10.7088 13.0026 12.8157C13.7049 14.7423 13.0799 16.3595 13.1895 16.5399C13.2088 16.5722 13.2153 16.585 13.2153 16.585C13.2153 16.585 14.0207 16.6495 15.6379 15.6508C16.5013 15.116 17.5258 14.5167 18.6921 14.5039C19.8196 14.4845 19.8776 15.8118 19.0336 16.0116Z"
fill="currentColor"
/>
</svg>
);
@@ -1,5 +1,5 @@
export * from "./FigmaIcon";
export { default as NavLogoWhite } from "./NavLogoWhite";
export { default as NAVLogoDark } from "./NavLogoDark";
export * from "./Logo";
export * from "./Icons";
@@ -36,9 +36,9 @@ const Footer = () => {
<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/C0370ADS0HX"
href="https://nav-it.slack.com/archives/C7NE7A8UF"
>
#Aksel på Slack
#Aksel-designsystemet på Slack
</Link>
</li>
<li>
@@ -1,8 +1,12 @@
import { FeedbackT } from "@/lib";
import { IdContext } from "@/utils";
import { Button, Heading, Label, Textarea } from "@navikt/ds-react";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useContext, useEffect, useState } from "react";
const FooterForm = () => {
const idCtx = useContext(IdContext);
const [contactForm, setContactForm] = useState({
content: "",
hasWritten: false,
@@ -27,12 +31,16 @@ const FooterForm = () => {
if (fail) return;
setContentError({ content: "" });
fetch("/api/generalFeedback", {
const body: FeedbackT = {
message: contactForm.content,
url: `${basePath}${asPath}`,
type: "footer",
docId: idCtx?.id,
};
fetch("/api/feedback", {
method: "POST",
body: JSON.stringify({
message: contactForm.content,
url: `${basePath}${asPath}`,
}),
body: JSON.stringify(body),
});
setSent({ status: true });
@@ -54,15 +54,18 @@ const AkselArtikkelTemplate = ({
: `Relevante artikler`}
</Heading>
<div className="card-grid-3-1 mt-6 px-4">
{data.relevante_artikler.map((x: any) => (
<ArtikkelCard {...x} key={x._id} />
))}
{data.relevante_artikler.map((x: any) =>
x && x?._id ? <ArtikkelCard {...x} key={x._id} /> : null
)}
</div>
</div>
</div>
</aside>
);
const filteredTema =
hasTema && data?.tema?.filter((x: any) => x?.title && x?.slug);
return (
<>
<Head>
@@ -136,7 +139,7 @@ const AkselArtikkelTemplate = ({
</div>
{hasTema && (
<div className="mt-8 flex flex-wrap gap-2">
{data.tema.map(({ title, slug }: any) => (
{filteredTema.map(({ title, slug }: any) => (
<span key={title}>
<NextLink
key={title}
@@ -125,7 +125,14 @@ export const WithSidebar = ({
</div>
</div>
{variant === "page" && pageProps.status?.bilde && (
<div className="relative hidden aspect-square h-[12.5rem] lg:block xl:mr-40">
<div
className={cl(
"relative hidden aspect-square h-[12.5rem] lg:block xl:mr-40",
{
"hue-rotate-[65deg]": pageProps?.status?.tag === "beta",
}
)}
>
<Image
src={urlFor(pageProps.status?.bilde).auto("format").url()}
decoding="async"
@@ -63,7 +63,11 @@ const NavItem = ({
: "info"
}
>
{link.tag}
{link.tag === "new"
? "ny"
: link.tag === "deprecated"
? "Avviklet"
: link.tag}
</Tag>
)}
</span>
@@ -130,7 +134,17 @@ export const Sidebar = ({
...x,
pages: links
.filter((y) => y?.kategori === x.value)
.sort((a, b) => a?.heading.localeCompare(b?.heading)),
.sort((a, b) => {
if (a?.tag === "deprecated" && b?.tag === "deprecated") {
return 0;
} else if (a?.tag === "deprecated") {
return 1;
} else if (b.tag === "deprecated") {
return -1;
}
return a?.heading.localeCompare(b?.heading);
}),
}))
.filter((x) => !(!x.pages || x.pages.length === 0)),
[links, kategori]
@@ -11,7 +11,12 @@ interface AkselTemaT extends SanityT.Schema.aksel_tema {
}
const GodPraksisCard = ({ node }: { node: AkselTemaT }) => {
if (!node?.pictogram || !node?.slug?.current || !node?.title) {
if (
!node?.pictogram ||
!node?.slug?.current ||
!node?.title ||
!node?.refCount
) {
return null;
}
@@ -43,7 +48,7 @@ const GodPraksisCard = ({ node }: { node: AkselTemaT }) => {
</NextLink>
<BodyShort className={cl("mb-2 lg:mb-6")}>{node.oppsummering}</BodyShort>
<BodyShort size="small" className="text-text-subtle">
{node.refCount} ARTIKLER
{node.refCount === 1 ? "1 ARTIKKEL" : `${node.refCount} ARTIKLER`}
</BodyShort>
</li>
);
@@ -3,10 +3,11 @@ import { withErrorBoundary } from "@/error-boundary";
import { SanityT } from "@/lib";
import { BodyLong, Link, Chips } from "@navikt/ds-react";
import cl from "classnames";
import { useEffect, useId, useState } from "react";
import { useEffect, useState } from "react";
import { CodeSandbox } from "./CodeSandbox";
const iframePadding = 192;
const iframeId = "example-iframe";
const ComponentExamples = ({
node,
@@ -16,22 +17,21 @@ const ComponentExamples = ({
filnavn?: SanityT.Schema.kode_eksempler_fil;
};
}): JSX.Element => {
const [iframeHeight, setIframeHeight] = useState(300);
const [activeExample, setActiveExample] = useState(null);
const iframeId = useId();
const [frameState, setFrameState] = useState(300);
const handleExampleLoad = (id: string) => {
const handleExampleLoad = () => {
let attempts = 0;
const waitForExampleContentToRender = setInterval(() => {
const exampleIframe = document.getElementById(id) as HTMLIFrameElement;
const exampleIframe = document.getElementById(
iframeId
) as HTMLIFrameElement;
const exampleIframeDOM = exampleIframe?.contentDocument;
const exampleWrapper = exampleIframeDOM?.getElementById("ds-example");
if (exampleWrapper) {
const newHeight = iframePadding + exampleWrapper.offsetHeight;
setIframeHeight(newHeight);
clearInterval(waitForExampleContentToRender);
setFrameState(newHeight < 300 ? 300 : newHeight);
}
attempts++;
@@ -56,35 +56,6 @@ const ComponentExamples = ({
.trim()
) ?? str;
const element = (exampleUrl: string, code: string, id: string) => (
<>
<div className="overflow-hidden rounded-t border border-b-0 border-gray-300 bg-gray-50">
<iframe
src={exampleUrl}
height={iframeHeight}
onLoad={() => handleExampleLoad(id)}
id={id}
aria-label="Komponent eksempler"
className="min-w-80 block w-full max-w-full resize-x overflow-auto bg-white shadow-[20px_0_20px_-20px_rgba(0,0,0,0.22)]"
title="Kode-eksempler"
/>
</div>
<div className="xs:justify-end mb-2 flex justify-center gap-2 rounded-b border border-gray-300 px-2 py-1 text-base ">
<CodeSandbox code={code.trim()} />
<Link href={exampleUrl} className="text-gray-900" target="_blank">
Åpne i nytt vindu
</Link>
</div>
<Snippet
node={{
_type: "kode" as const,
code: { code: code.trim(), language: "jsx" },
}}
/>
</>
);
if (
!node.dir?.filer ||
node.dir.filer.length === 0 ||
@@ -94,14 +65,6 @@ const ComponentExamples = ({
return null;
}
if (node.standalone) {
return element(
`/eksempler/${node.filnavn.title.replace(".tsx", "")}`,
node.filnavn?.filer?.[0]?.innhold ?? "",
iframeId
);
}
const active = activeExample ?? node?.dir?.filer?.[0]?.navn;
return (
@@ -122,7 +85,7 @@ const ComponentExamples = ({
})}
</Chips>
</div>
{node.dir.filer.map((fil, xi) => {
{node.dir.filer.map((fil) => {
return (
<div
key={fil._key}
@@ -134,10 +97,46 @@ const ComponentExamples = ({
{fil?.description && (
<BodyLong className="mb-2">{fil.description}</BodyLong>
)}
{element(
`/eksempler/${node.dir.title}/${fil.navn.replace(".tsx", "")}`,
fil.innhold,
iframeId + xi
{active === fil.navn && (
<>
<div className="overflow-hidden rounded-t border border-b-0 border-gray-300 bg-gray-50">
<iframe
src={`/eksempler/${node.dir.title}/${fil.navn.replace(
".tsx",
""
)}`}
height={frameState}
onLoad={() => handleExampleLoad()}
id={iframeId}
aria-label="Komponent eksempler"
className={cl(
"min-w-80 block w-full max-w-full resize-x overflow-auto bg-white shadow-[20px_0_20px_-20px_rgba(0,0,0,0.22)]"
)}
title="Kode-eksempler"
/>
</div>
<div className="xs:justify-end mb-2 flex justify-center gap-2 rounded-b border border-gray-300 px-2 py-1 text-base ">
<CodeSandbox code={fil.innhold.trim()} />
<Link
href={`/eksempler/${node.dir.title}/${fil.navn.replace(
".tsx",
""
)}`}
className="text-gray-900"
target="_blank"
>
Åpne i nytt vindu
</Link>
</div>
<Snippet
node={{
_type: "kode" as const,
code: { code: fil.innhold.trim(), language: "jsx" },
}}
/>
</>
)}
</div>
);
@@ -27,7 +27,16 @@ const ComponentOverview = ({
}
return true;
})
.sort((a, b) => a?.heading?.localeCompare(b?.heading));
.sort((a, b) => {
if (a?.status?.tag === "deprecated" && b?.status?.tag === "deprecated") {
return 0;
} else if (a?.status?.tag === "deprecated") {
return 1;
} else if (b?.status?.tag === "deprecated") {
return -1;
}
return a?.heading?.localeCompare(b?.heading);
});
return (
<div className="mb-8">
@@ -37,7 +46,12 @@ const ComponentOverview = ({
<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">
<div
className={cl(
"flex max-h-44 items-center justify-center overflow-hidden rounded-t-2xl"
"flex max-h-44 items-center justify-center overflow-hidden rounded-t-2xl",
"filter",
{
"hue-rotate-[65deg]": x?.status?.tag === "beta",
grayscale: x?.status?.tag === "deprecated",
}
)}
>
{x.status?.bilde ? (
@@ -162,7 +162,7 @@ const IconSearch = () => {
href="https://nav-it.slack.com/archives/C7NE7A8UF"
target="_blank"
>
#designsystem slack.
#Aksel-designsystemet på Slack.
</Link>
</BodyLong>
<Modal open={open} onClose={() => handleClose()}>
@@ -69,11 +69,10 @@ export const BloggAd = () => {
</BodyLong>
<BodyLong>
Ta kontakt med{" "}
<NextLink
href="https://nav-it.slack.com/archives/C0370ADS0HX"
passHref
>
<Link className="font-semibold text-[#831843]">#Aksel</Link>
<NextLink href="https://nav-it.slack.com/archives/C7NE7A8UF" passHref>
<Link className="font-semibold text-[#831843]">
#Aksel-designsystemet
</Link>
</NextLink>{" "}
på Slack
</BodyLong>
@@ -17,19 +17,19 @@ export const StatusTag = ({
case "new":
return (
<Tag variant="info" size="small">
New
Ny
</Tag>
);
case "ready":
return showStable ? (
<Tag variant="success" size="small">
Stable
Stabil
</Tag>
) : null;
case "deprecated":
return (
<Tag variant="neutral" size="small">
Deprecated
Avviklet
</Tag>
);
default:
@@ -174,9 +174,6 @@ export function TableOfContentsv2({
"text-text-subtle": link.id !== activeId || activeSubId,
}
)}
aria-expanded={
link?.lvl3?.length > 0 && link?.id === activeId
}
>
{link.heading}
</Link>
@@ -7,6 +7,8 @@ export const ScrollTop = () => {
window.scrollTo(0, 0);
}}
className="text-xlarge text-text-on-inverted focus-visible:shadow-focus-inverted group -mt-[10px] flex h-[48px] w-fit items-center justify-center gap-2 rounded p-2 font-semibold hover:underline focus:outline-none"
aria-hidden
id="scroll-top-button"
>
<svg
fill="none"
@@ -76,7 +76,7 @@ export const ToolCard = () => {
</div>
<div>
<NextLink href={t.href} passHref>
<Link className="text-text-default mb-1 font-semibold no-underline hover:underline">
<Link className="text-text-default mb-1 font-semibold">
{t.title}
</Link>
</NextLink>
@@ -1,9 +1,15 @@
import { BodyShort, Button, Heading, Label, Textarea } from "@navikt/ds-react";
import cl from "classnames";
import { useRouter } from "next/router";
import React, { useCallback, useEffect, useRef, useState } from "react";
import { HelpfulArticleEnum, HelpfulArticleT } from "@/lib";
import { AmplitudeEvents, logAmplitudeEvent } from "../utils";
import React, {
useCallback,
useContext,
useEffect,
useRef,
useState,
} from "react";
import { FeedbackT, HelpfulArticleEnum } from "@/lib";
import { AmplitudeEvents, IdContext, logAmplitudeEvent } from "../utils";
const Feedback = ({
docId,
@@ -18,6 +24,7 @@ const Feedback = ({
akselFeedback?: boolean;
text?: string;
}): JSX.Element => {
const idCtx = useContext(IdContext);
const { asPath, basePath } = useRouter();
const [textValue, setTextValue] = useState("");
const [activeState, setActiveState] = useState<HelpfulArticleEnum | null>(
@@ -30,17 +37,22 @@ const Feedback = ({
const [hasLoggedFeedback, setHasLoggedFeedback] = useState(false);
const fetchFeedback = () => {
const msg: HelpfulArticleT = {
answer: activeState,
message: textValue,
url: `${basePath}${asPath}`,
docId: docId,
docType: docType,
const state = {
ja: "ja",
nei: "nei",
misc: "forslag",
};
fetch("/api/helpfulArticleFeedback", {
const body: FeedbackT = {
message: textValue,
url: `${basePath}${asPath}`,
type: state[activeState],
docId: idCtx?.id,
};
fetch("/api/feedback", {
method: "POST",
body: JSON.stringify(msg),
body: JSON.stringify(body),
});
};
@@ -208,6 +220,7 @@ const Feedback = ({
x === HelpfulArticleEnum.MISC ? null : HelpfulArticleEnum.MISC
)
}
id="feedback-forbedringer-button"
>
<Label as="span">Foreslå forbedring</Label>
</Button>
@@ -63,7 +63,10 @@ export const usePageView = (router: Router, pageProps: any) => {
const data = {};
try {
if (pageProps?.page && pageProps.page?._type === "aksel_artikkel") {
data["tema"] = pageProps.page.tema.map((x) => x?.slug?.current);
const tema = pageProps.page.tema.map((x) => x?.slug?.current) ?? null;
if (tema && tema.length > 0) {
data["tema"] = tema;
}
}
} catch (error) {
isDevelopment && console.error(error);
@@ -7,7 +7,7 @@ export * from "./hooks";
export * from "./contexts";
export const dateStr = (date: string) =>
format(new Date(date), "d. MMM YYY", { locale: nbLocale });
format(new Date(date), "d. MMMM YYY", { locale: nbLocale });
export const dateTimeStr = (date: string) =>
format(new Date(date), "d-MM-YYY", { locale: nbLocale });
+2
View File
@@ -10,6 +10,7 @@ test.describe("Axe a11y", () => {
const accessibilityScanResults = await new AxeBuilder({ page })
.disableRules(["definition-list", "scrollable-region-focusable"])
.exclude("iframe")
.exclude("#scroll-top-button")
.analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});
@@ -20,4 +21,5 @@ test.describe("Axe a11y", () => {
Disabled rules:
- definition-list: 'div' as a direct child of 'dl' should be valid. Ignoring failed test.
- scrollable-region-focusable: Up for discussion. Should code-block be focusable fot easier access and allowing scroll with keyboard?
- Excluded "Til toppen" button to avoid error around focusable items with aria-hidden
*/
+15 -13
View File
@@ -167,7 +167,7 @@ export const akselTema = `*[_type == "godpraksis_landingsside"][0]{
${deRefs}
}
},
"temaer": *[_type == "aksel_tema"]{
"temaer": *[_type == "aksel_tema" && defined(seksjoner[].sider[])]{
...,
"refCount": count(*[_type == "aksel_artikkel" && !(_id in path("drafts.**")) && references(^._id)])
},
@@ -233,8 +233,6 @@ export const akselForsideQuery = `*[_type == "aksel_forside"][0]{
}
}`;
export const akselDocumentsByType = `*[_type in $types]{ _type, _id, 'slug': slug.current }`;
export const akselPrinsippBySlug = `{
"prinsipp": *[slug.current == $slug] | order(_updatedAt desc)[0]
{
@@ -282,8 +280,6 @@ export const akselEditorById = `*[_id == $id][0]
${contributorsAll}
}`;
export const dsDocuments = `*[_type in ["komponent_artikkel", "ds_artikkel"]]{ ..., 'slug': slug.current }`;
const sidebarQuery = `"sidebar": *[_type == $type && defined(kategori)] {
heading,
"slug": slug.current,
@@ -291,6 +287,11 @@ const sidebarQuery = `"sidebar": *[_type == $type && defined(kategori)] {
"tag": status.tag,
}`;
/**
* "refs" må disables i preview da next-sanity sin
* preview-funksjonalitet fører til en infinite loop som låser applikasjonen.
* Dette er på grunn av av hele datasettet blir lastet inn i preview flere ganger som til slutt låser vinduet.
*/
export const komponentQuery = `{
"page": *[_type == "komponent_artikkel" && slug.current == $slug] | order(_updatedAt desc)[0]
{
@@ -313,12 +314,15 @@ export const komponentQuery = `{
${deRefs}
},
},
"refs": *[_type == "komponent_artikkel" && count(*[references(^._id)][slug.current == $slug]) > 0][0...3]{
_id,
heading,
"slug": slug,
status
},
"refs": select(
$preview == "true" => [],
$preview != "true" => *[_type == "komponent_artikkel" && count(*[references(^._id)][slug.current == $slug]) > 0][0...3]{
_id,
heading,
"slug": slug,
status
}
),
"seo": *[_type == "komponenter_landingsside"][0].seo.image,
${sidebarQuery}
}`;
@@ -337,8 +341,6 @@ export const grunnleggendeQuery = `{
${sidebarQuery}
}`;
export const akselTemaNames = `*[_type == "aksel_tema" && count(*[references(^._id)]) > 0].slug`;
export const akselTemaDocs = `{
"tema": *[_type == "aksel_tema" && slug.current == $slug] | order(_updatedAt desc)[0]{
...,
+78 -47
View File
@@ -1,6 +1,4 @@
import imageUrlBuilder from "@sanity/image-url";
import { SanityT } from "..";
import { akselDocumentsByType, akselTemaNames, dsDocuments } from "./queries";
import { getClient, noCdnClient, sanityClient } from "./sanity.server";
const imageBuilder = imageUrlBuilder(sanityClient);
@@ -10,23 +8,40 @@ export function urlFor(source: any) {
}
export const getAllPages = async (token?: string) => {
const komponenter = await getDocumentsTmp("komponent_artikkel", token);
const grunnleggende = await getDocumentsTmp("ds_artikkel", token);
const artikler = await getAkselDocuments("all", token);
const temaer = await getAkselTema(token);
return [
"",
"god-praksis",
"produktbloggen",
...komponenter,
...grunnleggende,
...artikler,
...temaer.map((x) => `god-praksis/${x}`),
];
const pages = await sitemapPages(token);
return pages.map((x) => x.path);
};
export async function sitemapPages(
token?: string
): Promise<{ path: string; lastmod: string }[]> {
const client = token ? noCdnClient(token) : getClient();
const artikler = await getDocuments("all");
const temaer = await getAkselTema();
const pages = await client.fetch(
`{
"frontpage": *[_type == "aksel_forside"][0]._updatedAt,
"godpraksis": *[_type == "godpraksis_landingsside"][0]._updatedAt,
"grunnleggende": *[_type == "grunnleggende_landingsside"][0]._updatedAt,
"komponenter": *[_type == "komponenter_landingsside"][0]._updatedAt,
"blogg": *[_type == "blogg_landingsside"][0]._updatedAt,
}`
);
return [
{ path: "", lastmod: pages.frontpage._updatedAt },
{ path: "god-praksis", lastmod: pages.godpraksis._updatedAt },
{ path: "grunnleggende", lastmod: pages.grunnleggende._updatedAt },
{ path: "komponenter", lastmod: pages.komponenter._updatedAt },
{ path: "produktbloggen", lastmod: pages.blogg._updatedAt },
...temaer.map((x) => ({
path: `god-praksis/${x.path}`,
lastmod: x.lastmod,
})),
...artikler.map((x) => ({ ...x, path: x.slug })),
];
}
export const getAkselDocuments = async (
source:
| "aksel_artikkel"
@@ -38,38 +53,60 @@ export const getAkselDocuments = async (
token?: string
): Promise<string[]> => {
if (!source) return [];
const client = token ? noCdnClient(token) : getClient();
const documents: any[] | null = await client.fetch(akselDocumentsByType, {
types:
source === "all"
? [
"aksel_artikkel",
"aksel_blogg",
"aksel_prinsipp",
"aksel_standalone",
]
: [source],
});
const paths = [];
const docs = await getDocuments(source, token);
const nonDrafts = documents.filter((x) => !x._id.startsWith("drafts."));
nonDrafts?.forEach((page) => {
page.slug && paths.push(page.slug);
});
return paths;
return docs.map((x) => x.slug);
};
export const getDocumentsTmp = async (
source: "komponent_artikkel" | "ds_artikkel",
token?: string
): Promise<string[]> => {
const docs = await getDocuments(source, token);
return docs.map((x) => x.slug);
};
export async function getAkselTema(
token?: string
): Promise<{ path: string; lastmod: string }[]> {
const client = token ? noCdnClient(token) : getClient();
const tags: { slug: { current: string }; _updatedAt: string }[] =
await client.fetch(
`*[_type == "aksel_tema" && count(*[references(^._id)]) > 0]{slug,_updatedAt}`
);
return tags.map((x) => ({
path: x?.slug.current,
lastmod: x?._updatedAt,
}));
}
async function getDocuments(
source:
| "komponent_artikkel"
| "ds_artikkel"
| "aksel_artikkel"
| "aksel_blogg"
| "aksel_prinsipp"
| "aksel_standalone"
| "all",
token?: string
): Promise<{ slug: string; lastmod: string }[]> {
const client = token ? noCdnClient(token) : getClient();
const documents: any[] | null = await client.fetch(
`*[_type in $types]{ _type, _id, 'slug': slug.current }`,
`*[_type in $types]{ _type, _id, 'slug': slug.current, _updatedAt }`,
{
types: [source],
types:
source === "all"
? [
"komponent_artikkel",
"ds_artikkel",
"aksel_artikkel",
"aksel_blogg",
"aksel_prinsipp",
"aksel_standalone",
]
: [source],
}
);
const paths = [];
@@ -77,14 +114,8 @@ export const getDocumentsTmp = async (
documents
.filter((x) => !x._id.startsWith("drafts."))
?.forEach((page) => {
page.slug && paths.push(page.slug);
page.slug && paths.push({ slug: page.slug, lastmod: page._updatedAt });
});
return paths;
};
export const getAkselTema = async (token?: string): Promise<string[]> => {
const client = token ? noCdnClient(token) : getClient();
const tags: { current: string }[] = await client.fetch(akselTemaNames);
return tags.map((x) => x?.current);
};
}
File diff suppressed because it is too large. Load diff
+3 -10
View File
@@ -17,16 +17,9 @@ export enum HelpfulArticleEnum {
"MISC" = "misc",
}
export type HelpfulArticleT = {
answer: HelpfulArticleEnum;
message?: string;
export type FeedbackT = {
message: string;
url: string;
docId: string;
docType: string;
};
export type DsFeddbackMsgT = {
message: string;
user?: string;
url: string;
type?: "ja" | "nei" | "forslag" | "footer";
};
+7 -6
View File
@@ -10,15 +10,16 @@
"build": "next build",
"start": "next start",
"e2e": "yarn build && yarn start-server-and-test start http://localhost:3000 playwright",
"e2e:full": "yarn build && npx ts-node ./e2e/genUrls.ts && FULL_TEST=true yarn start-server-and-test start http://localhost:3000 playwright",
"update:props": "npx ts-node --project tsconfig.tsnode.json ./lib/update-documents/update-props",
"update:tokens": "npx ts-node --project tsconfig.tsnode.json ./lib/update-documents/update-tokens",
"update:eksempler": "npx ts-node --project tsconfig.tsnode.json ./lib/examples/update-sanity",
"e2e:full": "yarn build && ts-node ./e2e/genUrls.ts && FULL_TEST=true yarn start-server-and-test start http://localhost:3000 playwright",
"update:props": "ts-node --project tsconfig.tsnode.json ./scripts/update-props",
"update:tokens": "ts-node --project tsconfig.tsnode.json ./scripts/update-tokens",
"update:eksempler": "ts-node --project tsconfig.tsnode.json ./scripts/examples/update-sanity",
"update:sanity": "yarn update:tokens && yarn update:props && yarn update:eksempler",
"analyze": "cross-env ANALYZE=true next build",
"test": "jest",
"playwright": "playwright test",
"test:watch": "jest --watch"
"test:watch": "jest --watch",
"backup": "ts-node scripts/backup.js"
},
"dependencies": {
"@sanity/block-content-to-react": "^3.0.0",
@@ -51,7 +52,6 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-modal": "3.15.1",
"react-snowfall": "1.2.1",
"sanity": "3.0.6",
"sanity-plugin-asset-source-unsplash": "^1.0.0",
"sanity-plugin-iframe-pane": "^2.1.1",
@@ -86,6 +86,7 @@
"postcss-loader": "7.0.0",
"start-server-and-test": "^1.14.0",
"ts-jest": "^29.0.0",
"ts-node": "10.9.0",
"typescript": "^4.8.0"
}
}
@@ -0,0 +1,73 @@
import dotenv from "dotenv";
import type { NextApiRequest, NextApiResponse } from "next";
import { FeedbackT } from "@/lib";
import { noCdnClient } from "../../lib/sanity/sanity.server";
dotenv.config();
const isDevelopment = process.env.NODE_ENV === "development";
const randKey = () => {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = 12;
for (let i = 0; i < charactersLength; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<void> {
switch (req.method) {
case "POST":
try {
const token = process.env.SANITY_WRITE_KEY;
if (!token && isDevelopment) {
console.log("No token! api/feedback");
return;
}
// this is our transactional client, it won't push anything until we say .commit() later
const transactionClient = noCdnClient(token).transaction();
const data: FeedbackT = JSON.parse(req.body);
if (!data?.docId) {
console.log("No docId! api/feedback");
return;
}
const doc = {
_id: `feedback.${randKey()}`,
_type: "aksel_feedback",
feedback_type:
data.type === "footer" ? "footer" : "artikkel_feedback",
...(data.type === "footer" ? {} : { artikkel_feedback: data.type }),
melding: data.message,
behandlet: false,
url: data.url,
doc_ref: {
_ref: data.docId,
_type: "reference",
_weak: true,
},
};
transactionClient.create(doc);
await transactionClient
.commit()
.then(() => console.log("Feedback-logged"))
.catch((e) => console.error(e.message));
return res.json({ status: "ok" });
} catch (err) {
console.error(err);
res.status(500).json({ msg: "Error, check console" });
}
break;
}
}
@@ -1,44 +0,0 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { DsFeddbackMsgT } from "@/lib";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<void> {
switch (req.method) {
case "POST":
try {
const trelloKey = "c319bd921b9b1a9d8fb2d3c872c0134e";
const trelloToken = process.env.TRELLO_TOKEN;
const labels = "619e2f030ae5bb5e10c9572f";
const data: DsFeddbackMsgT = JSON.parse(req.body);
if (!trelloKey || !trelloToken) {
res.status(500).json({ msg: "Could not find needed tokens in .env" });
return;
}
const card = `&name=${data.message}&desc=**Bruker:** %0A **Side:** %0A ${data.url}`;
const url = `https://api.trello.com/1/cards?idList=619cc5721924df5816bcc45f&idLabels=${labels}&key=${trelloKey}&token=${trelloToken}${card}`;
const postRes = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
},
});
if (!postRes.ok) {
throw new Error(
`request failed with status ${res.status}: ${await postRes.text()}`
);
}
return res.json({ status: "ok" });
} catch (err) {
console.error(err);
res.status(500).json({ msg: "Error, check console" });
}
break;
}
}
@@ -1,70 +0,0 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { HelpfulArticleT, HelpfulArticleEnum } from "@/lib";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
): Promise<void> {
switch (req.method) {
case "POST":
try {
const trelloKey = "c319bd921b9b1a9d8fb2d3c872c0134e";
const trelloToken = process.env.TRELLO_TOKEN;
if (!trelloKey || !trelloToken) {
res.status(500).json({ msg: "Could not find needed tokens in .env" });
return;
}
const data: HelpfulArticleT = JSON.parse(req.body);
const sideUrl = "https://aksel.nav.no";
/* Var denne artikkelen til hjelp? */
const trelloList = "61d44fc3995604743a83f5cb";
let label = "";
switch (data.answer) {
case HelpfulArticleEnum.JA:
label = "61d44fd76c19645dd4d423ab";
break;
case HelpfulArticleEnum.DELVIS:
label = "61d44fe8180b832f7c89c3d4";
break;
case HelpfulArticleEnum.NEI:
label = "61d44fdeb5bfff71c69d619b";
break;
case HelpfulArticleEnum.MISC:
label = "61d44ff4f92e56297e937af8";
break;
default:
break;
}
const editUrl = `https://verktoykasse.sanity.studio/desk/__edit__${data.docId}%2Ctype%3D${data.docType}`;
const card = `&name=${data.message}&desc=**Side:** %0A
${sideUrl + data.url} %0A
**[Rediger side](${editUrl})**`;
const url = `https://api.trello.com/1/cards?idList=${trelloList}&idLabels=${label}&key=${trelloKey}&token=${trelloToken}${card}`;
const postRes = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
},
});
if (!postRes.ok) {
throw new Error(
`request failed with status ${res.status}: ${await postRes.text()}`
);
}
return res.json({ status: "ok" });
} catch (err) {
console.error(err);
res.status(500).json({ msg: "Error, check console" });
}
break;
}
}
+5 -5
View File
@@ -1,6 +1,6 @@
import { NextApiRequest, NextApiResponse } from "next";
import { SitemapStream, streamToPromise } from "sitemap";
import { getAllPages } from "@/lib";
import { sitemapPages } from "@/lib";
/* https://linguinecode.com/post/add-robots-txt-file-sitemaps-nextjs */
export default async (req: NextApiRequest, res: NextApiResponse) => {
@@ -9,14 +9,14 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
hostname: `https://${req.headers.host}`,
});
const pages = await getAllPages();
const pages = await sitemapPages();
// Create each URL row
pages.forEach((post) => {
smStream.write({
url: `/${post}`,
changefreq: "weekly",
priority: 0.5,
url: `/${post.path}`,
changefreq: "monthly",
lastmod: post.lastmod,
});
});
@@ -0,0 +1,32 @@
import { Chat } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="grid gap-10">
<Chat avatar="EVA" name="EVA" timestamp="01.01.21 14:00">
<Chat.Bubble>Hei! Mitt navn er Eva.</Chat.Bubble>
<Chat.Bubble>Hva kan jeg hjelpe deg med?</Chat.Bubble>
</Chat>
<Chat
avatar="NO"
name="Ola Normann"
timestamp="01.01.21 14:00"
position="right"
toptextPosition="left"
>
<Chat.Bubble>Hei Eva.</Chat.Bubble>
<Chat.Bubble>
Hvor sjekker jeg statusen på foreldrepengersøknaden min?
</Chat.Bubble>
</Chat>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 3,
desc: "Noen ganger ønsker man mer fleksibilitet for plassering av navn + tid i chatboblen.",
};
@@ -43,6 +43,8 @@ const Page = ({ tema: page }: PageProps): JSX.Element => {
const hasAnsvarlig = !!page?.ansvarlig?.title;
const hasPages = !!page.seksjoner.find((x) => !!x.sider);
return (
<>
<Head>
@@ -74,10 +76,10 @@ const Page = ({ tema: page }: PageProps): JSX.Element => {
<main
tabIndex={-1}
id="hovedinnhold"
className="min-h-[80vh] focus:outline-none"
className="relative min-h-[80vh] overflow-hidden focus:outline-none"
>
<div className="relative overflow-hidden pt-20 text-center">
<AkselCubeStatic className="text-deepblue-300 opacity-5 " />
<AkselCubeStatic className="text-deepblue-300 opacity-5 " />
<div className=" pt-20 text-center">
<div className="dynamic-wrapper px-4 pb-6 text-center">
<Image
src={urlFor(page.pictogram.url).auto("format").url()}
@@ -143,35 +145,45 @@ const Page = ({ tema: page }: PageProps): JSX.Element => {
</div>
<div className="relative px-4 pt-8 pb-24 md:pt-16 xl:pt-8 ">
<div className="dynamic-wrapper grid gap-20">
{page.seksjoner.map((seksjon) => (
<div key={seksjon._key}>
<Heading level="2" size="medium">
{seksjon.title}
</Heading>
{seksjon.beskrivelse && (
<div className="max-w-prose">
<SanityBlockContent
blocks={seksjon.beskrivelse}
noLastMargin
/>
{hasPages ? (
<div className="dynamic-wrapper grid gap-20">
{page.seksjoner.map((seksjon) =>
seksjon?.sider ? (
<div key={seksjon._key}>
<Heading level="2" size="medium">
{seksjon.title}
</Heading>
{seksjon.beskrivelse && (
<div className="max-w-prose">
<SanityBlockContent
blocks={seksjon.beskrivelse}
noLastMargin
/>
</div>
)}
<div className="card-grid-3-1 mt-6">
{(seksjon?.sider as unknown as ArtiklerT[])?.map(
(x: ArtiklerT) => (
<ArtikkelCard
{...x}
source={page?.slug?.current}
key={x._id}
variant="god-praksis"
/>
)
)}
</div>
</div>
)}
<div className="card-grid-3-1 mt-6">
{(seksjon.sider as unknown as ArtiklerT[]).map(
(x: ArtiklerT) => (
<ArtikkelCard
{...x}
source={page?.slug?.current}
key={x._id}
variant="god-praksis"
/>
)
)}
</div>
</div>
))}
</div>
) : null
)}
</div>
) : (
<div className="dynamic-wrapper mb-20">
<Heading level="2" size="medium">
Fant ingen artikler her enda...
</Heading>
</div>
)}
</div>
</main>
<Footer />
@@ -206,9 +218,9 @@ export default Wrapper;
export const getStaticPaths = async () => {
return {
paths: await getAkselTema().then((paths) =>
paths.map((slug) => ({
paths.map(({ path }) => ({
params: {
slug,
slug: path,
},
}))
),
@@ -109,6 +109,7 @@ export const getStaticProps = async () => {
return {
props: {
articles,
id: "godpraksis_landingsside_id1",
},
revalidate: 60,
};
+61 -15
View File
@@ -3,7 +3,13 @@ import { Footer } from "@/layout";
import { akselForsideQuery, SanityT, urlFor } from "@/lib";
import { getClient } from "@/sanity-client";
import { BodyLong, Heading } from "@navikt/ds-react";
import { ComponentIcon, DownloadIcon, TokenIcon } from "@sanity/icons";
import {
ComponentIcon,
DownloadIcon,
PauseIcon,
PlayIcon,
TokenIcon,
} from "@sanity/icons";
import { Header } from "components/layout/header/Header";
import ArtikkelCard from "components/sanity-modules/cards/ArtikkelCard";
import GodPraksisCard from "components/sanity-modules/cards/GodPraksisCard";
@@ -14,8 +20,15 @@ import { ToolCard } from "components/website-modules/ToolsCard";
import { PreviewSuspense } from "next-sanity/preview";
import Head from "next/head";
import Link from "next/link";
import Snowfall from "react-snowfall";
import { lazy } from "react";
import { lazy, useEffect, useState } from "react";
import cl from "classnames";
function getPrefersReducedMotion() {
const QUERY = "(prefers-reduced-motion: no-preference)";
const mediaQueryList = window.matchMedia(QUERY);
const prefersReducedMotion = !mediaQueryList.matches;
return prefersReducedMotion;
}
const introcards = [
{
@@ -62,9 +75,21 @@ const IntroCards = () => {
const GetStarted = ({
links,
togglePause,
}: {
links: { title: string; slug: string }[];
togglePause: (x: boolean) => void;
}) => {
const [reducedMotion, setReducedMotion] = useState(false);
const [pause, setPause] = useState(false);
useEffect(() => {
setReducedMotion(getPrefersReducedMotion());
const data = localStorage.getItem("pause-animations");
setPause(JSON.parse(data) ?? false);
togglePause(JSON.parse(data) ?? false);
}, [togglePause]);
return (
<div className="bg-deepblue-700 text-text-on-action relative mx-auto w-full max-w-screen-lg -translate-y-1/2 rounded-2xl py-12 px-2">
<Heading size="xlarge" level="2" className="text-center">
@@ -84,13 +109,28 @@ const GetStarted = ({
</li>
))}
</ul>
<div aria-hidden>
<Snowfall
color="rgba(230, 241, 248, 0.3)"
speed={[0.2, 1.0]}
snowflakeCount={70}
/>
</div>
{!reducedMotion && (
<button
className="focus-visible:ring-border-focus-on-inverted absolute top-2 right-2 grid h-11 w-11 place-items-center rounded text-2xl focus:outline-none focus-visible:ring-2"
onClick={() => {
setPause(!pause);
togglePause(!pause);
localStorage.setItem("pause-animations", JSON.stringify(!pause));
}}
>
{pause ? (
<>
<PlayIcon aria-hidden />
<span className="sr-only">Start animasjon</span>
</>
) : (
<>
<PauseIcon aria-hidden />
<span className="sr-only">Stopp animasjon</span>
</>
)}
</button>
)}
</div>
);
};
@@ -104,6 +144,8 @@ const Forside = ({
resent,
komigang,
}: PageProps): JSX.Element => {
const [pause, setPause] = useState(false);
return (
<>
<Head>
@@ -141,10 +183,15 @@ const Forside = ({
/>
</Head>
<div className="header-animated-bg relative max-w-[100vw] overflow-hidden bg-[#DCCAF3]">
<div
className={cl(
"header-animated-bg relative max-w-[100vw] overflow-hidden bg-[#DCCAF3]",
{ "animation-stop": pause }
)}
>
<Header variant="transparent" />
<main tabIndex={-1} id="hovedinnhold" className=" focus:outline-none">
<main tabIndex={-1} id="hovedinnhold" className="focus:outline-none">
<div className="z-20 pb-8">
<div className="centered-layout xs:mt-36 xs:mb-18 xs:max-w-screen-xs relative mb-16 mt-20 grid max-w-xs place-items-center text-center">
<Heading
@@ -161,7 +208,7 @@ const Forside = ({
</div>
<div className="bg-surface-subtle min-h-96 relative pb-72 md:pb-40">
<div className="centered-layout grid max-w-screen-2xl">
<GetStarted links={komigang} />
<GetStarted links={komigang} togglePause={setPause} />
{/* God praksis */}
<div className="mx-auto">
<Heading
@@ -296,11 +343,10 @@ export const getStaticProps = async ({
komigang,
slug: "/",
preview,
id: page?._id ?? "",
},
revalidate: 60,
};
};
export default Page;
<div>lorem</div>;
@@ -1,8 +1,15 @@
import { dateStr } from "@/components";
import {
ChangelogIcon,
dateStr,
FigmaIcon,
GithubIcon,
logAmplitudeEvent,
YarnIcon,
} from "@/components";
import { getDocumentsTmp, komponentQuery, urlFor } from "@/lib";
import { SanityBlockContent } from "@/sanity-block";
import { getClient } from "@/sanity-client";
import { Detail, Heading } from "@navikt/ds-react";
import { BodyShort, Detail, Heading } from "@navikt/ds-react";
import { WithSidebar } from "components/layout/page-templates/WithSidebar";
import ComponentOverview from "components/sanity-modules/component-overview";
import IntroSeksjon from "components/sanity-modules/IntroSeksjon";
@@ -13,6 +20,51 @@ import Head from "next/head";
import { lazy } from "react";
import NotFotfund from "../404";
const kodepakker = {
"ds-react": {
title: "@navikt/ds-react",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/core/react",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/core/react/CHANGELOG.md",
},
"ds-css": {
title: "@navikt/ds-css",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/core/css",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/core/css/CHANGELOG.md",
},
"ds-react-internal": {
title: "@navikt/ds-react-internal",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/internal/react",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/internal/react/CHANGELOG.md",
},
"ds-css-internal": {
title: "@navikt/ds-css-internal",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/internal/css",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/internal/css/CHANGELOG.md",
},
"ds-icons": {
title: "@navikt/ds-reaciconst",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/icons",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/icons/CHANGELOG.md",
},
"ds-tokens": {
title: "@navikt/ds-tokens",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/core/tokens",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/core/tokens/CHANGELOG.md",
},
"ds-tailwind": {
title: "@navikt/ds-tailwind",
git: "https://github.com/navikt/Designsystemet/tree/master/%40navikt/core/tailwind",
changelog:
"https://github.com/navikt/Designsystemet/blob/master/%40navikt/core/tailwind/CHANGELOG.md",
},
};
const Page = ({
page,
sidebar,
@@ -30,6 +82,8 @@ const Page = ({
return <NotFotfund />;
}
const pack = page?.kodepakker?.length > 0 && kodepakker[page?.kodepakker[0]];
const date = page?.updateInfo?.lastVerified
? page?.updateInfo?.lastVerified
: page?.publishedAt
@@ -98,6 +152,81 @@ const Page = ({
)
}
>
<BodyShort
as="span"
size="small"
className="text-text-subtle mb-6 flex flex-wrap gap-4"
>
{pack && (
<>
<a
target="_blank"
rel="noreferrer noopener"
href={pack.git}
className="hover:text-text-default focus:text-text-on-inverted focus:shadow-focus flex items-center gap-1 underline hover:no-underline focus:bg-blue-800 focus:no-underline focus:outline-none"
onClick={() =>
logAmplitudeEvent("link", {
kilde: "intro-lenker komponenter",
til: "github",
})
}
>
<GithubIcon /> Github
</a>
<a
target="_blank"
rel="noreferrer noopener"
href={`https://yarnpkg.com/package/${pack.title}`}
className="hover:text-text-default focus:text-text-on-inverted focus:shadow-focus flex items-center gap-1 underline hover:no-underline focus:bg-blue-800 focus:no-underline focus:outline-none"
onClick={() =>
logAmplitudeEvent("link", {
kilde: "intro-lenker komponenter",
til: "yarn",
})
}
>
<YarnIcon />
Yarn
</a>
</>
)}
{page.figma_link && (
<a
target="_blank"
rel="noreferrer noopener"
href={page.figma_link}
className="hover:text-text-default focus:text-text-on-inverted focus:shadow-focus flex items-center gap-1 underline hover:no-underline focus:bg-blue-800 focus:no-underline focus:outline-none"
onClick={() =>
logAmplitudeEvent("link", {
kilde: "intro-lenker komponenter",
til: "figma",
})
}
>
<FigmaIcon /> Figma
</a>
)}
{pack && (
<>
<a
target="_blank"
rel="noreferrer noopener"
href={pack.changelog}
className="hover:text-text-default focus:text-text-on-inverted focus:shadow-focus flex items-center gap-1 underline hover:no-underline focus:bg-blue-800 focus:no-underline focus:outline-none"
onClick={() =>
logAmplitudeEvent("link", {
kilde: "intro-lenker komponenter",
til: "endringslogg",
})
}
>
<ChangelogIcon />
Endringslogg
</a>
</>
)}
</BodyShort>
{page?.status?.tag === "beta" && <BetaWarning />}
<IntroSeksjon node={page?.intro} />
<SanityBlockContent blocks={page["content"]} />
@@ -118,6 +247,7 @@ const Wrapper = (props: any): JSX.Element => {
params={{
slug: `komponenter/${props.slug.slice(0, 2).join("/")}`,
type: "komponent_artikkel",
preview: "true",
}}
props={props}
/>
@@ -156,6 +286,7 @@ export const getStaticProps = async ({
const { page, sidebar, refs, seo } = await getClient().fetch(komponentQuery, {
slug: `komponenter/${slug.slice(0, 2).join("/")}`,
type: "komponent_artikkel",
preview: "false",
});
return {
@@ -131,7 +131,7 @@ const Page = ({
aria-hidden
priority
className="rounded-2xl"
alt="Illustrasjon"
alt=""
quality={100}
/>
) : (
@@ -143,7 +143,7 @@ const Page = ({
aria-hidden
priority
className="rounded-2xl"
alt="Illustrasjon"
alt=""
/>
)}
</div>
@@ -270,7 +270,7 @@ export const getServerSideProps: GetServerSideProps = async (
morePosts,
slug: context.params.slug as string,
preview: context.preview ?? false,
id: blogg?._id,
id: blogg?._id ?? "",
},
notFound: !blogg && !context.preview,
};
+4 -3
View File
@@ -1,8 +1,6 @@
User-agent: *
Allow: /*
Sitemap: https://aksel.nav.no/api/sitemap
# Next.JS Crawl Budget Performance Updates
# Block files ending in .json, _buildManifest.js, _middlewareManifest.js, _ssgManifest.js, and any other JS files
# The asterisks allows any file name
@@ -18,4 +16,7 @@ Disallow: /*_ssgManifest.js$
Disallow: /*.js$
Disallow: /eksempler/
Disallow: /eksempler
Disallow: /admin
Sitemap: https://aksel.nav.no/api/sitemap
+20
View File
@@ -6,6 +6,23 @@ export const allArticleDocuments = [
"aksel_prinsipp",
];
export const previews = [
"aksel_artikkel",
"komponent_artikkel",
"ds_artikkel",
"aksel_blogg",
"aksel_prinsipp",
"aksel_standalone",
];
export const landingsider = [
{ name: "godpraksis_landingsside", url: "god-praksis" },
{ name: "blogg_landingsside", url: "produktbloggen" },
{ name: "grunnleggende_landingsside", url: "grunnleggende" },
{ name: "komponenter_landingsside", url: "komponenter" },
{ name: "prinsipper_landingsside", url: "prinsipper" },
];
export const allArticleDocsRef = allArticleDocuments.map((x) => ({ type: x }));
export const komponentKategorier = [
@@ -17,6 +34,9 @@ export const grunnleggendeKategorier = [
{ title: "Styling", value: "styling" },
{ title: "Guider", value: "guider" },
{ title: "Stæsj", value: "staesj" },
{ title: "Design", value: "design" },
{ title: "Kode", value: "kode" },
{ title: "Nedlastbart", value: "nedlastbart" },
];
export const monsterKategorier = [];
@@ -29,10 +29,11 @@ export const createWrappedDefaultPublish = (
tone: "positive",
onHandle: () => {
setIsPublishing(true);
patch.execute(
[{ set: { publishedAt: new Date().toISOString() } }],
props.published
);
!props.published &&
patch.execute(
[{ set: { publishedAt: new Date().toISOString() } }],
props.published
);
publish.execute();
props.onComplete();
@@ -67,11 +67,15 @@ export const publicationFlow = definePlugin<PublicationFlowOptions>(
({ hasQualityControl, hasPublishedAt }) => ({
name: "publication-flow",
document: {
actions: (prev, { schemaType }) => {
actions: (prev, { schemaType, currentUser }) => {
if (hasQualityControl.some((e) => e === schemaType)) {
return getCustomActions(prev);
} else if (hasPublishedAt.some((e) => e === schemaType)) {
return withCustomPublishAction(prev);
} else if (schemaType === "aksel_feedback") {
return currentUser.roles.find((x) => x.name === "developer")
? prev
: [prev[0]];
}
return prev;
},
@@ -0,0 +1,132 @@
import { Accordion, Loader } from "@navikt/ds-react";
import { Card } from "@sanity/ui";
import {
getPublishedId,
IntentButton,
Preview,
useClient,
useSchema,
} from "sanity";
import useSWR from "swr";
export function FeedbackView(props) {
const { documentId } = props;
const schema = useSchema();
const schemaType = schema.get("aksel_feedback");
const client = useClient({ apiVersion: "2021-06-07" });
const { data, error, isValidating } = useSWR(
`*[_type == "aksel_feedback" && references($id)]`,
(query) =>
client.fetch(query, {
id: documentId,
})
);
if (isValidating) {
return (
<div className="grid place-items-center px-6">
<div className="mx-auto mt-24">
<Loader size="xlarge" variant="neutral" />
</div>
</div>
);
}
if (error) {
return (
<div className="grid place-items-center">
<div className="mx-auto mt-24 px-6">
En feil oppstod, prøv å laste side på nytt eller kontakt utvikler.
</div>
</div>
);
}
if (data.length === 0) {
return (
<div className="grid place-items-center">
<div className="mx-auto mt-24 px-6">
Siden har ingen tilbakemeldinger enda.
</div>
</div>
);
}
const done = data.filter((x) => x?.behandlet === true);
const notDone = data.filter((x) => x?.behandlet === false);
return (
<div className="grid place-items-center">
<div className="mx-auto mt-8 w-full px-6">
<div className="mt-7">
<ul>
{notDone.map((x) => (
<li key={x._id}>
<Card flex={1}>
<IntentButton
key={x._id}
intent="edit"
mode="ghost"
padding={1}
radius={0}
params={{
type: "aksel_feedback",
id: getPublishedId(x._id),
}}
style={{ width: "100%" }}
>
<Preview
schemaType={schemaType}
value={x}
key={x._id}
layout="default"
/>
</IntentButton>
</Card>
</li>
))}
</ul>
</div>
{done.length > 0 && (
<div className="mt-7">
<Accordion>
<Accordion.Item>
<Accordion.Header>{`Ferdig behandlet ${done.length}`}</Accordion.Header>
<Accordion.Content>
<ul>
{done.map((x) => (
<li key={x._id}>
<Card flex={1}>
<IntentButton
intent="edit"
mode="bleed"
padding={1}
radius={2}
params={{
type: "aksel_feedback",
id: getPublishedId(x._id),
}}
style={{ width: "100%" }}
>
<Preview
schemaType={schemaType}
value={x}
key={x._id}
/>
</IntentButton>
</Card>
</li>
))}
</ul>
</Accordion.Content>
</Accordion.Item>
</Accordion>
</div>
)}
</div>
</div>
);
}
@@ -0,0 +1,26 @@
import { EyeClosedIcon, EyeOpenIcon } from "@sanity/icons";
import { StructureBuilder } from "sanity/desk";
export const FeedbackPanes = async (getClient, S: StructureBuilder) => {
const fb = await getClient({ apiVersion: "2021-06-07" }).fetch(
`{
"behandlet": count(*[_type == "aksel_feedback" && behandlet == true]),
"ubehandlet": count(*[_type == "aksel_feedback" && behandlet == false]),
}`
);
return [
S.listItem().title(`Ubehandlet (${fb.ubehandlet})`).icon(EyeOpenIcon).child(
S.documentList()
.title(`Ubehandlet`)
.filter(`_type == "aksel_feedback" && behandlet == false`)
/* .menuItems([...S.documentTypeList("aksel_artikkel").getMenuItems()]) */
),
S.listItem().title(`Behandlet (${fb.behandlet})`).icon(EyeClosedIcon).child(
S.documentList()
.title(`Behandlet`)
.filter(`_type == "aksel_feedback" && behandlet == true`)
/* .menuItems([...S.documentTypeList("aksel_artikkel").getMenuItems()]) */
),
];
};
@@ -3,6 +3,7 @@ import {
AccessDeniedIcon,
BookIcon,
BulbOutlineIcon,
CommentIcon,
JoystickIcon,
OkHandIcon,
TokenIcon,
@@ -13,11 +14,15 @@ import {
bloggKategorier,
grunnleggendeKategorier,
komponentKategorier,
landingsider,
previews,
prinsippKategorier,
} from "../../config";
import { FeedbackPanes } from "./feedback";
import { GodPraksisPanes } from "./god-praksis";
import { PanesWithCount } from "./with-count";
import { FeedbackView } from "./FeedbackPreview";
/* import { WebPreview, JsonView } from './previews' */
const filtered = [
@@ -42,6 +47,7 @@ const filtered = [
"aksel_artikkel",
"skrivehjelp",
"publication_flow",
"aksel_feedback",
];
export const structure = async (
@@ -58,6 +64,9 @@ export const structure = async (
const adminOrDev = currentUser.roles.find((x) =>
["developer", "administrator", "editor"].includes(x.name)
);
const developer = currentUser.roles.find((x) =>
["developer"].includes(x.name)
);
/* const hasBloggerRole = currentUser.roles.find((x) => x.name === "blogger");
const hasGrunnleggendeRole = currentUser.roles.find(
(x: Role) => x.name === "grunnleggende"
@@ -201,6 +210,15 @@ export const structure = async (
.schemaType(`aksel_forside`)
.icon(Picture)
.id(`aksel_forside_dokument`),
S.listItem()
.title("Feedback")
.icon(CommentIcon)
.child(
S.list()
.title("Feedback")
.items([...(await FeedbackPanes(getClient, S))])
),
S.listItem().title("Standalone-sider").child(
S.documentList()
.title("Sider")
@@ -264,29 +282,14 @@ export const structure = async (
: []),
S.divider(),
...S.documentTypeListItems().filter(
(listItem) => !filtered.includes(listItem.getId())
),
...(developer
? S.documentTypeListItems().filter(
(listItem) => !filtered.includes(listItem.getId())
)
: []),
]);
};
const previews = [
"aksel_artikkel",
"komponent_artikkel",
"ds_artikkel",
"aksel_blogg",
"aksel_prinsipp",
"aksel_standalone",
];
const landingsider = [
{ name: "godpraksis_landingsside", url: "god-praksis" },
{ name: "blogg_landingsside", url: "produktbloggen" },
{ name: "grunnleggende_landingsside", url: "grunnleggende" },
{ name: "komponenter_landingsside", url: "komponenter" },
{ name: "prinsipper_landingsside", url: "prinsipper" },
];
export const resolveProductionUrl = (doc) => {
const basePath = "https://aksel.nav.no";
const devPath = "http://localhost:3000";
@@ -324,7 +327,7 @@ export const resolveProductionUrl = (doc) => {
}
};
export const defaultDocumentNode = (S, { schemaType }) => {
export const defaultDocumentNode = (S, { schemaType, getClient }) => {
if (
[...previews, "aksel_tema", ...landingsider.map((x) => x.name)].includes(
schemaType
@@ -343,6 +346,10 @@ export const defaultDocumentNode = (S, { schemaType }) => {
},
})
.title("Preview"),
S.view
.component(FeedbackView)
.icon(CommentIcon)
.title("Tilbakemeldinger"),
]);
}
return S.document().views([S.view.form()]);
-20
View File
@@ -1,20 +0,0 @@
import { InputWithCounter } from "./schema/custom-components";
export const form = {
form: {
components: {
field: (props) => {
const name = props.schemaType?.name;
if (name === "string" && props.schemaType?.options?.maxLength) {
return <InputWithCounter {...props.inputProps} />;
}
if (name === "text" && props.schemaType?.options?.maxLength) {
return <InputWithCounter {...props.inputProps} size="large" />;
}
return props.renderDefault(props);
},
},
},
};
@@ -1,156 +0,0 @@
import { codeInput } from "@sanity/code-input";
import { colorInput } from "@sanity/color-input";
import { table } from "@sanity/table";
import { visionTool } from "@sanity/vision";
import { createAuthStore, defineConfig } from "sanity";
import { unsplashImageAsset } from "sanity-plugin-asset-source-unsplash";
import { media } from "sanity-plugin-media";
import { deskTool } from "sanity/desk";
import {
defaultDocumentNode,
publicationFlow,
structure,
} from "./custom-plugins";
import { form } from "./form";
import { getTemplates } from "./util";
import { DatabaseIcon, RemoveCircleIcon } from "@sanity/icons";
import { allArticleDocuments } from "./config";
import { schema } from "./schema";
const projectId = "hnbe3yhs";
const sharedConfig = {
projectId,
apiVersion: "2021-10-21",
schema: schema,
...form,
document: {
newDocumentOptions: (prev, { currentUser }) => {
const adminOrDev = currentUser.roles.find((x) =>
["developer", "administrator", "editor"].includes(x.name)
);
if (adminOrDev) {
return [...getTemplates(currentUser.roles), ...prev];
}
return getTemplates(currentUser.roles);
},
},
plugins: [
deskTool({
title: "Desk",
structure,
defaultDocumentNode,
}),
table(),
codeInput(),
media({
projectId,
dataset: "production",
}),
visionTool(),
unsplashImageAsset(),
publicationFlow({
hasQualityControl: [
"komponent_artikkel",
"ds_artikkel",
"aksel_artikkel",
],
hasPublishedAt: allArticleDocuments,
}),
colorInput(),
],
};
export const workspaceConfig = defineConfig([
{
name: "default",
title: "Prod",
icon: DatabaseIcon,
dataset: "production",
basePath: "/admin/prod",
...sharedConfig,
auth: createAuthStore({
redirectOnSingle: false,
mode: "replace",
projectId,
dataset: "production",
providers: [
{
name: "saml",
title: "NAV SSO",
url: "https://api.sanity.io/v2021-10-01/auth/saml/login/f3270b37",
logo: "/images/navlogo.svg",
},
{
name: "github",
title: "GitHub",
url: "https://api.sanity.io/v1/auth/login/github",
},
{
name: "google",
title: "Google",
url: "https://api.sanity.io/v1/auth/login/google",
},
],
}),
},
{
name: "dev",
title: "Dev (testing only)",
icon: RemoveCircleIcon,
dataset: "development",
basePath: "/admin/dev",
...sharedConfig,
auth: createAuthStore({
redirectOnSingle: false,
mode: "replace",
projectId,
dataset: "development",
providers: [
{
name: "saml",
title: "NAV SSO",
url: "https://api.sanity.io/v2021-10-01/auth/saml/login/f3270b37",
logo: "/images/navlogo.svg",
},
{
name: "github",
title: "GitHub",
url: "https://api.sanity.io/v1/auth/login/github",
},
{
name: "google",
title: "Google",
url: "https://api.sanity.io/v1/auth/login/google",
},
],
}),
},
]);
/* interface WorkspaceOptions {
name: string
title: string
projectId: string
dataset: string
plugins?: PluginOptions[]
schema?: SchemaPluginOptions
document?: DocumentPluginOptions
tools?: Tool[] | ComposableOption<Tool[], ConfigContext>
form?: SanityFormConfig
basePath?: string
subtitle?: string
logo?: React.ComponentType
icon?: React.ComponentType
navbar?: {
components?: {
ToolMenu: React.ComponentType<ToolMenuProps>
}
}
theme?: StudioTheme
}
*/
@@ -0,0 +1,125 @@
import { InputWithCounter } from "./schema/custom-components";
import { codeInput } from "@sanity/code-input";
import { colorInput } from "@sanity/color-input";
import { table } from "@sanity/table";
import { visionTool } from "@sanity/vision";
import { createAuthStore, defineConfig } from "sanity";
import { unsplashImageAsset } from "sanity-plugin-asset-source-unsplash";
import { media } from "sanity-plugin-media";
import { deskTool } from "sanity/desk";
import {
defaultDocumentNode,
publicationFlow,
structure,
} from "./custom-plugins";
import { getTemplates } from "./util";
import { DatabaseIcon, RemoveCircleIcon } from "@sanity/icons";
import { allArticleDocuments } from "./config";
import { schema } from "./schema";
const projectId = "hnbe3yhs";
export const workspaceConfig = defineConfig([
{
...defaultConfig(),
title: "Aksel",
name: "default",
dataset: "production",
basePath: "/admin/prod",
icon: DatabaseIcon,
auth: authStore(),
},
{
...defaultConfig(),
title: "Aksel Dev-miljø",
name: "dev",
dataset: "development",
basePath: "/admin/dev",
icon: RemoveCircleIcon,
auth: authStore(),
},
]);
function defaultConfig() {
return {
projectId,
apiVersion: "2021-10-21",
schema,
form: {
components: {
field: (props) => {
const name = props.schemaType?.name;
if (name === "string" && props.schemaType?.options?.maxLength) {
return <InputWithCounter {...props.inputProps} />;
}
if (name === "text" && props.schemaType?.options?.maxLength) {
return <InputWithCounter {...props.inputProps} size="large" />;
}
return props.renderDefault(props);
},
},
},
document: {
newDocumentOptions: (prev, { currentUser }) =>
currentUser.roles.find((x) =>
["developer", "administrator", "editor"].includes(x.name)
)
? [...getTemplates(currentUser.roles), ...prev]
: getTemplates(currentUser.roles),
},
plugins: [
deskTool({
title: "Editor",
structure,
defaultDocumentNode,
}),
publicationFlow({
hasQualityControl: [
"komponent_artikkel",
"ds_artikkel",
"aksel_artikkel",
],
hasPublishedAt: allArticleDocuments,
}),
/* 3rd-party */
table(),
codeInput(),
media(),
visionTool(),
unsplashImageAsset(),
colorInput(),
],
};
}
function authStore() {
return createAuthStore({
redirectOnSingle: false,
mode: "replace",
projectId,
dataset: "production",
providers: [
{
name: "saml",
title: "NAV SSO",
url: "https://api.sanity.io/v2021-10-01/auth/saml/login/f3270b37",
logo: "/images/navlogo.svg",
},
{
name: "github",
title: "GitHub",
url: "https://api.sanity.io/v1/auth/login/github",
},
{
name: "google",
title: "Google",
url: "https://api.sanity.io/v1/auth/login/google",
},
],
});
}
@@ -70,7 +70,7 @@ const OutDatedList = ({ data }: { data: any[] }) => {
() =>
data.filter(
(x) =>
!isAfter(x?.updateInfo?.lastVerified) &&
isAfter(x?.updateInfo?.lastVerified) &&
["ds_artikkel", "aksel_artikkel", "komponent_artikkel"].includes(
x._type
)
@@ -81,7 +81,7 @@ const OutDatedList = ({ data }: { data: any[] }) => {
return (
<Accordion.Item>
<Accordion.Header>
Artikler til godkjenning ({list.length})
Artikler som må godkjennes ({list.length})
</Accordion.Header>
<Accordion.Content>
<ul>
@@ -158,6 +158,56 @@ const DraftList = ({ data }: { data: any[] }) => {
);
};
const FeedbackList = ({ data, title }: { data: any[]; title: string }) => {
const schema = useSchema();
const list = useMemo(
() =>
data.filter((x) =>
title.startsWith("Ferdig") ? x.behandlet : !x.behandlet
),
[data, title]
);
if (list.length === 0) {
return null;
}
return (
<Accordion.Item>
<Accordion.Header>{`${title} (${list.length ?? 0})`}</Accordion.Header>
<Accordion.Content>
<ul>
{list.map((x) => (
<li key={x._id}>
<Card flex={1}>
<IntentButton
intent="edit"
mode="ghost"
padding={1}
radius={0}
params={{
type: "aksel_feedback",
id: getPublishedId(x._id),
}}
style={{ width: "100%" }}
>
<Preview
layout="default"
schemaType={schema.get("aksel_feedback")}
value={x}
key={x._id}
/>
</IntentButton>
</Card>
</li>
))}
</ul>
</Accordion.Content>
</Accordion.Item>
);
};
export const EditorPage = () => {
const user = useCurrentUser();
const userId = useFormValue([`user_id`]) as { current?: string };
@@ -168,6 +218,17 @@ export const EditorPage = () => {
(query) => client.fetch(query)
);
console.log(data);
const {
data: fbData,
error: fbError,
isValidating: fbValidating,
} = useSWR(
`*[_type == "aksel_feedback" && $id in doc_ref->contributors[]->user_id.current]{_id, behandlet}`,
(query) => client.fetch(query, { id: userId.current })
);
if (error || !user) {
return <div>Feilet lasting av bruker...</div>;
}
@@ -197,18 +258,29 @@ export const EditorPage = () => {
</dl>
<p>
Om det er noe du mangler tilgang til kan du sende melding på{" "}
<Link href="https://nav-it.slack.com/archives/C0370ADS0HX">
#Aksel
<Link href="https://nav-it.slack.com/archives/C7NE7A8UF">
#Aksel-designsystemet
</Link>
</p>
</div>
{!fbError && !fbValidating && (
<div className="mt-7">
<Heading level="2" size="small" spacing>
Tilbakemeldinger på artikler du er satt som forfatter (
{fbData?.length ?? 0})
</Heading>
{fbData?.length > 0 && (
<Accordion>
<FeedbackList data={fbData} title="Ubehandlet" />
<FeedbackList data={fbData} title="Ferdig behandlet" />
</Accordion>
)}
</div>
)}
<div className="mt-7">
<Heading level="2" size="small" spacing>
Innhold du jobber med
Under arbeid / må re-valideres
</Heading>
<BodyShort spacing>
Dette er alle artikler du jobber med eller må godkjenne asap.
</BodyShort>
<Accordion>
<DraftList data={data} />
<OutDatedList data={data} />
@@ -1,7 +1,13 @@
import { Stack, Heading, Card, Text } from "@sanity/ui";
import { Card, Heading, Stack } from "@sanity/ui";
import { useEffect, useState } from "react";
import { IntentButton, Preview } from "sanity";
import { getPublishedId, useClient, useSchema, useFormValue } from "sanity";
import {
getPublishedId,
IntentButton,
Preview,
useClient,
useFormValue,
useSchema,
} from "sanity";
export function TemaView(props) {
const client = useClient({ apiVersion: "2021-06-07" });
@@ -13,14 +19,14 @@ export function TemaView(props) {
const type = schema.get("aksel_artikkel");
useEffect(() => {
const query = `*[_type == "aksel_tema" && defined(seksjoner) && !(_id in path("drafts.**"))]{_id,title,seksjoner, "artikler":*[_type == "aksel_artikkel" && !(_id in path("drafts.**")) && ^._id in tema[]._ref]{_id}}`;
const query = `*[_type == "aksel_tema" && !(_id in path("drafts.**"))]{_id,title,seksjoner, "artikler":*[_type == "aksel_artikkel" && !(_id in path("drafts.**")) && ^._id in tema[]._ref]{_id}}`;
client.fetch(query).then(setTema);
}, [client]);
const sider = tema
.find((x) => x.title === title)
?.["seksjoner"]?.reduce(
(b, n) => [...b, ...(n?.sider.map((x) => x._ref) ?? [])],
(b, n) => [...b, ...(n?.sider?.map((x) => x._ref) ?? [])],
[]
);
const artikler = tema.find((x) => x.title === title)?.["artikler"];
@@ -36,12 +42,6 @@ export function TemaView(props) {
<Heading size={1}>
{`Artikler ikke i seksjoner (${notFound.length})`}
</Heading>
{notFound.length ? (
<Text>
Disse artiklene vil man ikke kunne finne i navigasjonen før dette er
fikset.
</Text>
) : null}
{notFound.map((x) => (
<Card flex={1}>
<IntentButton
Loaded 100 of 121 files, more files were not shown because too many files have changed in this diff. Show more