Compare commits

...
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] e7a62a9082 Version Packages (#1772)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-27 13:20:54 +01:00
Ken 494566e604 🐛 Monthpicker oppdaterte ikke år riktig (#1771) 2023-01-27 12:33:17 +01:00
Kai Erik Schieren 1c492fda56 🎨 add labels (#1770) 2023-01-27 11:53:01 +01:00
github-actions[bot]andgithub-actions[bot] 9691ac4713 Version Packages (#1768)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-27 11:51:25 +01:00
Ken 7174bbe7bf 🐛 Fikset visning av tema-grupperinger i sanity 2023-01-27 11:47:05 +01:00
Ken 62f36da5e7 📝 Changeset 2023-01-27 10:23:41 +01:00
Ken 9ec5133ba2 💄 +4px horisontal padding small textfield (team-aksel/issues/89) 2023-01-27 10:23:01 +01:00
Ken 0a7906187f 🔥 Linting 2023-01-27 10:17:56 +01:00
Ken 28f2a3f532 ♿ Aria-live polite på tilbakemeldinger 2023-01-27 10:16:54 +01:00
Ken f5d404b925 🐛 Fikset proptabell-feil med dl-lister 2023-01-27 10:00:06 +01:00
Ken 05955acaf7 ♿ Fikset tabindex scrolltop, skiplink 2023-01-27 09:51:05 +01:00
Ken 55362f3ea7 🎨 Fikset team-aksel#145 issue god-praksis forfatter og dato 2023-01-27 09:42:20 +01:00
Ken 28f8f7a408 🐛 System-theme light fungerte ikke i Sanity 2023-01-27 09:34:38 +01:00
Ken 6778e902f3 ♿ Fikset heading-nivå for artikkelkort på landingssider god-praksis 2023-01-26 16:04:36 +01:00
Ken 92566d5750 Merge branch 'master' of https://github.com/navikt/Designsystemet 2023-01-26 15:38:11 +01:00
Kai Erik Schieren 6911913748 ✨ cmp label (#1765) 2023-01-26 13:49:40 +01:00
Kai Erik Schieren 7f3e96ae01 🎨 add labels to issue templates (#1764) 2023-01-26 12:55:42 +01:00
Ken 19791c0339 Merge branch 'master' into next 2023-01-26 12:17:03 +01:00
Kai Erik Schieren 6a00fca823 Issue templates (#1763)
* ✨ new component issue template

* ✨ add templates for feeback icon + cmp
2023-01-26 09:40:54 +01:00
Ole Jørgen Bakken f5d3ed8eee Endret til textarea i svaralternativet (#1762) 2023-01-25 14:56:07 +01:00
Ole Jørgen Bakken 5c00b91dfb Legger til en issue form for nye ikoner (#1761) 2023-01-25 14:53:13 +01:00
Ken 5b82182fda 🔥 Fjernet gamle sanity-felt 2023-01-25 09:26:55 +01:00
Ken 6246c1d311 📝 Readmes 2023-01-25 09:18:46 +01:00
Ken 04ad4d09b2 ⬆️ Oppdatert sanity 2023-01-24 16:02:07 +01:00
Ken 65ddd4bd18 Merge branch 'master' into next 2023-01-24 15:47:30 +01:00
github-actions[bot]andgithub-actions[bot] 8bb5b8f7b9 Version Packages (#1760)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-24 11:40:38 +01:00
Ken dcf5cfc06b 🐛 Fikset typefeil introdusert i v2.0.6 for ikoner og loader (#1759) 2023-01-24 11:35:28 +01:00
Ken ff97e7f3f8 📝 Readmes 2023-01-24 09:50:21 +01:00
Ken 9e1165de0a 🎨 Oppdatert backup-token bruk 2023-01-24 09:47:25 +01:00
Ken 812573ac43 🎨 Visning av antall god-praksis tema på forside 2023-01-23 10:13:06 +01:00
Ken 5f340eba49 🎨 Bedre feilmelding SEO-tab 2023-01-23 08:50:07 +01:00
Ken 703e7e3ab5 Merge branch 'master' of https://github.com/navikt/Designsystemet 2023-01-20 14:05:28 +01:00
github-actions[bot]andgithub-actions[bot] b42101f6f1 Version Packages (#1757)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-01-20 14:04:04 +01:00
Ken 8b0c4d8f59 🐛 Fikset oppretting av ny profilside Sanity 2023-01-20 13:54:51 +01:00
6ab84e581f [FEATURE] Timeline interne-flater (#1665)
Co-authored-by: Ken <26967723+KenAJoh@users.noreply.github.com>
Co-authored-by: Kai Erik Schieren <kai.schieren@soprasteria.com>
Co-authored-by: Kai Erik Schieren <111572054+kschieren@users.noreply.github.com>
2023-01-20 13:50:52 +01:00
Ken 42f3a298a2 🔥 Lint 2023-01-20 13:14:47 +01:00
Ken e49922d3fe ✨ Copy-knapp for tokens 2023-01-20 13:05:44 +01:00
Ken fc06e8f7b4 🎨 Default å tillate 2-siffer år (yy) 2023-01-20 12:41:51 +01:00
Ken 0273b42fb4 Revert "🎨 År med 2 tall er standard i datepicker nå"
This reverts commit aebb22bf1b.
2023-01-20 12:40:43 +01:00
Ken 0873fe6520 📝 changeset 2023-01-20 12:39:37 +01:00
Ken fdcf502a64 ♿ Aria-labels for sanity riktekst-editor 2023-01-20 12:34:46 +01:00
Ken aebb22bf1b 🎨 År med 2 tall er standard i datepicker nå 2023-01-20 12:32:38 +01:00
Ken 4529e64c6e ✨ Støtte for 'yy'-format i datepicker/monthpicker (#1755)
* 🎨 Støtte for 2-digit år

* 🎨 Props for toggling av twoDigitYear

* ✅ Tester for parsing av twoDigitYears

* 🎨 twoDigitYear demo

* 📝 Docs
2023-01-20 08:53:58 +01:00
Ken 01395e65ba 🎨 Utfaset gammel sanity-løsning 2023-01-19 21:45:29 +01:00
Ken 21dd0450e7 ⬆️ Yarn.lock 2023-01-19 21:15:04 +01:00
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 f51d43c06a Revert "✨ Ny tokenvisning"
This reverts commit ff2515fabb.
2023-01-10 10:44:41 +01:00
Ken 8c81ae46e0 Revert "💄 Copytoken med tooltip"
This reverts commit 21da657eb0.
2023-01-10 10:43:50 +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
Ken d64da78d8b Merge branch 'master' into next 2023-01-09 09:05:25 +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 21da657eb0 💄 Copytoken med tooltip 2023-01-05 11:03:20 +01:00
Ken 52d2d5f41d Merge branch 'tokens/refactor-v2' into next 2023-01-03 14:18:30 +01:00
Ken ff2515fabb ✨ Ny tokenvisning 2023-01-03 13:31:05 +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 23066e9503 ⬆️ Oppdatert aksel til å bruke clsx 2022-12-25 14:19:25 +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
Ken a9e080f892 📝 Ikonoppdatering 2022-12-20 19:16:54 +01:00
Ken 0dc8eb7a1e Ikonsynk Figma (#1730) 2022-12-20 19:15:49 +01:00
Ken 70fd78c926 🔍 Bedre scroll logging 2022-12-20 18:18:15 +01:00
Ken dbc5e7dc07 💄 Mindre gap introcards forside 2022-12-20 17:07:44 +01:00
Ken 4b0b8e4ae4 🐛 Fjernet gammel internal kategori 2022-12-20 16:33:12 +01:00
Ken 57e7e1ecc4 🐛 Forsøk på fix for flaky e2e tester 2022-12-20 16:25:17 +01:00
Ken 9534fe2540 ⚰️ fjernet limits for hva redirects kan løse 2022-12-20 16:02:23 +01:00
Ken 44683d38f1 🎨 La til ny kategori: interne 2022-12-20 16:00:42 +01:00
Ken 23c976e5d2 🐛 Fjernet sidecar fra aksel 2022-12-20 15:26:01 +01:00
Ken 9ea823d630 🐛 Fikset import 2022-12-20 15:14:36 +01:00
Ken 65c65a6637 🎨 Fikset OG-bilde grunnleggende, migrerings-script 2022-12-20 15:05:53 +01:00
ef2a2a9c49 Visuelle oppdateringer Aksel + nytt sanity-studio (#1734)
Co-authored-by: Kai Erik Schieren <kai.schieren@soprasteria.com>
Co-authored-by: Kai Erik Schieren <111572054+kschieren@users.noreply.github.com>
2022-12-20 14:00:20 +01:00
Ken 3f63fd7fb6 🐛 Backup funket ikke 2022-12-20 12:21:06 +01:00
Ken 6fe9788444 🐛 Button submittet form i table 2022-12-16 12:47:35 +01:00
Ken 10c6545885 🐛 Fikset e2e tester 2022-12-15 16:11:31 +01:00
Ken 2e76272a35 🐛 Fikset preview fra dev->prod 2022-12-15 15:44:20 +01:00
Ken 803a7a4d0f ♿ Fokusmarkering relatert innhold-cards 2022-12-15 14:18:10 +01:00
Ken d8b7e69788 📝 Datepicker i modal demo 2022-12-15 11:07:55 +01:00
Ken 097ef18910 ✨ Kan nå toggle lukking av modal med ESC 2022-12-15 10:57:03 +01:00
Ken bb081354fc ✨ Komponentvisning fra next -> prod 2022-12-15 10:10:29 +01:00
Ken edc08c6f8a 🐛 Fikset standalone-sider som fikk 404 2022-12-13 12:48:09 +01:00
Ken fc3577baf4 🐛 Fikset lenker på safari 2022-12-13 09:37:29 +01:00
Ken f02250ab75 🔧 Redirect fra /storybook til chromatic-instans 2022-12-11 21:00:00 +01:00
Ken 1af80dcc1b 🐛 ConfirmationPanel nå wrappet med divog ikke p 2022-12-06 15:00:45 +01:00
Ken 373f40d968 🐛 Fikset keyboard-event error i monthpicker 2022-12-06 14:07:09 +01:00
Ken 75609e1b09 🐛 Fikset duplikat className i dateinput 2022-12-04 18:39:32 +01:00
Ken ea9bb63d0a 🚚 temp url for migrering av ds sider 2022-12-03 17:46:48 +01:00
Ken a148b08eb5 🔥 Fjernet nissehatt 2022-12-03 17:29:02 +01:00
Ken 1ca7e746e1 💄 xmas etter 10 sec 2022-12-03 15:50:26 +01:00
Ken 535ed17d36 🐛 Fikset backup-script 2022-12-03 15:12:19 +01:00
Ken 8df1bc26a0 🐛 Fikser deploy-error grunnet duplikerte pakker 2022-12-02 21:11:54 +01:00
Kai Erik Schieren 1b15ab146a 🔥 remove cl 2022-12-02 15:33:17 +01:00
Kai Erik Schieren 0868b7d716 🚧 add buttons to dialogs 2022-12-02 15:31:01 +01:00
Ken 618d8d3de1 🔥 Fjernet ubrukt prop for TemaCard 2022-12-02 15:21:25 +01:00
Ken e9831b4e2a ⬆️ Oppdatert til next.sanity v3 2022-12-02 15:16:17 +01:00
Ken b0aa3ce0e7 🔥 Console.log 2022-12-02 15:14:15 +01:00
Ken 4fa62f5d64 🏷️ Sanity-typer 2022-12-02 15:05:32 +01:00
Ken 350e929bd2 🐛 Gjemme temp felt for aksel_tema 2022-12-02 14:24:07 +01:00
Ken 64d178ea36 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-12-02 14:02:08 +01:00
Ken cb3decf3bd 👽 Migrert til nye preview 2022-12-02 13:58:45 +01:00
Ken d66d009fe8 👽 Migrert alle sider til nye preview-løsning 2022-12-02 13:30:45 +01:00
Ken 5974a77140 👽 Migrert god-praksis forside 2022-12-02 13:07:42 +01:00
Ken 68b4444bb1 ✨ Tema bruker nå en slug for url-håndtering 2022-12-02 13:02:18 +01:00
Kai Erik Schieren fc7d16b64b 🔥 cleanup 2022-12-02 11:43:07 +01:00
Kai Erik Schieren 08a893c29a 🚧 update dialogs 2022-12-02 11:25:04 +01:00
Kai Erik Schieren 8d181e7a92 🚧 publish dialog 2022-12-02 10:51:12 +01:00
Ken ab1c0849f4 👽 Migrert 3/7 sider til ny next-sanity verson (ds-forside) 2022-12-02 10:32:05 +01:00
Ken 96098e532f 👽 Migrert 2/7 sider til ny next-sanity verson 2022-12-02 10:15:07 +01:00
Ken 0b14ef50e9 🎨 editor-previews 2022-12-01 22:05:47 +01:00
Ken 262f8bf5d2 🎨 bedre editor-preview 2022-12-01 17:56:04 +01:00
Ken f18a2dde8f Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-12-01 17:29:32 +01:00
Ken 2e48c97b50 🎨 Custom tema-view2 2022-12-01 17:29:22 +01:00
Ken 8bf2b8f322 🎨 Oppdatert deskstruct for god-praksis 2022-12-01 15:33:57 +01:00
Kai Erik Schieren ceb7b231b5 ✨ add draft status badge 2022-12-01 15:19:19 +01:00
Kai Erik Schieren f7f304b33d ♻️ add includedSchemas as param 2022-12-01 14:37:53 +01:00
Kai Erik Schieren 151484afd3 🚧 ✨ update info action 2022-12-01 14:23:56 +01:00
Ken 7ae6969b35 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-12-01 14:20:34 +01:00
Ken 65cfd8b459 📝 Oppdatert felt-tekster 2022-12-01 14:20:26 +01:00
Kai Erik Schieren 3c9405b718 🔥 remove publishaction 2022-12-01 13:33:16 +01:00
Kai Erik Schieren 48b347e814 🚧 focusAction wip 2022-12-01 13:14:32 +01:00
Ken 59de2d7992 🎨 Oppdatert field-struktur 2022-12-01 13:10:57 +01:00
Ken 0166c17985 🎨 Oppdatert inputfelt med counter 2022-12-01 12:49:27 +01:00
Ken 57b1de13a9 🎨 Sanity-ikoner 2022-12-01 10:17:04 +01:00
Ken 52104b0f23 🐛 Fikset url-feil 2022-11-30 21:39:31 +01:00
Ken 564a6b4b90 ✨ Preview for artikler 2022-11-30 21:32:50 +01:00
Ken d43a4bfbdb ✨ God-praksis visning 2022-11-30 20:52:19 +01:00
Ken 1e647bffc6 ✨ Generisk Pane med teller 2022-11-30 19:49:52 +01:00
Ken 986c43ead3 Merge branch 'master' into next 2022-11-30 17:07:00 +01:00
Ken ea4fffdeba 🔥 Fjernet referanser til slug_v2 2022-11-30 17:06:35 +01:00
Ken c14e9c346b Merge branch 'next' 2022-11-30 16:07:43 +01:00
Kai Erik Schieren d3dd96d2d4 🚧 godkjenn innhold wip 2022-11-30 15:54:52 +01:00
Ken b5fd3dd734 📝 console endring 2022-11-30 15:44:38 +01:00
Ken 6979811e67 ⚰️ Fjernet isMigrated felt 2022-11-30 15:18:14 +01:00
Andreas Nordahl 82ab82889d update cdn-upload action (#1725) 2022-11-30 15:16:32 +01:00
Ken 0b978693d6 ⚰️ Fjernet tmp slug_v2 2022-11-30 14:36:07 +01:00
Ken feabc168d7 🐛 Fikset build-error 2022-11-30 14:31:22 +01:00
Ken 759c12eeef Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-11-30 14:26:25 +01:00
Ken e3bc4f99a0 🎨 Slug-migrerings script 2022-11-30 14:26:07 +01:00
Kai Erik Schieren 8c31007854 🐛 only use custom badges for included schemas 2022-11-30 14:23:12 +01:00
Kai Erik Schieren cf80626256 🚧 publication flow approve content set verified 2022-11-30 14:17:21 +01:00
Ken cbcfecbe72 🎨 Slug-migrerings script 2022-11-30 14:10:22 +01:00
Ken a1ae58d041 🚚 Oppdatert struktur for god-praksis migrering 2022-11-30 14:08:27 +01:00
Ken a6cf7c1f25 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-11-30 12:46:11 +01:00
Ken a31a969863 🚚 oppdatert slug for alle god-praksis artikler 2022-11-30 12:44:58 +01:00
Ken 19504b0d32 🚧 god-praksis migrerings-script 2022-11-30 12:43:38 +01:00
Kai Erik Schieren 920a037b47 🚧 publication flow approve content wip 2022-11-30 12:16:23 +01:00
Ken 568f55e4be 🏷️ Sanity-typer 2022-11-30 10:38:39 +01:00
Kai Erik Schieren 53cbedf041 ✨ add discardChanges to publication-flow 2022-11-30 10:33:57 +01:00
Kai Erik Schieren cb356c23dc ✨ add restore to publication flow 2022-11-30 10:28:20 +01:00
Kai Erik Schieren 8f76acc776 🔥 delete console logs 2022-11-30 10:21:34 +01:00
Ken d0269a84c0 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-11-30 10:19:45 +01:00
Ken e36206197d 🧱 v2 slug-felt for migrering av god-praksis 2022-11-30 10:19:35 +01:00
Kai Erik Schieren 5e6bb7e016 ✨ ✏️ add duplicate to publication-flow
and fix some typos
2022-11-30 10:18:34 +01:00
Ken 15ed6b0f2f 🎉 Ny god-praksis pages struktur 2022-11-30 10:09:57 +01:00
Kai Erik Schieren 16142657ec ✨ add delete to publication-flow 2022-11-30 10:09:23 +01:00
Kai Erik Schieren a5b50f4cef ✨ add unpublish to publication-flow 2022-11-30 09:57:05 +01:00
Kai Erik Schieren 796b7ac49f 🧱 create plugin structure 2022-11-30 09:45:20 +01:00
Kai Erik Schieren 9bafc3e218 💬 update custom badges 2022-11-30 09:14:36 +01:00
Ken 72c04454e5 🐛 Fikset sitemap 2022-11-29 23:15:28 +01:00
Ken dc4ad88427 🎨 Fjernet task-analytics fra admin-visning 2022-11-29 21:31:02 +01:00
Ken 00ecf7c67c 🐛 Fikset forsidelenke for blogger 2022-11-29 21:18:02 +01:00
Ken 83f8127570 🐛 Fikset e2e for migrering 2022-11-29 21:00:52 +01:00
Ken b6017ea5cf Merge branch 'next' 2022-11-29 20:46:32 +01:00
Ken b96036d14a 🚚 Oppdatert blogg-url er 2022-11-29 20:44:50 +01:00
Kai Erik Schieren d0fafb41b3 ♻️ custom badge 2022-11-29 18:51:28 +01:00
Ken ddf8f65499 🎨 Begynt på god-praksis struktur 2022-11-29 17:06:39 +01:00
Ken 31aa6243ef ✨ Bedre kategorisering og avatar 2022-11-29 16:34:19 +01:00
Ken afca0f481a ✨ Prinsippsider 2022-11-29 15:58:01 +01:00
Ken 2ffc2c22dc ✨ Bloggsider 2022-11-29 15:47:37 +01:00
Ken d8100c1589 🐛 Statusbadge 2022-11-29 15:35:40 +01:00
Ken a4cce95171 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-11-29 15:34:06 +01:00
Ken 01ab8e5741 ✨ profilside 2022-11-29 15:33:39 +01:00
Kai Erik Schieren dd1a961dd2 ✨ custom article status badge 2022-11-29 15:21:02 +01:00
Ken 11520ce468 ✨ Oppdatert deskstruct 2022-11-29 15:14:38 +01:00
Ken 20c8f9204b ✨ Ny navigasjon for komponentsider i sanity 2022-11-29 14:15:38 +01:00
Ken 0074bfd5fb 🐛 Fikset sanity-backup 2022-11-29 12:41:01 +01:00
Kai Erik Schieren a0504f4e57 use lastVerified 2022-11-29 12:12:03 +01:00
Kai Erik Schieren 7bcac33423 🚧 custom publish 2022-11-29 12:07:39 +01:00
Ken a6feaea201 🐛 Fikset sanity-backup 2022-11-29 11:56:06 +01:00
Ken 9c6cf8c811 📝 Popover docs 2022-11-29 11:34:57 +01:00
Kai Erik Schieren 592e0ccae9 🚧 set up custom publish 2022-11-29 11:04:41 +01:00
Ken f2f44ad2d7 🔥 Fjernet påbegynt kategori-løsning 2022-11-29 10:50:23 +01:00
Ken 322077fff8 Merge branch 'next' of https://github.com/navikt/Designsystemet into next 2022-11-29 09:19:30 +01:00
Ken 5eaf729cc4 🎉 Påbegynt ny navigasjon ds 2022-11-29 09:19:17 +01:00
Kai Erik Schieren f285477a6c 🚧 updateInfo refactor ++ 2022-11-29 08:18:12 +01:00
Ken 16f693cee9 🚚 Migert alle sanity-dokumenter 2022-11-28 20:04:58 +01:00
Ken 2a7198e02b 🚚 Migrert blogg-mal 2022-11-28 19:11:10 +01:00
Ken 98b4f4e76a 🐛 Fikset schema-error 2022-11-28 18:07:18 +01:00
Kai Erik Schieren cf397f2522 🔥 cleanup 2022-11-28 16:44:19 +01:00
Kai Erik Schieren 7f1305c639 🚧 updateInfo wip 2022-11-28 16:41:19 +01:00
Ken 5964775a8e 🐛 Fikset typer 2022-11-28 16:31:47 +01:00
Ken f1ea4ee1e0 🚚 Migrert over ds_artikkel 2022-11-28 15:36:09 +01:00
Ken cc24357a9e 🔥 linting 2022-11-28 15:21:43 +01:00
Ken 53406e54a9 🐛 Viser nå task-analytics på alle sider 2022-11-28 15:17:26 +01:00
Ken 39faa2b945 🚚 Migrert aksel_artikkel 2022-11-28 15:09:43 +01:00
Ken 02e5978664 🔥 Cleanup ds_artikkel 2022-11-28 14:52:10 +01:00
Ken fa20f601df 🎨 Flyttet task-analytics til sidemaler 2022-11-28 14:38:38 +01:00
Ken 132ee94235 🎨 Task-analytics 2022-11-28 13:20:15 +01:00
Ken fa5aa175ab 🔥 Fjernet kode for bruk_tab 2022-11-28 11:52:49 +01:00
Ken cf8833c885 🎨 Bedre slug 2022-11-27 20:27:28 +01:00
Ken a37f42b28a 🚚 Migrert slug-håndtering 2022-11-27 18:29:58 +01:00
Ken b8e797bc92 🚚 Migrert moduler for dokumenter 2022-11-27 18:02:04 +01:00
Ken c248cb2a57 ⚡ Minsket first load med 120kB, eksempler med 50% 2022-11-27 13:48:02 +01:00
Ken 2a748c7903 🏷️ Sanity-typer 2022-11-27 13:25:56 +01:00
Ken 2f2cbc16ca 🔥 Fjernet gammel artikkelmal 2022-11-27 13:22:27 +01:00
Ken c0b8928ece 🏷️ rename innholdsfelt komponentsider 2022-11-27 12:43:38 +01:00
Ken 50fe0e785b 🚚 Migrert komponent-artikkel 2022-11-27 12:31:58 +01:00
Ken b2d31aed46 🚚 Migrert ds-schemas 2022-11-26 22:48:27 +01:00
9fdf2cd4df Sync next-branch med master (#1724)
Co-authored-by: Ken <KenAJoh@users.noreply.github.com>
Co-authored-by: Kai Erik Schieren <kai.schieren@soprasteria.com>
2022-11-26 21:02:29 +01:00
Ken 02aa151153 ♿ Fikser siteimprove-error 2022-11-25 14:39:58 +01:00
Ken a472fc4793 🔥 Fjernet utkommentert kode 2022-11-25 14:27:13 +01:00
Ken fdab54742f ⚡ Lazy-loading av bilder i komponent-oversikt 2022-11-25 14:26:42 +01:00
439 changed files with 34681 additions and 17467 deletions

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
name: Ny komponent
description: Send et ønske om en eller flere nye komponenter
title: "[Ny komponent]: "
labels: ["nytt ✨", "forespørsel 🥰", "komponenter 🧩"]
assignees:
- olejorgenbakken
body:
- type: markdown
attributes:
value: |
Takk for at du bidrar inn i Aksel!
- type: input
id: title
attributes:
label: Navn på komponent
description: Hva er navnet på komponenten du ønsker deg?
placeholder: eks. datepicker
validations:
required: true
- type: textarea
id: examples
attributes:
label: Eksempel på komponenten
description: Send en lenke til eksempler på komponenten
+24
View File
@@ -0,0 +1,24 @@
name: Nytt ikon
description: Send et ønske om et eller flere nye ikoner
title: "[Nytt ikon]: "
labels: ["nytt ✨", "ikoner 🖼", "forespørsel 🥰"]
assignees:
- olejorgenbakken
body:
- type: markdown
attributes:
value: |
Takk for at du bidrar inn i Aksel!
- type: input
id: title
attributes:
label: Navn på ikonet
description: Hva er navnet på ikonet du ønsker deg?
placeholder: eks. send
validations:
required: true
- type: textarea
id: examples
attributes:
label: Eksempel på ikonet
description: Send en lenke til eksempler på ikonet
@@ -0,0 +1,16 @@
name: Innspill til komponent
description: Send inn innspill til komponent
title: "[Innspill til komponent]: "
labels: ["forespørsel 🥰", "komponenter 🧩", "nytt ✨", "beta 🧪"]
assignees:
- olejorgenbakken
body:
- type: markdown
attributes:
value: |
Takk for at du bidrar inn i Aksel!
- type: textarea
id: feeback
attributes:
label: Tilbakemelding
description: Beskriv hvilke tilbakemeldinger du har til komponenten
+16
View File
@@ -0,0 +1,16 @@
name: Innspill til ikon
description: Send inn innspill til ikon
title: "[Innspill til ikon]: "
labels: ["forespørsel 🥰", "nytt ✨"]
assignees:
- olejorgenbakken
body:
- type: markdown
attributes:
value: |
Takk for at du bidrar inn i Aksel!
- type: textarea
id: feeback
attributes:
label: Tilbakemelding
description: Beskriv hvilke tilbakemeldinger du har til ikonet
-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
+4 -5
View File
@@ -22,18 +22,17 @@ jobs:
key: ${{ runner.os }}-build-${{ github.sha }}
restore-keys: |
${{ runner.os }}-build-
- name: Install dependencies
run: yarn
run: cd aksel.nav.no/website && yarn
- name: Export dataset
run: SANITY_TOKEN=${{secrets.SANITY_DATASET_EDITOR_TOKEN}} yarn workspace aksel.nav.no sanity:backup
run: cd aksel.nav.no/website && SANITY_PREVIEW_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"
glob: "backup-*.tar.gz"
+1 -4
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
@@ -47,7 +44,7 @@ jobs:
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: yarn workspace website e2e
run: yarn workspace website e2e:full
- uses: actions/upload-artifact@v3
if: always()
with:
+1 -2
View File
@@ -20,9 +20,8 @@ jobs:
- uses: "actions/checkout@v3"
- id: upload
uses: nais/frontend-plattform-cdn-upload-action@main
uses: navikt/frontend/actions/cdn-upload/v1@main
with:
cdn-environment: cdn.nav.no
cdn-team-name: aksel
source: ./fonts
destination: "" # uploads folder to team root
-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 }}
+3
View File
@@ -148,3 +148,6 @@ tmp.json
/playwright/.cache/
playwright-report/
/test-results/
backup-*.tar.gz
sitemap-urls.json
*.tar.gz
+34
View File
@@ -1,5 +1,39 @@
# @navikt/ds-codemod
## 2.1.3
## 2.1.2
## 2.1.1
## 2.1.0
## 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.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
## 2.0.4
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "2.0.5",
"version": "2.1.3",
"description": "Aksel codemods for NAVs designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
+2 -3
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.5",
"@navikt/ds-react": "^2.0.5",
"@navikt/ds-icons": "^2.1.3",
"@navikt/ds-react": "^2.1.3",
"clsx": "^1.1.1"
},
"devDependencies": {
@@ -51,7 +51,6 @@
"@rollup/plugin-commonjs": "23.0.2",
"@rollup/plugin-node-resolve": "^15.0.1",
"@svgr/cli": "6.2.1",
"@types/node": "^17.0.35",
"concurrently": "7.2.1",
"copyfiles": "2.4.1",
"postcss-combine-duplicated-selectors": "10.0.3",
+46
View File
@@ -1,5 +1,51 @@
# @navikt/ds-css
## 2.1.3
## 2.1.2
### Patch Changes
- [`62f36da5e`](https://github.com/navikt/Designsystemet/commit/62f36da5e74fc7f53414d42b310c3b57597795bc) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Small textfield har nå 8px horisontal padding (4px før)
## 2.1.1
## 2.1.0
## 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
## 2.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
### Patch Changes
+1 -1
View File
@@ -14,7 +14,7 @@
background: transparent;
cursor: pointer;
border: none;
border-bottom: 2px solid var(--a-border-strong);
border-bottom: 2px solid var(--ac-accordion-header-border, var(--a-border-strong));
}
.navds-accordion__header:focus {
+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);
}
+1 -1
View File
@@ -27,7 +27,7 @@
}
.navds-form-field--small .navds-text-field__input {
padding: 0 0.25rem;
padding: 0 0.5rem;
min-height: 32px;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "2.0.5",
"version": "2.1.3",
"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.5",
"@navikt/ds-tokens": "^2.1.3",
"normalize.css": "^8.0.1",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
+1
View File
@@ -10,6 +10,7 @@
"--ac-alert-success-bg": "--a-surface-success-subtle"
},
"accordion": {
"--ac-accordion-header-border": "--a-border-strong",
"--ac-accordion-header-text-hover": "--a-text-action-on-action-subtle",
"--ac-accordion-header-border-hover": "--a-border-strong",
"--ac-accordion-item-bg-open": "--a-surface-action-subtle",
+143
View File
@@ -1,5 +1,148 @@
# @navikt/ds-react
## 2.1.3
### Patch Changes
- [#1771](https://github.com/navikt/Designsystemet/pull/1771) [`494566e60`](https://github.com/navikt/Designsystemet/commit/494566e604e958363f75ebfa2adbc1669397636a) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Monthpicker håndterer nå visning av År riktig
- Updated dependencies []:
- @navikt/ds-icons@2.1.3
## 2.1.2
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@2.1.2
## 2.1.1
### Patch Changes
- [#1759](https://github.com/navikt/Designsystemet/pull/1759) [`dcf5cfc06`](https://github.com/navikt/Designsystemet/commit/dcf5cfc06b751341559ef30085bd974820531e57) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Fikset @types/react v18 feil introdusert i v2.0.6
- Updated dependencies [[`dcf5cfc06`](https://github.com/navikt/Designsystemet/commit/dcf5cfc06b751341559ef30085bd974820531e57)]:
- @navikt/ds-icons@2.1.1
## 2.1.0
### Minor Changes
- [`0873fe652`](https://github.com/navikt/Designsystemet/commit/0873fe6520e817e462197c162b49c05826da4838) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Datepicker/Monthpicker støtter nå år med 2 siffer i input
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@2.1.0
## 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
- Updated dependencies []:
- @navikt/ds-icons@2.0.11
## 2.0.10
### Patch Changes
- Button submittet form i table
- Updated dependencies []:
- @navikt/ds-icons@2.0.10
## 2.0.9
### Patch Changes
- ShouldCloseOnEsc i Modal
- Updated dependencies []:
- @navikt/ds-icons@2.0.9
## 2.0.8
### Patch Changes
- Confirmationpanel wrappet med div
- Updated dependencies []:
- @navikt/ds-icons@2.0.8
## 2.0.7
### Patch Changes
- :bug: Fikset keyboard-click i monthpicker
- Updated dependencies []:
- @navikt/ds-icons@2.0.7
## 2.0.6
### Patch Changes
- DateInput hadde duplikat className satt
- Updated dependencies []:
- @navikt/ds-icons@2.0.6
## 2.0.5
### Patch Changes
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "2.0.5",
"version": "2.1.3",
"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.5",
"@floating-ui/react": "0.17.0",
"@navikt/ds-icons": "^2.1.3",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
@@ -52,7 +52,6 @@
"@testing-library/user-event": "^14.2.0",
"@types/faker": "5.5.8",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"@types/react-modal": "^3.13.1",
"concurrently": "7.2.1",
"copyfiles": "^2.4.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">
@@ -108,7 +108,6 @@ const DateInput: DateInputType = forwardRef<HTMLInputElement, DateInputProps>(
autoComplete="off"
aria-controls={ariaId}
className={cl(
className,
"navds-date__field-input",
"navds-text-field__input",
"navds-body-short",
@@ -49,6 +49,13 @@ export interface UseDatepickerOptions
* validation-callback
*/
onValidate?: (val: DateValidationT) => void;
/**
* Allows input of with 'yy' year format.
* @default true
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
* In 2023 this equals to 1943 - 2042
*/
allowTwoDigitYear?: boolean;
}
interface UseDatepickerValue {
@@ -59,7 +66,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)
*/
@@ -112,6 +122,7 @@ export const useDatepicker = (
inputFormat,
onValidate,
defaultMonth,
allowTwoDigitYear = true,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -188,7 +199,13 @@ export const useDatepicker = (
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
!open && setOpen(true);
let day = parseDate(e.target.value, today, locale, "date");
let day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
if (isValidDate(day)) {
setMonth(day);
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
@@ -196,7 +213,13 @@ export const useDatepicker = (
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "date");
let day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
};
@@ -227,7 +250,13 @@ export const useDatepicker = (
// the calendar’s month.
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
setInputValue(e.target.value);
const day = parseDate(e.target.value, today, locale, "date");
const day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
const isBefore =
fromDate && day && differenceInCalendarDays(fromDate, day) > 0;
@@ -35,6 +35,13 @@ export interface UseMonthPickerOptions
* Default shown year
*/
defaultYear?: Date;
/**
* Allows input of with 'yy' year format.
* @default true
* @Note Decision between 20th and 21st century is based on before(todays year - 80) ? 21st : 20th.
* In 2023 this equals to 1943 - 2042
*/
allowTwoDigitYear?: boolean;
}
interface UseMonthPickerValue {
@@ -45,7 +52,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
@@ -94,6 +103,7 @@ export const useMonthpicker = (
inputFormat,
onValidate,
defaultYear,
allowTwoDigitYear = true,
} = opt;
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
@@ -101,7 +111,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
@@ -171,15 +181,29 @@ export const useMonthpicker = (
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
!open && setOpen(true);
let day = parseDate(e.target.value, today, locale, "month");
let day = parseDate(
e.target.value,
today,
locale,
"month",
allowTwoDigitYear
);
if (isValidDate(day)) {
setYear(day);
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
} else {
setYear(defaultSelected ?? defaultYear ?? today);
}
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "month");
let day = parseDate(
e.target.value,
today,
locale,
"month",
allowTwoDigitYear
);
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
};
@@ -189,12 +213,14 @@ export const useMonthpicker = (
if (month) {
setOpen(false);
inputRef.current && inputRef.current.focus();
setYear(month);
}
if (!required && !month) {
updateMonth(undefined);
updateValidation({ isValidMonth: false, isEmpty: true });
setInputValue("");
setYear(defaultYear ?? today);
return;
}
updateMonth(month);
@@ -209,7 +235,13 @@ export const useMonthpicker = (
// the calendar’s month.
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
setInputValue(e.target.value);
const month = parseDate(e.target.value, today, locale, "month");
const month = parseDate(
e.target.value,
today,
locale,
"month",
allowTwoDigitYear
);
const isBefore =
fromDate &&
@@ -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)
*/
@@ -202,12 +202,13 @@ export const useRangeDatepicker = (
inputFormat,
onValidate,
defaultMonth,
allowTwoDigitYear = true,
} = opt;
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);
@@ -322,7 +323,13 @@ export const useRangeDatepicker = (
const handleFocus = (e, src: RangeT) => {
!open && setOpen(true);
let day = parseDate(e.target.value, today, locale, "date");
let day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
if (isValidDate(day)) {
setMonth(day);
src === RANGE.FROM
@@ -334,7 +341,13 @@ export const useRangeDatepicker = (
};
const handleBlur = (e, src: RangeT) => {
let day = parseDate(e.target.value, today, locale, "date");
let day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
if (!isValidDate(day)) {
return;
}
@@ -426,7 +439,13 @@ export const useRangeDatepicker = (
}
if (toInputValue && !selectedRange?.to) {
const toDay = parseDate(toInputValue, today, locale, "date");
const toDay = parseDate(
toInputValue,
today,
locale,
"date",
allowTwoDigitYear
);
if (validateDay(toDay)) {
updateRange({ from: day, to: toDay });
setMonth(day);
@@ -489,7 +508,13 @@ export const useRangeDatepicker = (
/* live-update datepicker based on changes in inputfields */
const handleChange = (e, src: RangeT) => {
const day = parseDate(e.target.value, today, locale, "date");
const day = parseDate(
e.target.value,
today,
locale,
"date",
allowTwoDigitYear
);
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
@@ -74,7 +74,6 @@ export const MonthButton = ({
: -1
}
onKeyDown={(e) => {
e.preventDefault();
const next = nextEnabled(
months,
e.key,
@@ -134,7 +134,7 @@ export const MonthPicker = forwardRef<HTMLDivElement, MonthPickerProps>(
);
const handleSelect = (month?: Date) => {
setSelectedMonth(month);
!onMonthSelect && setSelectedMonth(month);
onMonthSelect?.(month);
month && (onClose?.() ?? setOpen(false));
};
@@ -175,7 +175,7 @@ export const MonthPicker = forwardRef<HTMLDivElement, MonthPickerProps>(
>
<RootProvider
locale={getLocaleFromString(locale)}
selected={selected}
selected={selected ?? selectedMonth}
toDate={toDate}
fromDate={fromDate}
month={selected ?? selectedMonth}
@@ -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();
@@ -2,7 +2,9 @@ import { parseDate } from "../parse-date";
import nb from "date-fns/locale/nb";
import { formatDateForInput } from "../format-date";
const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
const parse = (inp: string) => parseDate(inp, new Date(), nb, "date", false);
const parseTwoDigit = (inp: string) =>
parseDate(inp, new Date(), nb, "date", true);
describe("Format date to correct output", () => {
test("formatDateForInput", () => {
@@ -19,4 +21,12 @@ describe("Format date to correct output", () => {
"15.05.2022"
);
});
test("formatDateForInput with twoDigitYears", () => {
expect(formatDateForInput(parseTwoDigit("15/05/22"), nb, "date")).toEqual(
"15.05.2022"
);
expect(formatDateForInput(parseTwoDigit("1/5/95"), nb, "date")).toEqual(
"01.05.1995"
);
});
});
@@ -4,11 +4,14 @@ import nb from "date-fns/locale/nb";
import getMonth from "date-fns/getMonth";
const check = (inp: string) =>
expect(isValidDate(parseDate(inp, new Date(), nb, "date")));
expect(isValidDate(parseDate(inp, new Date(), nb, "date", false)));
const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
const checkTwoDigit = (inp: string) =>
expect(isValidDate(parseDate(inp, new Date(), nb, "date", true)));
describe("Parse date-inputs", () => {
const parse = (inp: string) => parseDate(inp, new Date(), nb, "date", false);
describe("Parse date-inputs with 4-digit years", () => {
test("No spaces", () => {
check("11052022").toBeTruthy();
check("15052022").toBeTruthy();
@@ -34,6 +37,44 @@ describe("Parse date-inputs", () => {
});
});
describe("Parse date-inputs with 2-digit years", () => {
test("No spaces", () => {
checkTwoDigit("110522").toBeTruthy();
checkTwoDigit("150522").toBeTruthy();
});
test(". divider", () => {
checkTwoDigit("1.5.22").toBeTruthy();
checkTwoDigit("11.05.22").toBeTruthy();
});
test("/ divider", () => {
checkTwoDigit("1/5/22").toBeTruthy();
checkTwoDigit("10/5/22").toBeTruthy();
checkTwoDigit("1/05/22").toBeTruthy();
checkTwoDigit("10/05/22").toBeTruthy();
});
test("- divider", () => {
checkTwoDigit("1-5-22").toBeTruthy();
checkTwoDigit("10-5-22").toBeTruthy();
checkTwoDigit("1-05-22").toBeTruthy();
checkTwoDigit("10-05-22").toBeTruthy();
});
test("Dissallow 1 and 3 digit years", () => {
checkTwoDigit("11052").toBeFalsy();
checkTwoDigit("1105222").toBeFalsy();
checkTwoDigit("1105999").toBeFalsy();
});
test("Dissallow date before year 1000", () => {
checkTwoDigit("11050999").toBeFalsy();
checkTwoDigit("11050010").toBeFalsy();
checkTwoDigit("11051000").toBeTruthy();
});
});
describe("Parse date-inputs to correct month", () => {
test("No spaces", () => {
expect(getMonth(parse("11052022"))).toEqual(4);
@@ -10,7 +10,7 @@ export const dateIsInCurrentMonth = (
/** @private */
export function isValidDate(day: Date): boolean {
return !isNaN(day.getTime());
return day && !isNaN(day?.getTime()) && day.getFullYear() > 999;
}
export const hasNextYear = (year: Date, years: Date[], val: any): boolean => {
+98 -19
View File
@@ -1,4 +1,6 @@
import parse from "date-fns/parse";
import isBefore from "date-fns/isBefore";
import sub from "date-fns/sub";
import { isValidDate } from ".";
export const INPUT_DATE_STRING_FORMAT_DATE = "dd.MM.yyyy";
@@ -22,7 +24,60 @@ const ALLOWED_INPUT_FORMATS_MONTH = [
...ALLOWED_INPUT_FORMATS_DATE,
];
const isTwoDigitYear = (dateString, today, locale, formats) => {
export const parseDate = (
date: string,
today: Date,
locale: Locale,
type: "date" | "month",
allowTwoDigitYear: boolean
): Date => {
let parsed;
const ALLOWED_FORMATS =
type === "date" ? ALLOWED_INPUT_FORMATS_DATE : ALLOWED_INPUT_FORMATS_MONTH;
if (allowTwoDigitYear) {
for (const format of ALLOWED_FORMATS) {
parsed = parse(date, format, today, { locale });
if (
isValidDate(parsed) &&
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
return parsed;
}
}
for (const format of [
...ALLOWED_FORMATS.map((x) => x.replace("yyyy", "yy")),
]) {
parsed = parse(date, format, today, { locale });
if (
isValidDate(parsed) &&
isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
const convertedDate = assignCenturyToDate(date, format, today, locale);
if (isValidDate(new Date(convertedDate))) {
return new Date(convertedDate);
} else {
return new Date("Invalid date");
}
}
}
return new Date("Invalid date");
} else {
for (const format of ALLOWED_FORMATS) {
parsed = parse(date, format, today, { locale });
if (
isValidDate(parsed) &&
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
return parsed;
}
}
return new Date("Invalid date");
}
};
function isTwoDigitYear(dateString, today, locale, formats) {
let parsed;
const newFormat = formats.map((x) => x.replace("yyyy", "yy"));
for (const format of newFormat) {
@@ -32,25 +87,49 @@ const isTwoDigitYear = (dateString, today, locale, formats) => {
}
}
return false;
};
}
export const parseDate = (
date: string,
function assignCenturyToDate(
dateStr: string,
format: string,
today: Date,
locale: Locale,
type: "date" | "month"
): Date => {
let parsed;
const ALLOWED_FORMATS =
type === "date" ? ALLOWED_INPUT_FORMATS_DATE : ALLOWED_INPUT_FORMATS_MONTH;
for (const format of ALLOWED_FORMATS) {
parsed = parse(date, format, today, { locale });
if (
isValidDate(parsed) &&
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
return parsed;
}
locale: Locale
) {
const date20Century = parse(
appendCenturyToTwoYearDigitDateString(dateStr, "19"),
format.replace("yy", "yyyy"),
today,
{ locale }
);
const date21Century = parse(
appendCenturyToTwoYearDigitDateString(dateStr, "20"),
format.replace("yy", "yyyy"),
today,
{ locale }
);
if (isValidDate(date20Century) && isValidDate(date21Century)) {
return isBefore(
date20Century,
sub(new Date(), {
years: 80,
})
)
? date21Century
: date20Century;
}
return new Date("Invalid date");
};
}
function appendCenturyToTwoYearDigitDateString(
dateString: string,
century: "19" | "20"
) {
const twoDigitYear = dateString.slice(-2);
return `${dateString.slice(
0,
dateString.length - 2
)}${century}${twoDigitYear}`;
}
@@ -51,6 +51,7 @@ export const ConfirmationPanel = forwardRef<
size={props.size}
className="navds-confirmation-panel__content"
id={`confirmation-panel-${id}`}
as="div"
>
{children}
</BodyLong>
+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,
@@ -6,11 +6,15 @@ interface SVGRProps {
titleId?: string;
}
export const DefaultIllustration = ({
export type DefaultIllustrationType = React.FunctionComponent<
SVGProps<SVGSVGElement> & SVGRProps
>;
export const DefaultIllustration: DefaultIllustrationType = ({
title,
titleId: _titleId,
...props
}: SVGProps<SVGSVGElement> & SVGRProps) => {
}) => {
let titleId: string | undefined = useId();
titleId = title ? (_titleId ? _titleId : "title-" + titleId) : undefined;
+6 -1
View File
@@ -33,7 +33,12 @@ export interface LoaderProps extends SVGProps<SVGSVGElement> {
variant?: "neutral" | "interaction" | "inverted";
}
export const Loader = forwardRef<SVGSVGElement, LoaderProps>(
/* Workaround for @types/react v17/v18 feil */
export type LoaderType = React.ForwardRefExoticComponent<
LoaderProps & React.RefAttributes<SVGSVGElement>
>;
export const Loader: LoaderType = forwardRef<SVGSVGElement, LoaderProps>(
(
{
children,
+6
View File
@@ -36,6 +36,10 @@ export interface ModalProps {
* @default true
*/
closeButton?: boolean;
/**
*
*/
shouldCloseOnEsc?: boolean;
/**
* Allows custom styling of ReactModal, in accordance with their typing
*/
@@ -75,6 +79,7 @@ export const Modal = forwardRef<ReactModal, ModalProps>(
className,
overlayClassName,
shouldCloseOnOverlayClick = true,
shouldCloseOnEsc = true,
closeButton = true,
"aria-describedby": ariaDescribedBy,
"aria-labelledby": ariaLabelledBy,
@@ -123,6 +128,7 @@ export const Modal = forwardRef<ReactModal, ModalProps>(
className={cl("navds-modal", className)}
overlayClassName={cl("navds-modal__overlay", overlayClassName)}
shouldCloseOnOverlayClick={shouldCloseOnOverlayClick}
shouldCloseOnEsc={shouldCloseOnEsc}
onRequestClose={(e) => onModalCloseRequest(e)}
aria={{
describedby: ariaDescribedBy,
+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,
@@ -44,6 +44,7 @@ export const ColumnHeader: ColumnHeaderType = forwardRef(
>
{sortable ? (
<button
type="button"
className="navds-table__sort-button"
onClick={
sortable && sortKey
@@ -85,6 +85,7 @@ export const ExpandableRow: ExpandableRowType = forwardRef(
>
{!expansionDisabled && (
<button
type="button"
className="navds-table__toggle-expand-button"
aria-controls={id}
aria-expanded={isOpen}
+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,
+34
View File
@@ -1,5 +1,39 @@
# @navikt/ds-tailwind
## 2.1.3
## 2.1.2
## 2.1.1
## 2.1.0
## 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.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
## 2.0.4
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "2.0.5",
"version": "2.1.3",
"description": "Tailwind config based on @navikt/ds-tokens",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -22,9 +22,8 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^2.0.5",
"@navikt/ds-tokens": "^2.1.3",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"color": "4.2.3",
"jest": "^29.0.0",
"lodash": "^4.17.21",
+39
View File
@@ -1,5 +1,44 @@
# @navikt/ds-tokens
## 2.1.3
## 2.1.2
## 2.1.1
## 2.1.0
### Patch Changes
- [#1665](https://github.com/navikt/Designsystemet/pull/1665) [`6ab84e581`](https://github.com/navikt/Designsystemet/commit/6ab84e581f8d3e850bcec340608354335506a051) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny Timeline-komponent for interne-flater
:bug: Fikset feil danger-hover token
## 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.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
## 2.0.4
+1 -1
View File
@@ -240,7 +240,7 @@
{ "name": "--a-surface-danger-subtle", "value": "rgba(255, 230, 230, 1)" },
{
"name": "--a-surface-danger-subtle-hover",
"value": "rgba(255, 230, 230, 1)"
"value": "rgba(255, 184, 184, 1)"
},
{ "name": "--a-surface-danger", "value": "rgba(195, 0, 0, 1)" },
{ "name": "--a-surface-danger-hover", "value": "rgba(173, 0, 0, 1)" },
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "2.0.5",
"version": "2.1.3",
"description": "Design-tokens for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -31,7 +31,6 @@
},
"devDependencies": {
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"color": "4.2.3",
"jest": "^29.0.0",
"lodash": "^4.17.21",
+1 -1
View File
@@ -159,7 +159,7 @@
"danger": {
"subtle": {
"hover": { "value": "{a.red.50.value}" },
"hover": { "value": "{a.red.100.value}" },
"@": { "value": "{a.red.50.value}" }
},
"hover": {
+54
View File
@@ -1,5 +1,59 @@
# @navikt/ds-icons
## 2.1.3
## 2.1.2
## 2.1.1
### Patch Changes
- [#1759](https://github.com/navikt/Designsystemet/pull/1759) [`dcf5cfc06`](https://github.com/navikt/Designsystemet/commit/dcf5cfc06b751341559ef30085bd974820531e57) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Fikset @types/react v18 feil introdusert i v2.0.6
## 2.1.0
## 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
- Oppdatert svg-path i ikoner
## 2.0.10
## 2.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
## 2.0.4
+20
View File
@@ -0,0 +1,20 @@
/**
* Fikser https://github.com/navikt/Designsystemet/issues/1758
*/
const fs = require("fs");
const files = fs.readdirSync(`./esm`).filter((x) => x.endsWith(".d.ts"));
files.forEach((file) => {
let data = fs.readFileSync(`./esm/${file}`).toString().split("\n");
data = data.map((x) => {
return x.includes("React.ForwardRefExoticComponent")
? x.split(":")[0] +
`: React.ForwardRefExoticComponent<React.SVGProps<SVGSVGElement> & SVGRProps & React.RefAttributes<SVGSVGElement>>;`
: x;
});
fs.writeFileSync(`./esm/${file}`, data.join("\n"));
});
+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",
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "2.0.5",
"version": "2.1.3",
"description": "Aksel icons for NAV",
"author": "Aksel | NAV designsystem team",
"repository": {
@@ -32,7 +32,7 @@
"create-package-json-pointers-to-esm": "node ../../scripts/createPackageJsonsWithESMPointers.js",
"create-icons": "svgr --silent --out-dir src svg",
"clean": "rimraf src cjs esm",
"build": "copyfiles util/* src && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"build": "copyfiles util/* src && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && node cleanTypes.js && yarn create-package-json-pointers-to-esm",
"update": "ts-node figma/index.ts dotenv/config",
"test": "jest"
},
@@ -49,7 +49,6 @@
"@svgr/cli": "6.2.1",
"@types/jest": "^29.0.0",
"@types/lodash.startcase": "^4.4.6",
"@types/node": "^17.0.35",
"@types/rimraf": "3.0.2",
"axios": "^0.21.3",
"concurrently": "7.2.1",
+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

+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="M7.70711 4.7071C8.09763 4.31657 8.09763 3.68341 7.70711 3.29289C7.31658 2.90236 6.68342 2.90236 6.29289 3.29289L2.29289 7.29289C2.10535 7.48042 2 7.73478 2 8C2 8.26521 2.10535 8.51957 2.29289 8.7071L6.29289 12.7071C6.68342 13.0976 7.31658 13.0976 7.70711 12.7071C8.09763 12.3166 8.09763 11.6834 7.70711 11.2929L5.41421 8.99999H15C17.7614 8.99999 20 11.2386 20 14C20 16.7614 17.7614 19 15 19H13.7879C13.2356 19 12.7879 19.4477 12.7879 20C12.7879 20.5523 13.2356 21 13.7879 21H15C18.866 21 22 17.866 22 14C22 10.134 18.866 6.99999 15 6.99999H5.41421L7.70711 4.7071Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.70708 4.7071L8.41418 3.99999L6.99997 2.58578L6.29286 3.29288L2.29286 7.29289L1.58575 7.99999L2.29286 8.7071L6.29286 12.7071L6.99997 13.4142L8.41418 12L7.70708 11.2929L5.41418 8.99999H15C17.7614 8.99999 20 11.2386 20 14C20 16.7614 17.7614 19 15 19H13.7878H12.7878V21H13.7878H15C18.866 21 22 17.866 22 14C22 10.134 18.866 6.99999 15 6.99999H5.41418L7.70708 4.7071Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 734 B

After

Width:  |  Height:  |  Size: 536 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="M2 0C0.895431 0 0 0.89543 0 2V22C0 23.1046 0.89543 24 2 24H22C23.1046 24 24 23.1046 24 22V2C24 0.895431 23.1046 0 22 0H2ZM7.70711 3.29289C8.09763 3.68342 8.09763 4.31658 7.70711 4.70711L5.41422 7H15C18.866 7 22 10.134 22 14C22 17.866 18.866 21 15 21H13.7879C13.2356 21 12.7879 20.5523 12.7879 20C12.7879 19.4477 13.2356 19 13.7879 19H15C17.7614 19 20 16.7614 20 14C20 11.2386 17.7614 9 15 9H5.41421L7.70711 11.2929C8.09763 11.6834 8.09763 12.3166 7.70711 12.7071C7.31659 13.0976 6.68342 13.0976 6.2929 12.7071L2.29289 8.70711C2.10536 8.51957 2 8.26522 2 8C2 7.73479 2.10536 7.48043 2.29289 7.2929L6.2929 3.29289C6.68342 2.90237 7.31659 2.90237 7.70711 3.29289Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.41418 3.99999L6.99997 2.58578L1.58575 7.99999L6.99997 13.4142L8.41418 12L5.41418 8.99999H15C17.7614 8.99999 20 11.2386 20 14C20 16.7614 17.7614 19 15 19H12.7878V21H15C18.866 21 22 17.866 22 14C22 10.134 18.866 6.99999 15 6.99999H5.41418L8.41418 3.99999Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 427 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

+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 d="M3 17V18H5V17H3ZM20 10L20.7071 10.7071L21.4142 10L20.7071 9.29289L20 10ZM16.7071 5.29289L16 4.58579L14.5858 6L15.2929 6.70711L16.7071 5.29289ZM15.2929 13.2929L14.5858 14L16 15.4142L16.7071 14.7071L15.2929 13.2929ZM5 17V14H3V17H5ZM8 11H20V9H8V11ZM20.7071 9.29289L16.7071 5.29289L15.2929 6.70711L19.2929 10.7071L20.7071 9.29289ZM19.2929 9.29289L15.2929 13.2929L16.7071 14.7071L20.7071 10.7071L19.2929 9.29289ZM5 14C5 12.3431 6.34315 11 8 11V9C5.23858 9 3 11.2386 3 14H5Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.58579L21.4142 10L16 15.4142L14.5858 14L17.5858 11H8C6.34315 11 5 12.3431 5 14V18H3V14C3 11.2386 5.23858 9 8 9H17.5858L14.5858 6.00001L16 4.58579Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 322 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 d="M3 17V18H5V17H3ZM20 10L20.7071 10.7071L21.4142 10L20.7071 9.29289L20 10ZM16.7071 5.29289L16 4.58579L14.5858 6L15.2929 6.70711L16.7071 5.29289ZM15.2929 13.2929L14.5858 14L16 15.4142L16.7071 14.7071L15.2929 13.2929ZM5 17V14H3V17H5ZM8 11H20V9H8V11ZM20.7071 9.29289L16.7071 5.29289L15.2929 6.70711L19.2929 10.7071L20.7071 9.29289ZM19.2929 9.29289L15.2929 13.2929L16.7071 14.7071L20.7071 10.7071L19.2929 9.29289ZM5 14C5 12.3431 6.34315 11 8 11V9C5.23858 9 3 11.2386 3 14H5Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.58578L21.4142 10L16 15.4142L14.5858 14L17.5858 11H8C6.34315 11 5 12.3431 5 14V18H3V14C3 11.2386 5.23858 9 8 9H17.5858L14.5858 6L16 4.58578Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 599 B

After

Width:  |  Height:  |  Size: 316 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="M1 0C0.447715 0 0 0.447716 0 1V23C0 23.5523 0.447716 24 1 24H23C23.5523 24 24 23.5523 24 23V1C24 0.447715 23.5523 0 23 0H1ZM12.2928 10.2929L17.5857 5L13 5V3H21V11H19V6.41412L13.707 11.7071L12.2928 10.2929ZM5 17.5859V13H3V21H11V19H6.4143L11.7072 13.7071L10.293 12.2929L5 17.5859Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5857 5L12.2928 10.2929L13.707 11.7071L19 6.41412V11H21V3H13V5L17.5857 5ZM5 13V17.5859L10.293 12.2929L11.7072 13.7071L6.4143 19H11V21H3V13H5Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 449 B

After

Width:  |  Height:  |  Size: 315 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="M1 0C0.447715 0 0 0.447716 0 1V23C0 23.5523 0.447716 24 1 24H23C23.5523 24 24 23.5523 24 23V1C24 0.447715 23.5523 0 23 0H1ZM21.7068 3.70709L16.414 8.99998H20.9999V11H12.9999V2.99998H14.9999V7.5856L20.2926 2.29288L21.7068 3.70709ZM2.29272 20.2929L7.58562 15L2.99991 15L2.99991 13L10.9999 13L10.9999 21H8.99991V16.4141L3.70694 21.7071L2.29272 20.2929Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.414 8.99998L21.7068 3.70709L20.2926 2.29288L14.9999 7.5856V2.99998H12.9999V11H20.9999V8.99998H16.414ZM7.58562 15L2.29272 20.2929L3.70694 21.7071L8.99991 16.4141L8.99991 21H10.9999L10.9999 13L2.99991 13L2.99991 15L7.58562 15Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 399 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

+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="M9.70711 3.7071C10.0976 3.31658 10.0976 2.68341 9.70711 2.29289C9.31658 1.90237 8.68342 1.90237 8.29289 2.29289L5.29289 5.29289C5.10535 5.48043 5 5.73478 5 6C5 6.26522 5.10535 6.51957 5.29289 6.70711L8.29289 9.7071C8.68342 10.0976 9.31658 10.0976 9.70711 9.7071C10.0976 9.31658 10.0976 8.68341 9.70711 8.29289L8.41421 7H17C18.6569 7 20 8.34314 20 10V12C20 12.5523 20.4477 13 21 13C21.5523 13 22 12.5523 22 12V10C22 7.23857 19.7614 5 17 5H8.41421L9.70711 3.7071ZM14.2929 20.2929C13.9024 20.6834 13.9024 21.3166 14.2929 21.7071C14.6834 22.0976 15.3166 22.0976 15.7071 21.7071L18.7071 18.7071C18.8946 18.5196 19 18.2652 19 18C19 17.7348 18.8946 17.4804 18.7071 17.2929L15.7071 14.2929C15.3166 13.9024 14.6834 13.9024 14.2929 14.2929C13.9024 14.6834 13.9024 15.3166 14.2929 15.7071L15.5858 17L7 17C5.34314 17 4 15.6568 4 14L4 12C4 11.4477 3.55228 11 3 11C2.44771 11 2 11.4477 2 12V14C2 16.7614 4.23858 19 7 19H15.5858L14.2929 20.2929Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.70711 3.7071L10.4142 2.99999L9 1.58578L8.29289 2.29289L5.29289 5.29289L4.58578 6L5.29289 6.7071L8.29289 9.7071L9 10.4142L10.4142 8.99999L9.70711 8.29289L8.41421 6.99999H17C18.6569 6.99999 20 8.34314 20 9.99999V12V13H22V12V9.99999C22 7.23857 19.7614 4.99999 17 4.99999H8.41421L9.70711 3.7071ZM14.2929 20.2929L13.5858 21L15 22.4142L15.7071 21.7071L18.7071 18.7071L19.4142 18L18.7071 17.2929L15.7071 14.2929L15 13.5858L13.5858 15L14.2929 15.7071L15.5858 17L7 17C5.34314 17 4 15.6568 4 14L4 12L4 11H2V12V14C2 16.7614 4.23858 19 7 19H15.5858L14.2929 20.2929Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 727 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="M2 0C0.895431 0 0 0.89543 0 2V22C0 23.1046 0.89543 24 2 24H22C23.1046 24 24 23.1046 24 22V2C24 0.895431 23.1046 0 22 0H2ZM9.70711 2.29289C10.0976 2.68342 10.0976 3.31658 9.70711 3.70711L8.41421 5H17C19.7614 5 22 7.23858 22 10V12C22 12.5523 21.5523 13 21 13C20.4477 13 20 12.5523 20 12V10C20 8.34315 18.6569 7 17 7H8.41421L9.70711 8.29289C10.0976 8.68342 10.0976 9.31658 9.70711 9.70711C9.31658 10.0976 8.68342 10.0976 8.29289 9.70711L5.29289 6.70711C5.10535 6.51957 5 6.26522 5 6C5 5.73479 5.10535 5.48043 5.29289 5.2929L8.29289 2.29289C8.68342 1.90237 9.31658 1.90237 9.70711 2.29289ZM14.2929 21.7071C13.9024 21.3166 13.9024 20.6834 14.2929 20.2929L15.5858 19H7C4.23858 19 2 16.7614 2 14V12C2 11.4477 2.44771 11 3 11C3.55228 11 4 11.4477 4 12V14C4 15.6569 5.34314 17 7 17H15.5858L14.2929 15.7071C13.9024 15.3166 13.9024 14.6834 14.2929 14.2929C14.6834 13.9024 15.3166 13.9024 15.7071 14.2929L18.7071 17.2929C18.8946 17.4804 19 17.7348 19 18C19 18.2652 18.8946 18.5196 18.7071 18.7071L15.7071 21.7071C15.3166 22.0976 14.6834 22.0976 14.2929 21.7071Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.70711 3.7071L10.4142 2.99999L9 1.58578L8.29289 2.29289L5.29289 5.29289L4.58578 6L5.29289 6.7071L8.29289 9.7071L9 10.4142L10.4142 8.99999L9.70711 8.29289L8.41421 6.99999H17C18.6569 6.99999 20 8.34314 20 9.99999V12V13H22V12V9.99999C22 7.23857 19.7614 4.99999 17 4.99999H8.41421L9.70711 3.7071ZM14.2929 20.2929L13.5858 21L15 22.4142L15.7071 21.7071L18.7071 18.7071L19.4142 18L18.7071 17.2929L15.7071 14.2929L15 13.5858L13.5858 15L14.2929 15.7071L15.5858 17L7 17C5.34314 17 4 15.6568 4 14L4 12L4 11H2V12V14C2 16.7614 4.23858 19 7 19H15.5858L14.2929 20.2929Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 727 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="M6.70817 6C8.11909 4.75448 9.9715 4 12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12H2C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C9.27396 2 6.80296 3.09136 5 4.85869L5 2H3L3 8H9V6H6.70817Z" fill="#262626"/>
<path d="M6.70817 6C8.11909 4.75448 9.9715 4 12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12H2C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C9.27396 2 6.80296 3.09136 5 4.85869L5 2H3L3 8H9V6H6.70817Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 394 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

+39
View File
@@ -1,5 +1,44 @@
# @navikt/ds-css-internal
## 2.1.3
## 2.1.2
## 2.1.1
## 2.1.0
### Minor Changes
- [#1665](https://github.com/navikt/Designsystemet/pull/1665) [`6ab84e581`](https://github.com/navikt/Designsystemet/commit/6ab84e581f8d3e850bcec340608354335506a051) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny Timeline-komponent for interne-flater
:bug: Fikset feil danger-hover token
## 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.0.9
## 2.0.8
## 2.0.7
## 2.0.6
## 2.0.5
## 2.0.4
+1
View File
@@ -1,3 +1,4 @@
@import "copy-to-clipboard.css";
@import "dropdown.css";
@import "header.css";
@import "timeline.css";
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "2.0.5",
"version": "2.1.3",
"description": "CSS for NAV internal Designsystem-components",
"author": "Aksel | NAV designsystem team",
"keywords": [
+281
View File
@@ -0,0 +1,281 @@
.navdsi-timeline {
position: relative;
display: grid;
grid-template-columns: auto minmax(0, 1fr);
width: 100%;
min-width: fit-content;
}
.navdsi-timeline__axislabels {
position: relative;
height: 1rem;
box-sizing: content-box;
grid-column: 2;
margin-bottom: var(--a-spacing-4);
margin-left: var(--a-spacing-8);
}
.navdsi-timeline__row-label {
white-space: nowrap;
width: auto;
margin-right: var(--a-spacing-4);
grid-column: 1;
height: 1.5rem;
display: flex;
align-items: center;
gap: var(--a-spacing-2);
}
.navdsi-timeline__axislabels-label {
position: absolute;
color: var(--ac-timeline-axislabel-text, var(--a-text-subtle));
white-space: nowrap;
}
.navdsi-timeline__row {
display: flex;
background: var(--ac-timeline-row-bg, var(--a-surface-subtle));
margin: 0 0 var(--a-spacing-8);
padding-left: var(--a-spacing-8);
grid-column: 2;
}
.navdsi-timeline__row--active {
background: var(--ac-timeline-row-active-bg, var(--a-surface-selected));
}
.navdsi-timeline__row:last-of-type {
margin-bottom: 0;
}
.navdsi-timeline__row-periods {
height: 1.5rem;
position: relative;
width: 100%;
margin: 0;
}
.navdsi-timeline__row-periods > li {
list-style-type: none;
}
.navdsi-timeline__period {
height: 100%;
border-radius: var(--a-border-radius-full);
position: absolute;
padding: 0;
display: flex;
align-items: center;
z-index: 2;
border: none;
font-size: 1rem;
}
.navdsi-timeline__period--inner {
margin: 0 var(--a-spacing-1) 0 var(--a-spacing-2);
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
text-align: left;
height: 1rem;
}
/* .navdsi-timeline__period > * {
flex-shrink: 0;
} */
.navdsi-timeline__period--clickable {
cursor: pointer;
}
.navdsi-timeline__period--success {
background: var(--ac-timeline-period-success-bg, var(--a-surface-success-subtle));
box-shadow: inset 0 0 0 1px var(--ac-timeline-period-success-border, var(--a-border-success));
}
.navdsi-timeline__period--success.navdsi-timeline__period--clickable:hover {
background: var(--a-surface-success-subtle-hover);
background: var(--ac-timeline-period-success-bg-hover, var(--a-surface-success-subtle-hover));
}
.navdsi-timeline__period--warning {
background: var(--ac-timeline-period-warning-bg, var(--a-surface-warning-subtle));
box-shadow: inset 0 0 0 1px var(--ac-timeline-period-warning-border, var(--a-border-warning));
}
.navdsi-timeline__period--warning.navdsi-timeline__period--clickable:hover {
background: var(--ac-timeline-period-warning-bg-hover, var(--a-surface-warning-subtle-hover));
}
.navdsi-timeline__period--danger {
background: var(--ac-timeline-period-danger-bg, var(--a-surface-danger-subtle));
box-shadow: inset 0 0 0 1px var(--ac-timeline-period-danger-border, var(--a-border-danger));
}
.navdsi-timeline__period--danger.navdsi-timeline__period--clickable:hover {
background: var(--ac-timeline-period-danger-bg-hover, var(--a-surface-danger-subtle-hover));
}
.navdsi-timeline__period--info {
background: var(--ac-timeline-period-info-bg, var(--a-surface-info-subtle));
box-shadow: inset 0 0 0 1px var(--ac-timeline-period-info-border, var(--a-border-info));
}
.navdsi-timeline__period--info.navdsi-timeline__period--clickable:hover {
background: var(--ac-timeline-period-info-bg-hover, var(--a-surface-info-subtle-hover));
}
.navdsi-timeline__period--neutral {
background: var(--ac-timeline-period-neutral-bg, var(--a-bg-subtle));
box-shadow: inset 0 0 0 1px var(--ac-timeline-period-neutral-border, var(--a-border-default));
}
.navdsi-timeline__period--neutral.navdsi-timeline__period--clickable:hover {
background: var(--ac-timeline-period-neutral-bg-hover, var(--a-gray-200));
}
.navdsi-timeline__period--connected-both {
border-radius: 0;
}
.navdsi-timeline__period--connected-right {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
.navdsi-timeline__period--connected-left {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
.navdsi-timeline__period--selected {
box-shadow: inset 0 0 0 2px var(--ac-timeline-period-selected-border, var(--a-border-action-selected));
z-index: 3;
}
.navdsi-timeline__pin-wrapper {
position: absolute;
grid-column: 2;
top: 0;
z-index: 1;
height: 100%;
display: flex;
flex-direction: column-reverse;
isolation: isolate;
--navdsc-timeline-pin-size: 0.9rem;
}
.navdsi-timeline__pin-button {
border: none;
cursor: pointer;
background: var(--a-surface-default);
box-shadow: inset 0 0 0 1px var(--ac-timeline-pin-bg, var(--a-surface-danger)),
0 0 0 4px var(--ac-timeline-pin-bg, var(--a-surface-danger)), 0 0 0 5px var(--a-surface-default);
z-index: 2;
border-radius: var(--a-border-radius-full);
padding: 3.5px;
position: relative;
}
.navdsi-timeline__pin-button::before {
content: "";
inset: 0;
position: absolute;
width: 25px;
height: 25px;
border-radius: var(--a-border-radius-full);
left: calc(-12.5px + 3.5px);
top: calc(-12.5px + 3.5px);
}
.navdsi-timeline__pin-button:focus {
box-shadow: inset 0 0 0 1px var(--ac-timeline-pin-bg, var(--a-surface-danger)),
0 0 0 3px var(--ac-timeline-pin-bg, var(--a-surface-danger)), 0 0 0 4px var(--a-surface-default),
0 0 0 6px var(--a-border-focus);
outline: none;
}
.navdsi-timeline__pin-button:hover {
box-shadow: inset 0 0 0 1px var(--ac-timeline-pin-bg-hover, var(--a-surface-danger-hover)),
0 0 0 4px var(--ac-timeline-pin-bg-hover, var(--a-surface-danger-hover)), 0 0 0 5px var(--a-surface-default);
}
.navdsi-timeline__pin-button:hover:focus {
box-shadow: inset 0 0 0 1px var(--ac-timeline-pin-bg-hover, var(--a-surface-danger-hover)),
0 0 0 3px var(--ac-timeline-pin-bg-hover, var(--a-surface-danger-hover)), 0 0 0 4px var(--a-surface-default),
0 0 0 6px var(--a-border-focus);
}
.navdsi-timeline__pin-wrapper::before {
content: "";
top: var(--navdsc-timeline-pin-size);
height: calc(94% - var(--navdsc-timeline-pin-size));
width: 1px;
margin: 0 auto;
background: var(--a-surface-inverted);
}
.navdsi-timeline__zoom {
margin-top: var(--a-spacing-6);
float: right;
display: flex;
list-style-type: none;
}
.navdsi-timeline__zoom-button {
all: unset;
cursor: pointer;
padding: 6px 9px 6px 8px;
border: 1px solid var(--ac-timeline-zoom-border, var(--a-border-default));
border-width: 1px 0 1px 1px;
background: var(--ac-timeline-zoom-bg, var(--a-surface-default));
}
.navdsi-timeline__zoom li:first-child .navdsi-timeline__zoom-button {
border-radius: var(--a-border-radius-medium) 0 0 var(--a-border-radius-medium);
}
.navdsi-timeline__zoom li:last-child .navdsi-timeline__zoom-button {
border-width: 1px;
border-radius: 0 var(--a-border-radius-medium) var(--a-border-radius-medium) 0;
}
.navdsi-timeline__zoom li:only-child .navdsi-timeline__zoom-button {
border-radius: var(--a-border-radius-medium);
}
.navdsi-timeline__zoom-button:not([aria-pressed="true"]):hover {
background: var(--ac-timeline-zoom-hover, var(--a-surface-action-subtle-hover));
}
.navdsi-timeline__zoom-button[aria-pressed="true"] {
background: var(--ac-timeline-zoom-selected-bg, var(--a-surface-inverted));
color: var(--ac-timeline-zoom-selected-text, var(--a-text-on-inverted));
}
.navdsi-timeline__period:focus {
outline: none;
z-index: 4;
box-shadow: 0 0 0 2px var(--a-border-focus);
}
.navdsi-timeline__period--selected:focus {
box-shadow: inset 0 0 0 2px var(--ac-timeline-period-selected-border, var(--a-border-action-selected)),
0 0 0 2px var(--a-border-focus);
z-index: 3;
}
.navdsi-timeline__zoom li:focus-within {
z-index: var(--a-z-index-focus);
}
.navdsi-timeline__zoom-button:focus {
box-shadow: 0 0 0 1px var(--a-surface-default), 0 0 0 3px var(--a-border-focus);
border-width: 1px;
}
.navdsi-timeline__zoom li:not(:last-child) .navdsi-timeline__zoom-button:focus {
margin-right: 2px;
padding-right: 6px;
}
+28
View File
@@ -16,5 +16,33 @@
"--ac-header-text": "--a-text-on-inverted",
"--ac-header-hover-bg": "--a-surface-inverted-hover",
"--ac-header-active-bg": "--a-surface-inverted-active"
},
"timeline": {
"--ac-timeline-row-bg": "--a-surface-subtle",
"--ac-timeline-row-active-bg": "--a-surface-selected",
"--ac-timeline-period-success-bg": "--a-surface-success-subtle",
"--ac-timeline-period-success-border": "--a-border-success",
"--ac-timeline-period-success-bg-hover": "--a-surface-success-subtle-hover",
"--ac-timeline-period-warning-bg": "--a-surface-warning-subtle",
"--ac-timeline-period-warning-border": "--a-border-warning",
"--ac-timeline-period-warning-bg-hover": "--a-surface-warning-subtle-hover",
"--ac-timeline-period-danger-bg": "--a-surface-danger-subtle",
"--ac-timeline-period-danger-border": "--a-border-danger",
"--ac-timeline-period-danger-bg-hover": "--a-surface-danger-subtle-hover",
"--ac-timeline-period-info-bg": "--a-surface-info-subtle",
"--ac-timeline-period-info-border": "--a-border-info",
"--ac-timeline-period-info-bg-hover": "--a-surface-info-subtle-hover",
"--ac-timeline-period-neutral-bg": "--a-bg-subtle",
"--ac-timeline-period-neutral-border": "--a-border-default",
"--ac-timeline-period-neutral-bg-hover": "--a-gray-200",
"--ac-timeline-period-selected-border": "--a-border-action-selected",
"--ac-timeline-pin-bg": "--a-surface-danger",
"--ac-timeline-pin-bg-hover": "--a-surface-danger-hover",
"--ac-timeline-zoom-border": "--a-border-default",
"--ac-timeline-zoom-bg": "--a-surface-default",
"--ac-timeline-zoom-hover": "--a-surface-action-subtle-hover",
"--ac-timeline-zoom-selected-bg": "--a-surface-inverted",
"--ac-timeline-zoom-selected-text": "--a-text-on-inverted",
"--ac-timeline-axislabel-text": "--a-text-subtle"
}
}
+141
View File
@@ -1,5 +1,146 @@
# @navikt/ds-react-internal
## 2.1.3
### Patch Changes
- Updated dependencies [[`494566e60`](https://github.com/navikt/Designsystemet/commit/494566e604e958363f75ebfa2adbc1669397636a)]:
- @navikt/ds-react@2.1.3
- @navikt/ds-icons@2.1.3
## 2.1.2
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.1.2
- @navikt/ds-icons@2.1.2
## 2.1.1
### Patch Changes
- Updated dependencies [[`dcf5cfc06`](https://github.com/navikt/Designsystemet/commit/dcf5cfc06b751341559ef30085bd974820531e57)]:
- @navikt/ds-react@2.1.1
- @navikt/ds-icons@2.1.1
## 2.1.0
### Minor Changes
- [#1665](https://github.com/navikt/Designsystemet/pull/1665) [`6ab84e581`](https://github.com/navikt/Designsystemet/commit/6ab84e581f8d3e850bcec340608354335506a051) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny Timeline-komponent for interne-flater
:bug: Fikset feil danger-hover token
### Patch Changes
- Updated dependencies [[`0873fe652`](https://github.com/navikt/Designsystemet/commit/0873fe6520e817e462197c162b49c05826da4838)]:
- @navikt/ds-react@2.1.0
- @navikt/ds-icons@2.1.0
## 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
- Updated dependencies []:
- @navikt/ds-icons@2.0.11
- @navikt/ds-react@2.0.11
## 2.0.10
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.10
- @navikt/ds-icons@2.0.10
## 2.0.9
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.9
- @navikt/ds-icons@2.0.9
## 2.0.8
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.8
- @navikt/ds-icons@2.0.8
## 2.0.7
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.7
- @navikt/ds-icons@2.0.7
## 2.0.6
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@2.0.6
- @navikt/ds-icons@2.0.6
## 2.0.5
### Patch Changes
+3 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "2.0.5",
"version": "2.1.3",
"description": "Aksel react components for internal UIs in NAV",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -35,13 +35,12 @@
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^2.0.5",
"@navikt/ds-react": "^2.0.5",
"@navikt/ds-icons": "^2.1.3",
"@navikt/ds-react": "^2.1.3",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
"devDependencies": {
"@types/node": "^17.0.35",
"concurrently": "7.2.1",
"rimraf": "^3.0.2",
"ts-node": "10.9.0",
+1
View File
@@ -1,3 +1,4 @@
export * from "./copy-to-clipboard";
export * from "./dropdown";
export * from "./header";
export * from "./timeline";
@@ -0,0 +1,142 @@
import { Detail } from "@navikt/ds-react";
import {
addDays,
addMonths,
addYears,
differenceInDays,
differenceInMonths,
differenceInYears,
endOfMonth,
endOfYear,
format,
startOfDay,
startOfMonth,
startOfYear,
subDays,
} from "date-fns";
import React from "react";
import { useTimelineContext } from "./hooks/useTimelineContext";
import { isVisible } from "./utils";
import { horizontalPositionAndWidth } from "./utils/calc";
import { AxisLabel } from "./utils/types.external";
export const dayLabels = (
start: Date,
end: Date,
totalDays: number,
direction: "left" | "right"
): AxisLabel[] => {
const increment = Math.ceil(totalDays / 10);
const lastDay = startOfDay(end);
return new Array(totalDays)
.fill(lastDay)
.map((thisDay, i) => {
if (i % increment !== 0) return null;
const day: Date = subDays(thisDay, i);
const { horizontalPosition, width } = horizontalPositionAndWidth(
day,
addDays(day, 1),
start,
end
);
return {
direction: direction,
horizontalPosition: horizontalPosition,
label: format(day, "MM.dd"),
date: day,
width: width,
};
})
.filter((label) => label !== null) as AxisLabel[];
};
export const monthLabels = (
start: Date,
end: Date,
direction: "left" | "right"
): AxisLabel[] => {
const startMonth = startOfMonth(start);
const endMonth = endOfMonth(end);
const numberOfMonths = differenceInMonths(endMonth, startMonth) + 1;
return new Array(numberOfMonths).fill(startMonth).map((thisMonth, i) => {
const month: Date = addMonths(thisMonth, i);
const { horizontalPosition, width } = horizontalPositionAndWidth(
month,
addMonths(month, 1),
start,
end
);
return {
direction: direction,
horizontalPosition: horizontalPosition,
label: format(month, "MMM yy"),
date: month,
width: width,
};
});
};
export const yearLabels = (
start: Date,
end: Date,
direction: "left" | "right"
): AxisLabel[] => {
const firstYear = startOfYear(start);
const lastYear = endOfYear(end);
const yearCount = differenceInYears(lastYear, start) + 1;
return new Array(yearCount).fill(firstYear).map((thisYear, i) => {
const year: Date = addYears(thisYear, i);
const { horizontalPosition, width } = horizontalPositionAndWidth(
year,
addYears(year, 1),
start,
end
);
return {
direction: direction,
horizontalPosition: horizontalPosition,
label: year.getFullYear().toString(),
date: year,
width: width,
};
});
};
const axisLabels = (
start: Date,
end: Date,
direction: "left" | "right"
): AxisLabel[] => {
const totalDays = differenceInDays(end, start);
if (totalDays < 40) {
return dayLabels(start, end, totalDays, direction);
} else if (totalDays < 370) {
return monthLabels(start, end, direction);
} else {
return yearLabels(start, end, direction);
}
};
export const AxisLabels = () => {
const { endDate, startDate, direction } = useTimelineContext();
const labels = axisLabels(startDate, endDate, direction).filter(isVisible);
return (
<div className="navdsi-timeline__axislabels" aria-hidden="true">
{labels.map((etikett) => (
<Detail
className="navdsi-timeline__axislabels-label"
as="div"
key={etikett.label}
style={{
justifyContent: direction === "left" ? "flex-start" : "flex-end",
[direction]: `${etikett.horizontalPosition}%`,
width: `${etikett.width}%`,
}}
>
{etikett.label}
</Detail>
))}
</div>
);
};
@@ -0,0 +1,66 @@
import { mergeRefs, Popover } from "@navikt/ds-react";
import { format } from "date-fns";
import React, { forwardRef, useMemo, useRef, useState } from "react";
import { useTimelineContext } from "./hooks/useTimelineContext";
import { position } from "./utils/calc";
import { TimelineComponentTypes } from "./utils/types.internal";
export interface TimelinePinProps {
/**
* Date position for the pin.
*/
date: Date;
/**
* Content in Pin Popover.
*/
children?: React.ReactNode;
}
export interface PinType
extends React.ForwardRefExoticComponent<
TimelinePinProps & React.RefAttributes<HTMLButtonElement>
> {
componentType: TimelineComponentTypes;
}
export const Pin = forwardRef<HTMLButtonElement, TimelinePinProps>(
({ date, children, ...rest }, ref) => {
const { startDate, endDate, direction } = useTimelineContext();
const [open, setOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement | null>(null);
const mergedRef = useMemo(() => mergeRefs([buttonRef, ref]), [ref]);
return (
<>
<div
className="navdsi-timeline__pin-wrapper"
style={{ [direction]: `${position(date, startDate, endDate)}%` }}
>
<button
{...rest}
ref={mergedRef}
className="navdsi-timeline__pin-button"
onClick={() => setOpen(!open)}
aria-label={`pin:${format(date, "dd.MM.yyyy")}`}
aria-expanded={open}
/>
</div>
{children && (
<Popover
open={open}
onClose={() => setOpen(false)}
anchorEl={buttonRef.current}
offset={18}
>
<Popover.Content>{children}</Popover.Content>
</Popover>
)}
</>
);
}
) as PinType;
Pin.componentType = "pin";
export default Pin;
@@ -0,0 +1,209 @@
import { endOfDay, isSameDay, startOfDay } from "date-fns";
import React, { forwardRef, useMemo, useRef, useState } from "react";
import { AxisLabels } from "./AxisLabels";
import { RowContext } from "./hooks/useRowContext";
import { TimelineContext } from "./hooks/useTimelineContext";
import {
useEarliestDate,
useLatestDate,
useTimelineRows,
} from "./hooks/useTimelineRows";
import Period, { PeriodType } from "./period";
import Pin, { PinType } from "./Pin";
import TimelineRow, { TimelineRowType } from "./TimelineRow";
import { parseRows } from "./utils/timeline";
import Zoom, { ZoomType } from "./zoom";
export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
children: React.ReactNode;
/**
* Decides startingpoint in timeline.
* Defaults to earliest date among the timeline periods.
*/
startDate?: Date;
/**
* Decides end-date for timeline.
* Defaults to the latest date among the timeline periods.
*/
endDate?: Date;
/**
* Decides direction which periods are sorted/displayed. "left" ascends from earliest date on left.
* @default "left"
*/
direction?: "left" | "right";
}
interface TimelineComponent
extends React.ForwardRefExoticComponent<TimelineProps> {
/**
* Built-in timeline row
*/
Row: TimelineRowType;
/**
* Built-in row period
*/
Period: PeriodType;
/**
* Built-in timeline pin
*/
Pin: PinType;
/**
* Built-in timeline zoom-component
*/
Zoom: ZoomType;
}
export const Timeline = forwardRef<HTMLDivElement, TimelineProps>(
({ children, startDate, endDate, direction = "left", ...rest }, ref) => {
const isMultipleRows = Array.isArray(children);
const firstFocusabled = useRef<
{ ref: HTMLButtonElement | null; id: number }[]
>([]);
if (!isMultipleRows) {
children = [children];
}
const rowChildren = React.Children.toArray(children).filter(
(c: any) => c?.type?.componentType === "row"
);
const pins = React.Children.toArray(children).filter(
(c: any) => c?.type?.componentType === "pin"
);
const zoomComponent = React.Children.toArray(children).find(
(c: any) => c?.type?.componentType === "zoom"
);
const rowsRaw = useMemo(() => {
return parseRows(rowChildren);
}, [rowChildren]);
const rows = rowsRaw.map((r) => {
if (r?.periods) {
return r.periods;
}
return [];
});
const initialStartDate = startOfDay(useEarliestDate({ startDate, rows }));
const [start, setStart] = useState(initialStartDate);
const [activeRow, setActiveRow] = useState<number | null>(null);
const [endInclusive, setEndInclusive] = useState(
endOfDay(useLatestDate({ endDate, rows }))
);
const initialEndDate = endOfDay(useLatestDate({ endDate, rows }));
const processedRows = useTimelineRows(
rowsRaw,
start,
endInclusive,
direction
);
const handleZoomChange = (zoomStart: Date) => {
if (direction === "left") {
if (isSameDay(zoomStart, start)) {
setStart(initialStartDate);
return;
}
setStart(zoomStart);
} else {
if (isSameDay(zoomStart, endInclusive)) {
setEndInclusive(initialEndDate);
return;
}
setEndInclusive(zoomStart);
}
};
const handleActiveRowChange = (key: string) => {
if (activeRow !== null && key === "ArrowDown") {
for (let i = activeRow + 1; i < processedRows.length; i++) {
const row = processedRows[i];
if (row.periods.find((p) => !!p.children || !!p.onSelectPeriod)) {
setActiveRow(i);
firstFocusabled.current.find((x) => x.id === i)?.ref?.focus();
break;
}
}
return;
}
if (activeRow !== null && key === "ArrowUp") {
for (let i = activeRow - 1; i >= 0; i--) {
const row = processedRows[i];
if (row.periods.find((p) => !!p.children || !!p.onSelectPeriod)) {
setActiveRow(i);
firstFocusabled.current.find((x) => x.id === i)?.ref?.focus();
break;
}
}
return;
}
};
const addFocusable = (ref: HTMLButtonElement | null, id: number) => {
let items = firstFocusabled.current;
items = items.filter((x) => x.id !== id);
items.push({ ref, id });
firstFocusabled.current = items;
};
return (
<TimelineContext.Provider
value={{
startDate: start,
endDate: endInclusive,
direction: direction,
setStart: (d) => handleZoomChange(d),
setEndInclusive: (d) => setEndInclusive(d),
activeRow: activeRow,
setActiveRow: (key) => handleActiveRowChange(key),
initiate: (i) => setActiveRow(i),
addFocusable,
}}
>
<div {...rest} ref={ref}>
<div className="navdsi-timeline">
<AxisLabels />
{pins.map((pin) => {
return pin;
})}
{processedRows.map((row, i) => {
return (
<RowContext.Provider
key={`row-${row.id}`}
value={{
periods: row.periods,
id: row.id,
active: activeRow === i,
index: i,
}}
>
<TimelineRow
{...row?.restProps}
ref={row?.ref}
label={row.label}
icon={row.icon}
headingTag={row.headingTag}
/>
</RowContext.Provider>
);
})}
</div>
{zoomComponent && zoomComponent}
</div>
</TimelineContext.Provider>
);
}
) as TimelineComponent;
Timeline.Row = TimelineRow;
Timeline.Period = Period;
Timeline.Pin = Pin;
Timeline.Zoom = Zoom;
export default Timeline;
@@ -0,0 +1,122 @@
import { BodyShort } from "@navikt/ds-react";
import { format } from "date-fns";
import React, { forwardRef } from "react";
import { PeriodContext } from "./hooks/usePeriodContext";
import { useRowContext } from "./hooks/useRowContext";
import { useTimelineContext } from "./hooks/useTimelineContext";
import Period from "./period";
import {
PositionedPeriod,
TimelineComponentTypes,
} from "./utils/types.internal";
import cl from "clsx";
export interface TimelineRowProps
extends React.HTMLAttributes<HTMLOListElement> {
/**
* Label for the timeline row
*/
label: string;
/**
* Heading level for the label e.g h2, h3...
* @default "h3"
*/
headingTag?: "h2" | "h3" | "h4" | "h5" | "h6";
/**
* Icon next to label
*/
icon?: React.ReactNode;
}
export interface TimelineRowType
extends React.ForwardRefExoticComponent<
TimelineRowProps & React.RefAttributes<HTMLOListElement>
> {
componentType: TimelineComponentTypes;
}
export const TimelineRow = forwardRef<HTMLOListElement, TimelineRowProps>(
({ label, headingTag = "h3", icon, ...rest }, ref) => {
const { periods, id, active } = useRowContext();
const { setActiveRow } = useTimelineContext();
const latest = periods.reduce((a, b) => {
return a.end > b.end ? a : b;
}, {} as PositionedPeriod);
const earliest = periods.reduce((a, b) => {
return a.end < b.end ? a : b;
}, {} as PositionedPeriod);
const firstFocusable = periods.find(
(p) => !!p.children || !!p.onSelectPeriod
);
return (
<>
{label && (
<BodyShort
as={headingTag}
id={`timeline-row-${id}`}
className="navdsi-timeline__row-label"
size="small"
>
{icon}
{label}
</BodyShort>
)}
<div
className={cl("navdsi-timeline__row", {
"navdsi-timeline__row--active": active,
})}
>
<ol
{...rest}
ref={ref}
aria-label={
periods.length === 0
? "Ingen perioder"
: `${format(earliest.start, "dd.MM.yyyy")} til ${format(
latest.end,
"dd.MM.yyyy"
)}`
}
className="navdsi-timeline__row-periods"
onKeyDown={(e) => {
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
e.preventDefault();
setActiveRow(e.key);
}
}}
>
{periods &&
periods.map((period) => {
return (
<li key={`period-${period.id}`}>
<PeriodContext.Provider
value={{
periodId: period.id,
firstFocus: firstFocusable?.id === period.id,
restProps: period?.restProps,
}}
>
<Period
start={period.start}
end={period.endInclusive}
icon={period.icon}
ref={period?.ref}
/>
</PeriodContext.Provider>
</li>
);
})}
</ol>
</div>
</>
);
}
) as TimelineRowType;
TimelineRow.componentType = "row";
export default TimelineRow;
@@ -0,0 +1,22 @@
import { createContext, useContext } from "react";
interface PeriodContextProps {
periodId: String;
firstFocus: boolean;
restProps?: any;
}
export const PeriodContext = createContext<PeriodContextProps>({
periodId: "",
firstFocus: false,
});
export const usePeriodContext = () => {
const context = useContext(PeriodContext);
if (!context) {
console.warn("usePeriodContext must be used with PeriodContext");
}
return context;
};
@@ -0,0 +1,26 @@
import { createContext, useContext } from "react";
import { PositionedPeriod } from "../utils/types.internal";
interface RowContextProps {
periods: PositionedPeriod[];
id: string;
active: boolean;
index: number;
}
export const RowContext = createContext<RowContextProps>({
periods: [],
id: "",
active: false,
index: 0,
});
export const useRowContext = () => {
const context = useContext(RowContext);
if (!context) {
console.warn("useRowContext must be used with RowContext");
}
return context;
};
@@ -0,0 +1,37 @@
import { createContext, useContext } from "react";
interface TimelineContextProps {
startDate: Date;
endDate: Date;
direction: "left" | "right";
setStart: (d: Date) => void;
setEndInclusive: (d: Date) => void;
activeRow: number | null;
setActiveRow: (i: string) => void;
initiate: (i: number) => void;
addFocusable: (ref: HTMLButtonElement | null, id: number) => void;
}
export const TimelineContext = createContext<TimelineContextProps>({
startDate: new Date(),
endDate: new Date(),
direction: "left",
setStart: () => null,
setEndInclusive: () => null,
activeRow: 0,
setActiveRow: () => null,
initiate: () => null,
addFocusable: () => null,
});
export const useTimelineContext = () => {
const context = useContext(TimelineContext);
if (!context) {
console.warn(
"useTimelineContext must be used with TimelineContext (<Timeline />)"
);
}
return context;
};
@@ -0,0 +1,161 @@
import { useMemo } from "react";
import { addDays, endOfDay, isAfter, startOfDay, subDays } from "date-fns";
import { lastPeriod } from "../utils/sort";
import { Period } from "../utils/types.external";
import {
InternalSimpleTimeline,
PositionedPeriod,
} from "../utils/types.internal";
import { horizontalPositionAndWidth } from "../utils/calc";
import { invisiblePeriods, withinADay } from "../utils/filter";
const spatialPeriod = (
period: Period,
timelineStart: Date,
timelineEndInclusive: Date,
direction: "left" | "right" = "left",
i: number,
periods: PositionedPeriod[],
rowIndex: number
): PositionedPeriod => {
const start = period.start;
const endInclusive = period.end;
const rightOverlap =
i < periods.length - 1 && !isAfter(periods[i + 1].start, endInclusive);
const { horizontalPosition, width } = horizontalPositionAndWidth(
startOfDay(start),
endOfDay(
rightOverlap ? startOfDay(subDays(periods[i + 1].start, 1)) : endInclusive
),
timelineStart,
timelineEndInclusive
);
return {
id: `r-${rowIndex}-p-${i}`,
start: start,
endInclusive: endInclusive,
horizontalPosition: horizontalPosition,
direction: direction,
width: width,
end: endInclusive,
status: period.status,
onSelectPeriod: period.onSelectPeriod,
icon: period.icon,
children: period.children,
isActive: period.isActive,
statusLabel: period.statusLabel,
};
};
const adjustedEdges = (
period: PositionedPeriod,
i: number,
allPeriods: PositionedPeriod[]
): PositionedPeriod => {
const left =
i > 0 && withinADay(period.start, allPeriods[i - 1].endInclusive);
const right =
i < allPeriods.length - 1 &&
withinADay(allPeriods[i + 1].start, period.endInclusive);
return left && right
? { ...period, cropped: "both" }
: left
? { ...period, cropped: "left" }
: right
? { ...period, cropped: "right" }
: period;
};
const trimmedPeriods = (period: PositionedPeriod) => {
let { horizontalPosition, width, cropped } = period;
if (horizontalPosition + width > 100) {
width = 100 - horizontalPosition;
cropped = cropped === "left" || cropped === "both" ? "both" : "right";
}
if (horizontalPosition < 0 && horizontalPosition + width > 0) {
width = horizontalPosition + width;
horizontalPosition = 0;
cropped = cropped === "right" || cropped === "both" ? "both" : "left";
}
return {
...period,
width: width,
horizontalPosition: horizontalPosition,
cropped: cropped,
};
};
export const useTimelineRows = (
rows: any,
startDate: Date,
endDate: Date,
direction: "left" | "right"
): InternalSimpleTimeline[] =>
useMemo(
() =>
rows.map((periods: InternalSimpleTimeline, i: number) => {
const rowIndex = i;
const timelinePeriods = periods.periods
.sort((a: Period, b: Period) => a.start.valueOf() - b.start.valueOf())
.map((period: Period & { restProps?: any; ref?: any }, i) => ({
...spatialPeriod(
period,
startDate,
endDate,
direction,
i,
periods.periods,
rowIndex
),
restProps: period?.restProps,
ref: period?.ref,
}))
.sort(lastPeriod)
.map(adjustedEdges)
.map(trimmedPeriods)
.filter(invisiblePeriods);
return {
id: `tl-row-${rowIndex}`,
label: periods.label,
headingTag: periods.headingTag || "h3",
icon: periods.icon,
periods:
direction === "left" ? timelinePeriods : timelinePeriods.reverse(),
restProps: periods?.restProps,
ref: periods?.ref,
};
}),
[rows, startDate, endDate, direction]
);
const earliestDate = (earliest: Date, period: Period) =>
period.start < earliest ? period.start : earliest;
const earliestFomDate = (rader: Period[][]) =>
rader.flat().reduce(earliestDate, new Date());
export const useEarliestDate = ({ startDate, rows }: any) =>
useMemo(
() => (startDate ? startDate : earliestFomDate(rows)),
[startDate, rows]
);
const latestDate = (latest: Date, period: Period) =>
period.end > latest ? period.end : latest;
const latestTomDate = (rows: Period[][]) =>
rows.flat().reduce(latestDate, new Date(0));
export const useLatestDate = ({ endDate, rows }: any) =>
useMemo(
() => (endDate ? endDate : addDays(latestTomDate(rows), 1)),
[endDate, rows]
);
@@ -0,0 +1,6 @@
export { default as Timeline } from "./Timeline";
export type { TimelineProps } from "./Timeline";
export type { TimelineRowProps } from "./TimelineRow";
export type { TimelinePinProps } from "./Pin";
export type { TimelinePeriodProps } from "./period";
export type { TimelineZoomButtonProps } from "./zoom/ZoomButton";
@@ -0,0 +1,91 @@
import { mergeRefs, Popover } from "@navikt/ds-react";
import cl from "clsx";
import React, { useMemo, useRef, useState } from "react";
import { usePeriodContext } from "../hooks/usePeriodContext";
import { useRowContext } from "../hooks/useRowContext";
import { useTimelineContext } from "../hooks/useTimelineContext";
import { ariaLabel, getConditionalClasses } from "../utils/period";
import { PeriodProps } from "./index";
interface TimelineClickablePeriodProps extends PeriodProps {
onSelectPeriod?: () => void;
isActive?: boolean;
periodRef: React.ForwardedRef<HTMLButtonElement>;
}
const ClickablePeriod = React.memo(
({
onSelectPeriod,
start,
end,
status,
cropped,
direction,
left,
width,
icon,
children,
isActive,
statusLabel,
restProps,
periodRef,
}: TimelineClickablePeriodProps) => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
const [selected, setSelected] = useState(false);
const { index } = useRowContext();
const { firstFocus } = usePeriodContext();
const { initiate, addFocusable } = useTimelineContext();
const mergedRef = useMemo(
() => mergeRefs([buttonRef, periodRef]),
[periodRef]
);
return (
<>
<button
{...restProps}
ref={(r) => {
firstFocus && addFocusable(r, index);
mergedRef(r);
}}
onClick={() => {
children && setSelected((x) => !x);
onSelectPeriod?.();
}}
aria-label={ariaLabel(start, end, status, statusLabel)}
className={cl(
"navdsi-timeline__period--clickable",
getConditionalClasses(cropped, direction, status),
restProps?.className,
{
"navdsi-timeline__period--selected": isActive,
}
)}
style={{
width: `${width}%`,
[direction]: `${left}%`,
}}
aria-expanded={children ? selected : undefined}
onFocus={() => {
initiate(index);
}}
>
<div className="navdsi-timeline__period--inner">{icon}</div>
</button>
{children && (
<Popover
open={selected}
onClose={() => setSelected(false)}
anchorEl={buttonRef.current}
strategy="fixed"
>
<Popover.Content>{children}</Popover.Content>
</Popover>
)}
</>
);
}
);
export default ClickablePeriod;
@@ -0,0 +1,44 @@
import React from "react";
import { ariaLabel, getConditionalClasses } from "../utils/period";
import { PeriodProps } from "./index";
import cl from "clsx";
interface TimelineNonClickablePeriodProps extends PeriodProps {
periodRef?: React.ForwardedRef<HTMLDivElement>;
}
const NonClickablePeriod = ({
start,
end,
status,
cropped,
direction,
left,
width,
icon,
statusLabel,
restProps,
periodRef,
}: TimelineNonClickablePeriodProps) => {
return (
<div
ref={periodRef}
{...restProps}
className={cl(
getConditionalClasses(cropped, direction, status),
restProps?.classname
)}
style={{
width: `${width}%`,
[direction]: `${left}%`,
}}
>
<div className="navdsi-timeline__period--inner">
{icon}
<p className="sr-only">{ariaLabel(start, end, status, statusLabel)}</p>
</div>
</div>
);
};
export default NonClickablePeriod;
@@ -0,0 +1,130 @@
import React, { forwardRef } from "react";
import { usePeriodContext } from "../hooks/usePeriodContext";
import { useRowContext } from "../hooks/useRowContext";
import { TimelineComponentTypes } from "../utils/types.internal";
import ClickablePeriod from "./ClickablePeriod";
import NonClickablePeriod from "./NonClickablePeriod";
export interface TimelinePeriodProps
extends React.HTMLAttributes<HTMLDivElement> {
/**
* Period start date.
*/
start: Date;
/**
* Period end date.
*/
end: Date;
/**
* Icon for easier visual identification.
*/
icon?: React.ReactNode;
/**
* Period status.
* @default "neutral"
*/
status?: "success" | "warning" | "danger" | "info" | "neutral";
/**
* Status label for screen-readers
* e.g "Sykemeldt", "foreldrepermisjon"
*/
statusLabel?: string;
/**
* Callback when selecting a period.
*/
onSelectPeriod?: () => void;
/**
* Content displayed in Popover on click.
*/
children?: React.ReactNode;
/**
* Visual active inidcation on period
* @note Make sure only one period is active at a time
*/
isActive?: boolean;
}
export interface PeriodProps {
start: Date;
end: Date;
status: string;
cropped: string;
direction: string;
width: Number;
left: Number;
icon?: React.ReactNode;
children?: React.ReactNode;
statusLabel?: string;
restProps?: any;
}
export interface PeriodType
extends React.ForwardRefExoticComponent<
TimelinePeriodProps &
React.RefAttributes<HTMLDivElement | HTMLButtonElement>
> {
componentType: TimelineComponentTypes;
}
export const Period = forwardRef<HTMLDivElement, TimelinePeriodProps>(
({ icon }, ref) => {
const { periods } = useRowContext();
const { periodId, restProps } = usePeriodContext();
const period = periods.find((p) => p.id === periodId);
if (!period) {
return <></>;
}
const {
start,
endInclusive,
width,
horizontalPosition,
status = "neutral",
onSelectPeriod,
cropped,
direction,
children,
isActive,
statusLabel,
} = period;
return onSelectPeriod || children ? (
<ClickablePeriod
periodRef={ref as React.ForwardedRef<HTMLButtonElement>}
start={start}
end={endInclusive}
status={status}
onSelectPeriod={onSelectPeriod}
cropped={cropped || ""}
direction={direction}
width={width}
left={horizontalPosition}
icon={icon}
children={children}
isActive={isActive}
statusLabel={statusLabel}
restProps={restProps}
/>
) : (
<NonClickablePeriod
periodRef={ref}
start={start}
end={endInclusive}
status={status}
cropped={cropped || ""}
direction={direction}
width={width}
left={horizontalPosition}
icon={icon}
statusLabel={statusLabel}
restProps={restProps}
/>
);
}
) as PeriodType;
Period.componentType = "period";
export default Period;
@@ -0,0 +1,326 @@
import { SuccessFilled } from "@navikt/ds-icons";
import { useState } from "@storybook/addons";
import { Meta } from "@storybook/react";
import * as React from "react";
import Timeline from "./Timeline";
export default {
title: "ds-react-internal/Timeline",
component: Timeline,
argTypes: {},
} as Meta;
const DummyLabel = () => {
return (
<div
style={{
width: "239px",
margin: 0,
textAlign: "left",
fontSize: "14px",
}}
>
<p>Periode: 15.07.2019 - 25.07.2019</p>
<p>Utbetalt: 12 345,00 kr</p>
<p style={{ color: "red" }}>Dager igjen: 0</p>
</div>
);
};
const row1 = [
{
id: "1",
start: new Date("Jan 1 2022"),
end: new Date("Jan 31 2022"),
status: "success",
icon: <SuccessFilled aria-hidden />,
statusLabel: "Sykemeldt",
},
{
id: "2",
start: new Date("Feb 1 2022"),
end: new Date("Mar 15 2022"),
status: "danger",
onSelectPeriod: () => console.log("PERIOD SELECTED!"),
statusLabel: "Sykemeldt",
},
{
id: "3",
start: new Date("May 2 2022"),
end: new Date("May 25 2022"),
status: "success",
icon: <SuccessFilled aria-hidden />,
statusLabel: "Sykemeldt",
},
{
id: "4",
start: new Date("Mar 1 2022"),
end: new Date("Mar 31 2022"),
status: "success",
onSelectPeriod: () => console.log("PERIOD SELECTED!"),
icon: <SuccessFilled aria-hidden />,
label: "test",
statusLabel: "Sykemeldt",
},
{
id: "5",
start: new Date("Jul 1 2022"),
end: new Date("Jul 31 2022"),
status: "warning",
icon: <SuccessFilled aria-hidden />,
onSelectPeriod: () => console.log("PERIOD SELECTED!"),
statusLabel: "Sykemeldt",
},
{
id: "6",
start: new Date("Aug 1 2022"),
end: new Date("Aug 30 2022"),
status: "warning",
icon: <SuccessFilled aria-hidden />,
statusLabel: "Sykemeldt",
},
];
const row2 = [
{
id: "7",
start: new Date("May 13 2022"),
end: new Date("May 25 2022"),
status: "warning",
onSelectPeriod: () => console.log("PERIOD SELECTED!"),
icon: <SuccessFilled aria-hidden />,
children: <DummyLabel />,
},
{
id: "8",
start: new Date("Feb 1 2022"),
end: new Date("May 2 2022"),
status: "neutral",
onSelectPeriod: () => console.log("PERIOD SELECTED!"),
icon: <SuccessFilled aria-hidden />,
children: <DummyLabel />,
},
];
export const Default = () => {
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Row label="Row 1" icon={<SuccessFilled aria-hidden />}>
{row1.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
<Timeline.Row label="Row 2" icon={<SuccessFilled aria-hidden />}>
{row2.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
</Timeline>
</div>
);
};
export const WithPins = () => {
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Pin date={new Date("Apr 15 2022")}>Pin 1</Timeline.Pin>
<Timeline.Pin date={new Date("Jun 12 2022")}>Pin 2</Timeline.Pin>
<Timeline.Pin date={new Date("Jul 28 2022")}>Pin 3</Timeline.Pin>
<Timeline.Row label="Row 1" icon={<SuccessFilled aria-hidden />}>
{row1.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
<Timeline.Row label="Row 2" icon={<SuccessFilled aria-hidden />}>
{row2.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
</Timeline>
</div>
);
};
export const WithZoom = () => {
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Row label="Row 1" icon={<SuccessFilled aria-hidden />}>
{row1.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
<Timeline.Row label="Row 2" icon={<SuccessFilled aria-hidden />}>
{row2.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
icon={p.icon}
/>
);
})}
</Timeline.Row>
<Timeline.Zoom>
<Timeline.Zoom.Button label="3 mnd" interval="month" count={3} />
<Timeline.Zoom.Button label="7 mnd" interval="month" count={7} />
<Timeline.Zoom.Button label="9 mnd" interval="month" count={9} />
</Timeline.Zoom>
</Timeline>
</div>
);
};
export const ActivePeriod = () => {
const [activePeriod, setActivePeriod] = useState(row1[0]);
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Pin date={new Date("Apr 15 2022")}>Pin 1</Timeline.Pin>
<Timeline.Pin date={new Date("Jun 12 2022")}>Pin 2</Timeline.Pin>
<Timeline.Pin date={new Date("Jul 28 2022")}>Pin 3</Timeline.Pin>
<Timeline.Row label="Rad 1" icon={<SuccessFilled aria-hidden />}>
{row1.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
onSelectPeriod={() => {
setActivePeriod(p);
p?.onSelectPeriod?.();
}}
icon={p.icon}
isActive={activePeriod.id === p.id}
statusLabel={p.statusLabel}
>
{p.children}
</Timeline.Period>
);
})}
</Timeline.Row>
<Timeline.Row label="Rad 2">
{row2.map((p: any, i) => {
return (
<Timeline.Period
key={p.id}
start={p.start}
end={p.end}
status={p.status}
onSelectPeriod={() => {
setActivePeriod(p);
p?.onSelectPeriod?.();
}}
icon={p.icon}
isActive={activePeriod.id === p.id}
statusLabel={p.statusLabel}
>
{p.children}
</Timeline.Period>
);
})}
</Timeline.Row>
<Timeline.Row label="Rad 3">
<Timeline.Period
start={new Date("Jan 1 2022")}
end={new Date("Aug 20 2022")}
status="info"
icon={<SuccessFilled aria-hidden />}
/>
</Timeline.Row>
</Timeline>
</div>
);
};
export const WithDayLabels = () => {
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Row label="Row 1" icon={<SuccessFilled aria-hidden />}>
<Timeline.Period
start={new Date("Feb 4 2022")}
end={new Date("Feb 13 2022")}
status="success"
/>
</Timeline.Row>
<Timeline.Row label="Row 2" icon={<SuccessFilled aria-hidden />}>
<Timeline.Period
start={new Date("Feb 17 2022")}
end={new Date("Feb 22 2022")}
status="warning"
/>
</Timeline.Row>
</Timeline>
</div>
);
};
export const WithYearLabels = () => {
return (
<div style={{ width: "80vw" }}>
<Timeline>
<Timeline.Row label="Row 1" icon={<SuccessFilled aria-hidden />}>
<Timeline.Period
start={new Date("Feb 4 2022")}
end={new Date("Feb 13 2028")}
status="success"
/>
</Timeline.Row>
<Timeline.Row label="Row 2" icon={<SuccessFilled aria-hidden />}>
<Timeline.Period
start={new Date("Feb 17 2024")}
end={new Date("Feb 22 2031")}
status="warning"
/>
</Timeline.Row>
</Timeline>
</div>
);
};
@@ -0,0 +1,26 @@
import { differenceInMilliseconds } from "date-fns";
export const position = (date: Date, start: Date, endInclusive: Date) => {
const diff = differenceInMilliseconds(endInclusive, start);
return (differenceInMilliseconds(date, start) / diff) * 100;
};
export const horizontalPositionAndWidth = (
start: Date,
endInclusive: Date,
timelineStart: Date,
timelineEndInclusive: Date
) => {
const horizontalPosition = position(
start,
timelineStart,
timelineEndInclusive
);
const width =
position(endInclusive, timelineStart, timelineEndInclusive) -
horizontalPosition;
return {
horizontalPosition: horizontalPosition,
width: width,
};
};
@@ -0,0 +1,32 @@
import { differenceInDays } from "date-fns";
import { PeriodProps } from "../period";
import { Spatial } from "./types.internal";
export interface Positioned {
horizontalPosition: number;
direction: "left" | "right";
}
export const isVisible = ({ horizontalPosition }: Positioned): boolean =>
horizontalPosition <= 98 && horizontalPosition >= 0;
export const getFirstDate = (periods: any) => {
return periods.sort(
(a: PeriodProps, b: PeriodProps) => a.start.getTime() - b.start.getTime()
)[0].start;
};
export const getLastDate = (periods: any) => {
return periods.sort(
(a: PeriodProps, b: PeriodProps) => a.end.getTime() - b.end.getTime()
)[periods.length - 1].end;
};
export const withinADay = (date1: Date, date2: Date): boolean =>
differenceInDays(date1, date2) <= 1;
export const invisiblePeriods = ({
horizontalPosition,
width,
}: Positioned & Spatial) =>
horizontalPosition >= 0 && horizontalPosition <= 100 && width > 0;
@@ -0,0 +1 @@
export { getFirstDate, getLastDate, isVisible, Positioned } from "./filter";
@@ -0,0 +1,48 @@
import cl from "clsx";
import { format } from "date-fns";
export const getConditionalClasses = (
cropped: string,
direction: string,
status: string
) => {
return cl(`navdsi-timeline__period navdsi-timeline__period--${status}`, {
"navdsi-timeline__period--connected-both": cropped === "both",
"navdsi-timeline__period--connected-right":
(cropped === "right" && direction === "left") ||
(cropped === "left" && direction === "right"),
"navdsi-timeline__period--connected-left":
(cropped === "left" && direction === "left") ||
(cropped === "right" && direction === "right"),
});
};
const translateStatus = (status: string): string => {
switch (status) {
case "success":
return "Suksess";
case "warning":
return "Advarsel";
case "danger":
return "Fare";
case "info":
return "Info";
case "neutral":
return "Nøytral";
default:
return status;
}
};
export const ariaLabel = (
startDate: Date,
endDate: Date,
status: string,
statusLabel?: string
): string => {
const start = format(startDate, "dd.MM.yyyy");
const end = format(endDate, "dd.MM.yyyy");
return `${
statusLabel ? statusLabel : translateStatus(status)
} fra ${start} til ${end}`;
};
@@ -0,0 +1,11 @@
import { differenceInMilliseconds } from "date-fns";
import { Period, PositionedPeriod } from "./types.internal";
export const lastDate = (a: Date, b: Date): number =>
differenceInMilliseconds(a, b);
export const lastPeriod = (a: PositionedPeriod, b: PositionedPeriod): number =>
a.horizontalPosition - b.horizontalPosition;
export const lastSinglePeriod = (a: Period, b: Period): number =>
differenceInMilliseconds(b.endInclusive, a.endInclusive);
Loaded 100 of 439 files, more files were not shown because too many files have changed in this diff. Show more