Compare commits

...
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] ede1f5858a Version Packages (#1711)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-04 14:50:55 +01:00
Ken ad9e7165bb 💚 dispatch cdn-publish 2022-11-04 14:46:55 +01:00
Kenandolejorgenbakken 77302a30b8 Ikonsynk Figma (#1709)
Co-authored-by: olejorgenbakken <olejorgenbakken@users.noreply.github.com>
2022-11-04 14:45:15 +01:00
Andreas Nordahl 0ef12ef601 upload font files to cdn (#1710) 2022-11-04 14:29:56 +01:00
Ken 4174f9a7b4 📝 Patch-version 2022-11-02 23:37:19 +01:00
Ken 608f158d70 🐛 Datepicker validation error var flipped 2022-11-02 22:40:36 +01:00
Ken 34d41ecc78 📝 Patch-version 2022-11-02 20:42:21 +01:00
Ken 7e62365a60 🔥 Fjernet flaky e2e test 2022-11-02 19:29:52 +01:00
Ken 8565f410a1 💄 Nye tags i sidebar 2022-11-02 18:16:42 +01:00
Ken 46d70820df 📝 Version-bump 2022-11-02 18:09:27 +01:00
github-actions[bot]andgithub-actions[bot] 67e66ffe02 Version Packages (#1707)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-02 16:29:26 +01:00
Ken e19bf67b33 [FEATURE] Tag varianter (#1684) 2022-11-02 16:25:31 +01:00
Ken 97c5f60e91 Chips (#1668) 2022-11-02 16:20:42 +01:00
Ken ea5293c28d ⬆️ Patch-versjon 2022-11-02 10:57:45 +01:00
Ken 6a58efa9a9 changeset 2022-11-02 10:55:34 +01:00
Ken c95f33679e 💚 Fikset timezones for jest-tester
✨ Timekeeper-demo

✨ timezone for jest-tester
2022-11-02 10:53:19 +01:00
Ken b52a5e02a0 ✨ Patch-versjoner 2022-11-01 23:57:38 +01:00
Ken ab3ef0d34b ✨ Validering i Date-komponenter
🐛 Date-formats skaper problemer for ranged-input

🐛 UX tweaks for inputs

🐛 Fikset weekendValidation

🎨 Custom input-format

🎨 validation api

🎉 range-validation

🎨 Export validation-types

🎨 Datepicker-validation

🎨 monthpicker validation

🎨 Småbugs med disabled datepicker

💄 reversert capitalization i månedsnavn
2022-11-01 23:54:27 +01:00
Ken 69798f6ee2 🔥 Fjernet flaky e2e test 2022-11-01 11:00:35 +01:00
Ken ee14586beb ⬆️ yarn-lock 2022-11-01 10:40:34 +01:00
90 changed files with 2122 additions and 506 deletions

No files matched your search

+31
View File
@@ -0,0 +1,31 @@
name: "push-to-cdn"
on:
workflow_dispatch:
push:
branches:
- "master"
paths:
- "fonts/**"
jobs:
upload:
runs-on: ubuntu-latest
permissions:
contents: "read"
id-token: "write"
steps:
- uses: "actions/checkout@v3"
- id: upload
uses: nais/frontend-plattform-cdn-upload-action@main
with:
cdn-environment: cdn.nav.no
cdn-team-name: aksel
source: ./fonts
destination: "" # uploads folder to team root
- run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
shell: bash
+4
View File
@@ -15,3 +15,7 @@
.rowgap[data-theme="dark"] {
background-color: #262626;
}
.rowgap-wrap {
flex-wrap: wrap;
}
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-codemod
## 1.5.4
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
## 1.4.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "1.4.2",
"version": "1.5.4",
"description": "NAV designsystem codemods",
"author": "NAV Designsystem team",
"license": "MIT",
+40
View File
@@ -1,5 +1,45 @@
# @navikt/ds-css
## 1.5.4
### Patch Changes
- [#1709](https://github.com/navikt/Designsystemet/pull/1709) [`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert ikoner
## 1.5.3
### Patch Changes
- Byttet om på alt-farge rekkefølge
## 1.5.2
### Patch Changes
- :memo: Rename FilterChips to ToggleChips
## 1.5.1
### Patch Changes
- Flex-wrap chips.css
## 1.5.0
### Minor Changes
- [#1684](https://github.com/navikt/Designsystemet/pull/1684) [`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Oppdaterte tag-varianter
- [#1668](https://github.com/navikt/Designsystemet/pull/1668) [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Chips komponent :sparkles:
## 1.4.4
## 1.4.3
### Patch Changes
- :sparkles: Validering og inputFormat i Date-komponenter
## 1.4.2
## 1.4.1
+141
View File
@@ -0,0 +1,141 @@
.navds-chips {
display: flex;
gap: var(--navds-spacing-2);
margin: 0;
padding: 0;
list-style: none;
flex-wrap: wrap;
}
.navds-chips :where(li) {
margin: 0;
padding: 0;
list-style: none;
display: block;
}
.navds-chips__chip {
all: unset;
display: flex;
cursor: pointer;
align-items: center;
justify-content: center;
gap: 0.125rem;
margin: 0;
padding: 0 var(--navds-spacing-3);
text-decoration: none;
border-radius: var(--navds-border-radius-full);
min-height: 32px;
}
.navds-chips--small .navds-chips__chip {
min-height: 24px;
padding: 0 var(--navds-spacing-2);
}
.navds-chips__toggle {
box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border, var(--navds-global-color-gray-500));
background-color: var(--ac-chip-toggle-bg, rgb(0 0 0 / 0.055));
}
.navds-chips--small .navds-chips__toggle {
gap: var(--navds-spacing-1);
}
.navds-chips__toggle:hover {
box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border-hover, var(--navds-global-color-gray-600));
background-color: var(--ac-chip-toggle-bg-hover, rgb(0 0 0 / 0.1));
}
.navds-chips__toggle[aria-pressed="true"] {
box-shadow: none;
background-color: var(--ac-chip-toggle-bg-pressed, var(--navds-global-color-deepblue-500));
color: var(--ac-chip-toggle-text-pressed, var(--navds-global-color-white));
}
.navds-chips__toggle[aria-pressed="true"]:hover {
background-color: var(--ac-chip-toggle-bg-pressed-hover, var(--navds-global-color-deepblue-600));
}
.navds-chips__toggle:focus-visible {
box-shadow: 0 0 0 2px var(--navds-global-color-blue-800);
}
.navds-chips__toggle[aria-pressed="true"]:focus-visible,
.navds-chips__toggle:active:focus-visible {
box-shadow: inset 0 0 0 1px var(--navds-global-color-white), 0 0 0 2px var(--navds-global-color-blue-800);
}
.navds-chips__removable--action {
background-color: var(--ac-chip-removable-action-bg, var(--navds-global-color-deepblue-500));
color: var(--ac-chip-removable-action-text, var(--navds-global-color-white));
}
.navds-chips__removable--neutral {
color: var(--ac-chip-removable-neutral-text, var(--navds-global-color-gray-900));
background-color: var(--ac-chip-removable-neutral-bg, rgb(0 0 0/ 0.055));
box-shadow: inset 0 0 0 1px var(--ac-chip-removable-neutral-border, var(--navds-global-color-gray-500));
}
.navds-chips__removable-icon {
width: 1.5rem;
height: 1.5rem;
display: grid;
place-items: center;
border-radius: var(--navds-border-radius-full);
}
.navds-chips__toggle-icon {
width: 1.25rem;
height: 1.25rem;
display: grid;
place-items: center;
border-radius: var(--navds-border-radius-full);
}
.navds-chips--small .navds-chips__toggle-icon {
width: 1rem;
height: 1rem;
}
.navds-chips--small .navds-chips__removable-icon {
width: 1.25rem;
height: 1.25rem;
}
.navds-chips--small .navds-chips__removable-icon > svg {
width: 0.75rem;
}
.navds-chips__removable--action:focus-visible {
box-shadow: inset 0 0 0 1px var(--navds-global-color-white), 0 0 0 2px var(--navds-global-color-blue-800);
}
.navds-chips__removable--neutral:focus-visible {
box-shadow: 0 0 0 2px var(--navds-global-color-blue-800);
}
.navds-chips__removable--action:hover {
background-color: var(--ac-chip-removable-action-bg-hover, var(--navds-global-color-deepblue-700));
}
.navds-chips__removable--neutral:hover {
background-color: var(--ac-chip-removable-action-bg-hover, rgb(0 0 0 / 0.1));
box-shadow: inset 0 0 0 1px var(--ac-chip-removable-neutral-border-hover, var(--navds-global-color-gray-600));
}
.navds-chips--icon-left {
padding-left: 0.375rem;
}
.navds-chips--icon-right {
padding-right: var(--navds-spacing-1);
}
.navds-chips--small .navds-chips--icon-right {
padding-right: 0.125rem;
}
.navds-chips--small .navds-chips--icon-left {
padding-left: 0.375rem;
}
+5
View File
@@ -13,6 +13,10 @@
gap: var(--navds-spacing-5);
}
.navds-date__caption-label {
text-transform: capitalize;
}
.navds-date .rdp-head_cell {
text-transform: capitalize;
font-size: var(--navds-font-size-small);
@@ -86,6 +90,7 @@
text-align: center;
width: 3rem;
height: 2.75rem;
text-transform: capitalize;
border-radius: var(--navds-border-radius-medium);
cursor: pointer;
}
+1
View File
@@ -7,6 +7,7 @@
@import "button.css";
@import "content-container.css";
@import "chat.css";
@import "chips.css";
@import "guide-panel.css";
@import "form/index.css";
@import "help-text.css";
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "1.4.2",
"version": "1.5.4",
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
@@ -20,7 +20,7 @@
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.4.2",
"@navikt/ds-tokens": "^1.5.4",
"normalize.css": "^8.0.1",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
+93 -14
View File
@@ -14,38 +14,117 @@
.navds-tag {
border: 1px solid;
border-color: var(--navds-tag-color-border);
border-radius: var(--navds-border-radius-medium);
background-color: var(--navds-tag-color-background);
border-radius: var(--navds-border-radius-small);
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.125rem var(--navds-spacing-3);
padding: 0.125rem var(--navds-spacing-2);
min-height: 32px;
line-height: 1;
}
.navds-tag--small {
min-height: 24px;
padding-right: var(--navds-spacing-1);
padding-left: var(--navds-spacing-1);
padding: 0 0.375rem;
}
.navds-tag--xsmall {
min-height: 20px;
padding: 0 var(--navds-spacing-1);
}
.navds-tag--error {
background-color: var(--navds-tag-color-error-background);
border-color: var(--navds-tag-color-error-border);
border-color: var(--ac-tag-error-border, var(--navds-global-color-red-500));
background-color: var(--ac-tag-error-bg, var(--navds-global-color-red-50));
color: var(--ac-tag-error-text, var(--navds-global-color-gray-900));
}
.navds-tag--error-filled {
border-color: transparent;
background-color: var(--ac-tag-error-filled-bg, var(--navds-global-color-red-500));
color: var(--ac-tag-error-filled-text, var(--navds-global-color-white));
}
.navds-tag--success {
background-color: var(--navds-tag-color-success-background);
border-color: var(--navds-tag-color-success-border);
border-color: var(--ac-tag-success-border, var(--navds-global-color-green-500));
background-color: var(--ac-tag-success-bg, var(--navds-global-color-green-50));
color: var(--ac-tag-success-text, var(--navds-global-color-gray-900));
}
.navds-tag--success-filled {
border-color: transparent;
background-color: var(--ac-tag-success-filled-bg, var(--navds-global-color-green-500));
color: var(--ac-tag-success-filled-text, var(--navds-global-color-white));
}
.navds-tag--warning {
background-color: var(--navds-tag-color-warning-background);
border-color: var(--navds-tag-color-warning-border);
border-color: var(--ac-tag-warning-border, var(--navds-global-color-orange-600));
background-color: var(--ac-tag-warning-bg, var(--navds-global-color-orange-50));
color: var(--ac-tag-warning-text, var(--navds-global-color-gray-900));
}
.navds-tag--warning-filled {
border-color: transparent;
background-color: var(--ac-tag-warning-filled-bg, var(--navds-global-color-orange-500));
color: var(--ac-tag-warning-filled-text, var(--navds-global-color-gray-900));
}
.navds-tag--info {
background-color: var(--navds-tag-color-info-background);
border-color: var(--navds-tag-color-info-border);
border-color: var(--ac-tag-info-border, var(--navds-global-color-lightblue-700));
background-color: var(--ac-tag-info-bg, var(--navds-global-color-lightblue-50));
color: var(--ac-tag-info-text, var(--navds-global-color-gray-900));
}
.navds-tag--info-filled {
border-color: transparent;
background-color: var(--ac-tag-info-filled-bg, var(--navds-global-color-lightblue-500));
color: var(--ac-tag-info-filled-text, var(--navds-global-color-gray-900));
}
.navds-tag--neutral {
border-color: var(--ac-tag-neutral-border, var(--navds-global-color-gray-500));
background-color: var(--ac-tag-neutral-bg, var(--navds-global-color-gray-100));
color: var(--ac-tag-neutral-text, var(--navds-global-color-gray-900));
}
.navds-tag--neutral-filled {
border-color: transparent;
background-color: var(--ac-tag-neutral-filled-bg, var(--navds-global-color-gray-800));
color: var(--ac-tag-neutral-filled-text, var(--navds-global-color-white));
}
.navds-tag--alt1 {
border-color: var(--ac-tag-alt1-border, var(--navds-global-color-purple-400));
background-color: var(--ac-tag-alt1-bg, var(--navds-global-color-purple-100));
color: var(--ac-tag-alt1-text, var(--navds-global-color-gray-900));
}
.navds-tag--alt1-filled {
border-color: transparent;
background-color: var(--ac-tag-alt1-filled-bg, var(--navds-global-color-purple-400));
color: var(--ac-tag-alt1-filled-text, var(--navds-global-color-white));
}
.navds-tag--alt2 {
border-color: var(--ac-tag-alt2-border, var(--navds-global-color-limegreen-500));
background-color: var(--ac-tag-alt2-bg, var(--navds-global-color-limegreen-100));
color: var(--ac-tag-alt2-text, var(--navds-global-color-gray-900));
}
.navds-tag--alt2-filled {
border-color: transparent;
background-color: var(--ac-tag-alt2-filled-bg, var(--navds-global-color-limegreen-400));
color: var(--ac-tag-alt2-filled-text, var(--navds-global-color-gray-900));
}
.navds-tag--alt3 {
border-color: var(--ac-tag-alt3-border, var(--navds-global-color-deepblue-400));
background-color: var(--ac-tag-alt3-bg, var(--navds-global-color-deepblue-100));
color: var(--ac-tag-alt3-text, var(--navds-global-color-gray-900));
}
.navds-tag--alt3-filled {
border-color: transparent;
background-color: var(--ac-tag-alt3-filled-bg, var(--navds-global-color-deepblue-500));
color: var(--ac-tag-alt3-filled-text, var(--navds-global-color-white));
}
+63
View File
@@ -1,5 +1,68 @@
# @navikt/ds-react
## 1.5.4
### Patch Changes
- Updated dependencies [[`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11)]:
- @navikt/ds-icons@1.5.4
## 1.5.3
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.5.3
## 1.5.2
### Patch Changes
- :memo: Rename FilterChips to ToggleChips
- Updated dependencies []:
- @navikt/ds-icons@1.5.2
## 1.5.1
### Patch Changes
- Flex-wrap chips.css
- Updated dependencies []:
- @navikt/ds-icons@1.5.1
## 1.5.0
### Minor Changes
- [#1684](https://github.com/navikt/Designsystemet/pull/1684) [`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Oppdaterte tag-varianter
- [#1668](https://github.com/navikt/Designsystemet/pull/1668) [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Chips komponent :sparkles:
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.5.0
## 1.4.4
### Patch Changes
- Eksponerer validation-typer
- Updated dependencies []:
- @navikt/ds-icons@1.4.4
## 1.4.3
### Patch Changes
- :sparkles: Validering og inputFormat i Date-komponenter
- Updated dependencies []:
- @navikt/ds-icons@1.4.3
## 1.4.2
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "1.4.2",
"version": "1.5.4",
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -33,11 +33,11 @@
"clean": "rimraf cjs esm",
"build": "concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"watch": "tsc --watch -p tsconfig.esm.json",
"test": "jest"
"test": "TZ=UTC jest"
},
"dependencies": {
"@floating-ui/react-dom-interactions": "0.9.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-icons": "^1.5.4",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
+45
View File
@@ -0,0 +1,45 @@
import cl from "clsx";
import React, { forwardRef, HTMLAttributes } from "react";
import ToggleChips, { ToggleChipsType } from "./Toggle";
import RemovableChips, { RemovableChipsType } from "./Removable";
export interface ChipsProps extends HTMLAttributes<HTMLUListElement> {
children: React.ReactNode;
/**
* Changes padding and font-sizes
* @default "medium"
*/
size?: "medium" | "small";
}
interface ChipsComponent
extends React.ForwardRefExoticComponent<
ChipsProps & React.RefAttributes<HTMLUListElement>
> {
Toggle: ToggleChipsType;
Removable: RemovableChipsType;
}
export const Chips: ChipsComponent = forwardRef<HTMLUListElement, ChipsProps>(
({ className, size = "medium", children, ...rest }, ref) => {
return (
<ul
{...rest}
ref={ref}
className={cl("navds-chips", className, `navds-chips--${size}`, {
"navds-body-short navds-body-short--small": size === "medium",
"navds-detail navds-detail--small": size === "small",
})}
>
{React.Children.map(children, (chip, index) => {
return <li key={index + (chip?.toString() ?? "")}>{chip}</li>;
})}
</ul>
);
}
) as ChipsComponent;
Chips.Toggle = ToggleChips;
Chips.Removable = RemovableChips;
export default Chips;
@@ -0,0 +1,68 @@
import { Close } from "@navikt/ds-icons";
import cl from "clsx";
import React, { forwardRef } from "react";
import { OverridableComponent } from "..";
export interface RemovableChipsProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: string;
/**
* Chip-variants
* @default "action"
*/
variant?: "action" | "neutral";
/**
* Replaces label read for screen-readers
* @default "slett filter"
*/
removeLabel?: string;
/**
* Click callback
*/
onDelete?: () => void;
}
export interface RemovableChipsType
extends OverridableComponent<RemovableChipsProps, HTMLButtonElement> {}
export const RemovableChips: OverridableComponent<
RemovableChipsProps,
HTMLButtonElement
> = forwardRef(
(
{
className,
children,
variant = "action",
as: Component = "button",
removeLabel = "slett",
onDelete,
...rest
},
ref
) => {
return (
<Component
{...rest}
ref={ref}
className={cl(
"navds-chips__chip navds-chips__removable navds-chips--icon-right",
className,
`navds-chips__removable--${variant}`
)}
aria-label={`${children} ${removeLabel}`}
onClick={(e) => {
onDelete?.();
rest?.onClick?.(e);
}}
>
<span className="navds-chips__chip-text">{children}</span>
<span className="navds-chips__removable-icon">
<Close aria-hidden />
</span>
</Component>
);
}
) as RemovableChipsType;
export default RemovableChips;
+41
View File
@@ -0,0 +1,41 @@
import { SuccessStroke } from "@navikt/ds-icons";
import cl from "clsx";
import React, { forwardRef } from "react";
import { OverridableComponent } from "..";
export interface ToggleChipsProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: string;
/**
* Toggles aria-pressed and visual-changes
*/
selected?: boolean;
}
export interface ToggleChipsType
extends OverridableComponent<ToggleChipsProps, HTMLButtonElement> {}
export const ToggleChips: ToggleChipsType = forwardRef(
(
{ className, children, selected, as: Component = "button", ...rest },
ref
) => {
return (
<Component
{...rest}
ref={ref}
className={cl("navds-chips__chip navds-chips__toggle", className, {
"navds-chips--icon-left": selected,
})}
aria-pressed={selected}
>
{selected && (
<SuccessStroke aria-hidden className="navds-chips__toggle-icon" />
)}
<span className="navds-chips__chip-text">{children}</span>
</Component>
);
}
);
export default ToggleChips;
@@ -0,0 +1,165 @@
import React, { useState } from "react";
import { Chips } from ".";
export default {
title: "ds-react/Chips",
component: Chips,
argTypes: {
type: {
control: {
type: "radio",
options: ["toggle", "removable"],
},
},
size: {
control: {
type: "radio",
options: ["medium", "small"],
},
},
},
};
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
export const Default = (props) => {
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
const [filter, setFilter] = useState(options);
if (props.type === "toggle") {
return (
<Chips size={props.size ?? "medium"}>
{options.map((c) => (
<Chips.Toggle
selected={selected.includes(c)}
key={c}
onClick={() =>
setSelected(
selected.includes(c)
? selected.filter((x) => x !== c)
: [...selected, c]
)
}
>
{c}
</Chips.Toggle>
))}
</Chips>
);
}
return (
<Chips size={props.size ?? "medium"}>
{filter.map((c) => (
<Chips.Removable
key={c}
onClick={() => setFilter((x) => x.filter((y) => y !== c))}
>
{c}
</Chips.Removable>
))}
</Chips>
);
};
export const Toggle = () => {
const [selected, setSelected] = useState<number[]>([]);
return (
<Chips>
{options.map((c, y) => (
<Chips.Toggle
selected={selected.includes(y)}
onClick={() =>
setSelected(
selected.includes(y)
? selected.filter((x) => x !== y)
: [...selected, y]
)
}
key={y}
>
{c}
</Chips.Toggle>
))}
</Chips>
);
};
export const Removable = () => {
return (
<div className="colgap">
<Chips>
{options.map((c, y) => (
<Chips.Removable key={y}>{c}</Chips.Removable>
))}
</Chips>
<Chips>
{options.map((c, y) => (
<Chips.Removable variant="neutral" key={y}>
{c}
</Chips.Removable>
))}
</Chips>
</div>
);
};
export const Regular = () => {
const [selected, setSelected] = useState<number[]>([]);
return (
<div className="colgap">
<Chips>
{options.map((c, y) => (
<Chips.Removable key={y}>{c}</Chips.Removable>
))}
</Chips>
<Chips>
{options.map((c, y) => (
<Chips.Toggle
selected={selected.includes(y)}
onClick={() =>
setSelected(
selected.includes(y)
? selected.filter((x) => x !== y)
: [...selected, y]
)
}
key={y}
>
{c}
</Chips.Toggle>
))}
</Chips>
</div>
);
};
export const Small = () => {
const [selected, setSelected] = useState<number[]>([]);
return (
<div className="colgap">
<Chips size="small">
{options.map((c, y) => (
<Chips.Removable key={y}>{c}</Chips.Removable>
))}
</Chips>
<Chips size="small">
{options.map((c, y) => (
<Chips.Toggle
selected={selected.includes(y)}
onClick={() =>
setSelected(
selected.includes(y)
? selected.filter((x) => x !== y)
: [...selected, y]
)
}
key={y}
>
{c}
</Chips.Toggle>
))}
</Chips>
</div>
);
};
+1
View File
@@ -0,0 +1 @@
export { default as Chips, ChipsProps } from "./Chips";
@@ -1,4 +1,3 @@
import isSaturday from "date-fns/isSaturday";
import React, { useId, useState } from "react";
import { UNSAFE_useDatepicker, UNSAFE_useRangeDatepicker } from "..";
import { Button } from "../..";
@@ -221,8 +220,13 @@ export const UserControlled = () => {
};
export const Validering = () => {
const { datepickerProps, selectedDay, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 23 2019"),
const [error, setError] = useState(false);
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 2 2019"),
onValidate: (val) => setError(val.isWeekend),
defaultSelected: new Date("Nov 26 2022"),
disableWeekends: true,
onDateChange: console.log,
});
return (
@@ -230,8 +234,8 @@ export const Validering = () => {
<DatePicker {...datepickerProps}>
<DatePicker.Input
error={
selectedDay && isSaturday(selectedDay)
? "NAV-kontoret er ikke åpent på lørdager. Velg en annen dag."
error
? "NAV-kontoret er ikke åpent i helger. Velg en annen dag."
: undefined
}
{...inputProps}
@@ -261,3 +265,24 @@ export const ErrorInput = () => {
</div>
);
};
export const UseRangedDatepickerValidation = () => {
const { datepickerProps, fromInputProps, toInputProps } =
UNSAFE_useRangeDatepicker({
fromDate: new Date("Aug 23 2019"),
disableWeekends: true,
disabled: [new Date("Oct 10 2022")],
onValidate: console.table,
});
return (
<div style={{ display: "flex", gap: "1rem" }}>
<DatePicker {...datepickerProps}>
<div style={{ display: "flex", gap: "1rem" }}>
<DatePicker.Input {...fromInputProps} label="Fra" />
<DatePicker.Input {...toInputProps} label="Til" />
</div>
</DatePicker>
</div>
);
};
@@ -1,6 +1,9 @@
export { useDatepicker as UNSAFE_useDatepicker } from "./useDatepicker";
export type { DateValidationT } from "./useDatepicker";
export { useRangeDatepicker as UNSAFE_useRangeDatepicker } from "./useRangeDatepicker";
export type { RangeValidationT } from "./useRangeDatepicker";
export { useMonthpicker as UNSAFE_useMonthpicker } from "./useMonthPicker";
export type { MonthValidationT } from "./useMonthPicker";
export { useDateInputContext, DateContext } from "./useDateInputContext";
export {
useSharedMonthContext,
@@ -36,6 +36,15 @@ export interface UseDatepickerOptions
* Callback for changed state
*/
onDateChange?: (val?: Date) => void;
/**
* Input-format
* @default "dd.MM.yyyy"
*/
inputFormat?: string;
/**
* validation-callback
*/
onValidate?: (val: DateValidationT) => void;
}
interface UseDatepickerValue {
@@ -62,6 +71,27 @@ interface UseDatepickerValue {
setSelected: (date?: Date) => void;
}
export type DateValidationT = {
isDisabled: boolean;
isWeekend: boolean;
isEmpty: boolean;
isInvalid: boolean;
isValidDate: boolean;
isBefore: boolean;
isAfter: boolean;
};
const getValidationMessage = (val = {}): DateValidationT => ({
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidDate: true,
...val,
});
export const useDatepicker = (
opt: UseDatepickerOptions = {}
): UseDatepickerValue => {
@@ -75,6 +105,8 @@ export const useDatepicker = (
disabled,
disableWeekends,
onDateChange,
inputFormat,
onValidate,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -90,7 +122,7 @@ export const useDatepicker = (
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "date")
? formatDateForInput(defaultSelected, locale, "date", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -99,6 +131,11 @@ export const useDatepicker = (
setSelectedDay(date);
};
const updateValidation = (val: Partial<DateValidationT> = {}) => {
const msg = getValidationMessage(val);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -134,7 +171,9 @@ export const useDatepicker = (
const setSelected = (date: Date | undefined) => {
updateDate(date);
setMonth(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "date") : "");
setInputValue(
date ? formatDateForInput(date, locale, "date", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
@@ -143,13 +182,14 @@ export const useDatepicker = (
let day = parseDate(e.target.value, today, locale, "date");
if (isValidDate(day)) {
setMonth(day);
setInputValue(formatDateForInput(day, locale, "date"));
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "date");
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "date"));
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
};
/* Only allow de-selecting if not required */
@@ -162,11 +202,15 @@ export const useDatepicker = (
if (!required && selected) {
updateDate(undefined);
setInputValue("");
updateValidation({ isValidDate: false, isEmpty: true });
return;
}
updateDate(day);
updateValidation();
setMonth(day);
setInputValue(day ? formatDateForInput(day, locale, "date") : "");
setInputValue(
day ? formatDateForInput(day, locale, "date", inputFormat) : ""
);
};
// When changing the input field, save its value in state and check if the
@@ -176,22 +220,39 @@ export const useDatepicker = (
setInputValue(e.target.value);
const day = parseDate(e.target.value, today, locale, "date");
const isBefore =
fromDate && day && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && day && differenceInCalendarDays(day, toDate) > 0;
if (
!isValidDate(day) ||
(disabled &&
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
(disableWeekends && isWeekend(day)) ||
(disabled && isMatch(day, disabled))
) {
updateDate(undefined);
updateValidation({
isInvalid: isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isValidDate: false,
isEmpty: !e.target.value,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
if (isBefore || isAfter) {
updateDate(undefined);
updateValidation({
isValidDate: false,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
updateDate(day);
updateValidation();
setMonth(day);
};
@@ -217,13 +278,15 @@ export const useDatepicker = (
month,
onMonthChange: (month) => setMonth(month),
onDayClick: handleDayClick,
selected: selectedDay,
selected: selectedDay ?? new Date("Invalid date"),
locale: _locale,
fromDate,
toDate,
today,
open,
onOpenToggle: () => setOpen((x) => !x),
disabled,
disableWeekends,
ref: daypickerRef,
};
@@ -22,6 +22,15 @@ export interface UseMonthPickerOptions
* Callback for month-change
*/
onMonthChange?: (date?: Date) => void;
/**
* Input-format
* @default "MMMM yyyy"
*/
inputFormat?: string;
/**
* validation-callback
*/
onValidate?: (val: MonthValidationT) => void;
}
interface UseMonthPickerValue {
@@ -48,6 +57,25 @@ interface UseMonthPickerValue {
reset: () => void;
}
export type MonthValidationT = {
isDisabled: boolean;
isEmpty: boolean;
isInvalid: boolean;
isValidMonth: boolean;
isBefore: boolean;
isAfter: boolean;
};
const getValidationMessage = (val = {}): MonthValidationT => ({
isDisabled: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidMonth: true,
...val,
});
export const useMonthpicker = (
opt: UseMonthPickerOptions = {}
): UseMonthPickerValue => {
@@ -59,6 +87,8 @@ export const useMonthpicker = (
disabled,
required,
onMonthChange,
inputFormat,
onValidate,
} = opt;
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
@@ -75,7 +105,7 @@ export const useMonthpicker = (
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "month")
? formatDateForInput(defaultSelected, locale, "month", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -85,6 +115,11 @@ export const useMonthpicker = (
setSelectedMonth(date);
};
const updateValidation = (val: Partial<MonthValidationT> = {}) => {
const msg = getValidationMessage(val);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -120,7 +155,9 @@ export const useMonthpicker = (
const setSelected = (date: Date | undefined) => {
updateMonth(date);
setYear(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "month") : "");
setInputValue(
date ? formatDateForInput(date, locale, "month", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
@@ -128,13 +165,14 @@ export const useMonthpicker = (
let day = parseDate(e.target.value, today, locale, "month");
if (isValidDate(day)) {
setYear(day);
setInputValue(formatDateForInput(day, locale, "month"));
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
}
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "month");
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "month"));
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
};
/* Only allow de-selecting if not required */
@@ -146,11 +184,15 @@ export const useMonthpicker = (
if (!required && !month) {
updateMonth(undefined);
updateValidation({ isValidMonth: false, isEmpty: true });
setInputValue("");
return;
}
updateMonth(month);
setInputValue(month ? formatDateForInput(month, locale, "month") : "");
updateValidation();
setInputValue(
month ? formatDateForInput(month, locale, "month", inputFormat) : ""
);
};
// When changing the input field, save its value in state and check if the
@@ -160,32 +202,48 @@ export const useMonthpicker = (
setInputValue(e.target.value);
const month = parseDate(e.target.value, today, locale, "month");
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
updateMonth(undefined);
return;
}
const isBefore =
fromDate &&
month &&
(fromDate.getFullYear() > month.getFullYear() ||
(fromDate.getFullYear() === month.getFullYear() &&
fromDate.getMonth() > month.getMonth()));
const isAfter =
toDate &&
month &&
(toDate.getFullYear() < month.getFullYear() ||
(toDate.getFullYear() === month.getFullYear() &&
toDate.getMonth() < month.getMonth()));
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
updateMonth(undefined);
updateValidation({
isInvalid: isValidDate(month),
isDisabled: disabled && isMatch(month, disabled),
isValidMonth: false,
isEmpty: !e.target.value,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
if (
isAfter ||
isBefore ||
(fromDate && toDate && !isMatch(month, [{ from: fromDate, to: toDate }]))
) {
updateMonth(undefined);
updateValidation({
isValidMonth: false,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
updateMonth(month);
updateValidation();
setYear(month);
};
@@ -0,0 +1,59 @@
/* eslint-disable react/jsx-pascal-case */
import { act, render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import { UNSAFE_DatePicker, UNSAFE_useRangeDatepicker } from "..";
const RangeDemo = () => {
const { datepickerProps, fromInputProps, selectedRange, toInputProps } =
UNSAFE_useRangeDatepicker({
fromDate: new Date("Aug 23 2019"),
});
return (
<div style={{ display: "flex", gap: "1rem" }}>
<UNSAFE_DatePicker {...datepickerProps}>
<UNSAFE_DatePicker.Input {...fromInputProps} label="Fra" />
<UNSAFE_DatePicker.Input {...toInputProps} label="Til" />
</UNSAFE_DatePicker>
<div title="res">{JSON.stringify(selectedRange)}</div>
</div>
);
};
describe("Writing in input sets correct values", () => {
it("useRangeDatepicker same date", async () => {
const utils = render(<RangeDemo />);
const fraInput = utils.getByRole("textbox", { name: "Fra" });
const tilInput = utils.getByRole("textbox", { name: "Til" });
await act(async () => {
await userEvent.type(fraInput, "03.08.2022");
await userEvent.type(tilInput, "03.08.2022");
});
const res = utils.getByTitle("res");
expect(res.innerHTML).toEqual(
JSON.stringify({
from: "2022-08-03T00:00:00.000Z",
to: "2022-08-03T00:00:00.000Z",
})
);
});
it("useRangeDatepicker before after to ", async () => {
const utils = render(<RangeDemo />);
const fraInput = utils.getByRole("textbox", { name: "Fra" });
const tilInput = utils.getByRole("textbox", { name: "Til" });
await act(async () => {
await userEvent.type(fraInput, "03.08.2022");
await userEvent.type(tilInput, "02.08.2022");
});
const res = utils.getByTitle("res");
expect(res.innerHTML).toEqual(
JSON.stringify({
from: "2022-08-03T00:00:00.000Z",
})
);
});
});
@@ -10,10 +10,42 @@ import {
isValidDate,
parseDate,
} from "../utils";
import { UseDatepickerOptions } from "./useDatepicker";
import { DateValidationT, UseDatepickerOptions } from "./useDatepicker";
export type RangeValidationT = {
from: DateValidationT;
to: DateValidationT & { isBeforeFrom?: boolean };
};
const getValidationMessage = (from = {}, to = {}): RangeValidationT => ({
from: {
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidDate: true,
...from,
},
to: {
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isBeforeFrom: false,
isValidDate: true,
...to,
},
});
interface UseRangeDatepickerOptions
extends Omit<UseDatepickerOptions, "defaultSelected" | "onDateChange"> {
extends Omit<
UseDatepickerOptions,
"defaultSelected" | "onDateChange" | "onValidate"
> {
/**
* The initially selected DateRange
*/
@@ -22,6 +54,10 @@ interface UseRangeDatepickerOptions
* Callback for changed state
*/
onRangeChange?: (val?: DateRange) => void;
/**
* validation-callback
*/
onValidate?: (val: RangeValidationT) => void;
}
interface UseRangeDatepickerValue {
@@ -65,6 +101,92 @@ const RANGE = {
type RangeT = typeof RANGE[keyof typeof RANGE];
const fromValidation = (day: Date, opt?: UseRangeDatepickerOptions) => {
const isBefore =
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
const isAfter =
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
if (
isValidDate(day) &&
!(opt?.disableWeekends && isWeekend(day)) &&
!(opt?.disabled && isMatch(day, opt.disabled))
) {
return {
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: opt?.disableWeekends && isWeekend(day),
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
isBefore: isBefore,
isAfter: isAfter,
};
}
if (isBefore || isAfter) {
return {
isValidDate: false,
isBefore: isBefore,
isAfter: isAfter,
};
}
};
const toValidation = (
day: Date,
from: Date,
opt?: UseRangeDatepickerOptions
) => {
const isBefore =
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
const isAfter =
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
const isBeforeFrom =
(from && differenceInCalendarDays(from, day) > 0) ?? false;
if (
isValidDate(day) &&
!(opt?.disableWeekends && isWeekend(day)) &&
!(opt?.disabled && isMatch(day, opt.disabled))
) {
return {
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: opt?.disableWeekends && isWeekend(day),
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
isBefore,
isAfter,
isBeforeFrom,
};
}
if (isBefore || isAfter || isBeforeFrom) {
return {
isValidDate: false,
isBefore,
isAfter,
isBeforeFrom,
};
}
};
const initialValidation = (
range?: DateRange,
opt?: UseRangeDatepickerOptions
): RangeValidationT => {
if (!range || !range?.from) {
return getValidationMessage(
{ isEmpty: true, isValidDate: false },
{ isEmpty: true, isValidDate: false }
);
}
const fromVal = fromValidation(range.from, opt);
const toVal = range.to
? toValidation(range.to, range.from, opt)
: { isEmpty: true, isValidDate: false };
return getValidationMessage({ ...fromVal }, { ...toVal });
};
export const useRangeDatepicker = (
opt: UseRangeDatepickerOptions = {}
): UseRangeDatepickerValue => {
@@ -77,6 +199,8 @@ export const useRangeDatepicker = (
disabled,
disableWeekends,
onRangeChange,
inputFormat,
onValidate,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -97,15 +221,20 @@ export const useRangeDatepicker = (
const [fromInputValue, setFromInputValue] = useState(
defaultSelected?.from
? formatDateForInput(defaultSelected.from, locale, "date")
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
: ""
);
const [toInputValue, setToInputValue] = useState(
defaultSelected?.to
? formatDateForInput(defaultSelected.to, locale, "date")
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
: ""
);
const [validation, setValidation] = useState<RangeValidationT>(
initialValidation(selectedRange, opt)
);
const [open, setOpen] = useState(false);
const updateRange = (range?: DateRange) => {
@@ -113,6 +242,15 @@ export const useRangeDatepicker = (
setSelectedRange(range);
};
const updateValidation = (
from: Partial<RangeValidationT["from"]> = {},
to: Partial<RangeValidationT["to"]> = {}
) => {
const msg = getValidationMessage(from, to);
setValidation(msg);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -143,14 +281,20 @@ export const useRangeDatepicker = (
const reset = () => {
updateRange(defaultSelected ?? { from: undefined, to: undefined });
setMonth(defaultSelected ? defaultSelected?.from : today);
setValidation(
initialValidation(
defaultSelected ?? { from: undefined, to: undefined },
opt
)
);
setFromInputValue(
defaultSelected?.from
? formatDateForInput(defaultSelected.from, locale, "date")
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
: ""
);
setToInputValue(
defaultSelected?.to
? formatDateForInput(defaultSelected.to, locale, "date")
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
: ""
);
setDefaultSelected(_defaultSelected);
@@ -159,11 +303,16 @@ export const useRangeDatepicker = (
const setSelected = (range?: DateRange) => {
updateRange(range);
setFromInputValue(
range?.from ? formatDateForInput(range.from, locale, "date") : ""
range?.from
? formatDateForInput(range.from, locale, "date", inputFormat)
: ""
);
setToInputValue(
range?.to ? formatDateForInput(range?.to, locale, "date") : ""
range?.to
? formatDateForInput(range?.to, locale, "date", inputFormat)
: ""
);
setValidation(initialValidation(range, opt));
};
const handleFocus = (e, src: RangeT) => {
@@ -172,52 +321,10 @@ export const useRangeDatepicker = (
if (isValidDate(day)) {
setMonth(day);
src === RANGE.FROM
? setFromInputValue(formatDateForInput(day, locale, "date"))
: setToInputValue(formatDateForInput(day, locale, "date"));
}
};
const handleInputs = (day: Date, src: RangeT) => {
if (src === RANGE.FROM) {
const isAfter =
toInputValue &&
differenceInCalendarDays(
day,
parseDate(toInputValue, today, locale, "date")
) > 0;
if (isAfter) {
setFromInputValue(
formatDateForInput(
parseDate(toInputValue, today, locale, "date"),
locale,
"date"
? setFromInputValue(
formatDateForInput(day, locale, "date", inputFormat)
)
);
setToInputValue(formatDateForInput(day, locale, "date"));
} else {
setFromInputValue(formatDateForInput(day, locale, "date"));
}
} else if (src === RANGE.TO) {
const isBefore =
fromInputValue &&
differenceInCalendarDays(
parseDate(fromInputValue, today, locale, "date"),
day
) > 0;
if (isBefore) {
setToInputValue(
formatDateForInput(
parseDate(fromInputValue, today, locale, "date"),
locale,
"date"
)
);
setFromInputValue(formatDateForInput(day, locale, "date"));
} else {
setToInputValue(formatDateForInput(day, locale, "date"));
}
: setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
@@ -227,7 +334,19 @@ export const useRangeDatepicker = (
return;
}
handleInputs(day, src);
if (src === RANGE.FROM) {
setFromInputValue(formatDateForInput(day, locale, "date", inputFormat));
} else if (src === RANGE.TO) {
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
const validateDay = (day: any) => {
return (
isValidDate(day) &&
!(disableWeekends && isWeekend(day)) &&
!(disabled && isMatch(day, disabled))
);
};
const handleSelect = (range) => {
@@ -238,68 +357,140 @@ export const useRangeDatepicker = (
!selectedRange?.from && selectedRange?.to ? selectedRange?.to : range?.to;
range?.from
? setFromInputValue(formatDateForInput(range?.from, locale, "date"))
? setFromInputValue(
formatDateForInput(range?.from, locale, "date", inputFormat)
)
: setFromInputValue("");
prevToRange
? setToInputValue(formatDateForInput(prevToRange, locale, "date"))
? setToInputValue(
formatDateForInput(prevToRange, locale, "date", inputFormat)
)
: setToInputValue("");
updateValidation(
{ isValidDate: !!range?.from, isEmpty: !range?.from },
{ isValidDate: !!range?.to, isEmpty: !prevToRange }
);
updateRange({ from: range?.from, to: prevToRange });
};
/* live-update datepicker based on changes in inputfields */
const handleChange = (e, src: RangeT) => {
src === RANGE.FROM
? setFromInputValue(e.target.value)
: setToInputValue(e.target.value);
const day = parseDate(e.target.value, today, locale, "date");
if (
!isValidDate(day) ||
(disabled &&
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
) {
updateRange(
src === RANGE.FROM
? { ...selectedRange, from: undefined }
: { from: selectedRange?.from, to: undefined }
const fromChange = (
val: string = "",
day: Date,
isBefore = false,
isAfter = false
) => {
setFromInputValue(val);
if (!validateDay(day)) {
updateRange({ ...selectedRange, from: undefined });
updateValidation(
{
isEmpty: !val,
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isBefore,
isAfter,
},
validation.to
);
return;
}
if (isBefore || isAfter) {
updateRange({ ...selectedRange, from: undefined });
updateValidation(
{
isValidDate: false,
isBefore,
isAfter,
},
validation.to
);
return;
}
if (
selectedRange?.to &&
differenceInCalendarDays(day, selectedRange?.to) > 0
) {
updateRange({ to: day, from: day });
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
setMonth(day);
updateValidation();
return;
}
if (toInputValue && !selectedRange?.to) {
const toDay = parseDate(toInputValue, today, locale, "date");
if (validateDay(toDay)) {
updateRange({ from: day, to: toDay });
setMonth(day);
updateValidation();
return;
}
}
updateRange({ ...selectedRange, from: day });
updateValidation({}, validation.to);
setMonth(day);
};
const toChange = (
val: string = "",
day: Date,
isBefore = false,
isAfter = false
) => {
setToInputValue(val);
if (!validateDay(day)) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isEmpty: !val,
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isBefore,
isAfter,
});
return;
}
if (isBefore || isAfter) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isValidDate: false,
isBefore,
isAfter,
});
return;
}
/* If to-value < from-value */
if (
selectedRange?.from &&
differenceInCalendarDays(selectedRange?.from, day) > 0
) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isValidDate: false,
isBeforeFrom: true,
});
return;
}
updateRange({ from: selectedRange?.from, to: day });
updateValidation(validation.from, {});
setMonth(day);
};
/* live-update datepicker based on changes in inputfields */
const handleChange = (e, src: RangeT) => {
const day = parseDate(e.target.value, today, locale, "date");
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
if (isBefore || isAfter) {
src === RANGE.FROM
? updateRange({ ...selectedRange, from: undefined })
: updateRange({ from: selectedRange?.from, to: undefined });
return;
}
/* If to-value < from-value, switch places in state */
if (
src === RANGE.TO &&
selectedRange?.from &&
differenceInCalendarDays(selectedRange?.from, day) >= 0
) {
updateRange({ from: day, to: selectedRange?.from });
setMonth(day);
return;
}
/* If from-value > to-value , switch places in state */
if (
src === RANGE.FROM &&
selectedRange?.to &&
differenceInCalendarDays(day, selectedRange?.to) >= 0
) {
updateRange({ to: day, from: selectedRange?.to });
setMonth(day);
return;
}
src === RANGE.FROM && updateRange({ ...selectedRange, from: day });
src === RANGE.TO && updateRange({ from: selectedRange?.from, to: day });
setMonth(day);
return src === RANGE.FROM
? fromChange(e.target.value, day, isBefore, isAfter)
: toChange(e.target.value, day, isBefore, isAfter);
};
const handleClose = useCallback(() => {
@@ -336,6 +527,8 @@ export const useRangeDatepicker = (
mode: "range" as const,
open,
onOpenToggle: () => setOpen((x) => !x),
disabled,
disableWeekends,
ref: datePickerRef,
};
+3
View File
@@ -9,6 +9,9 @@ export {
UNSAFE_useDatepicker,
UNSAFE_useMonthpicker,
UNSAFE_useRangeDatepicker,
RangeValidationT,
DateValidationT,
MonthValidationT,
} from "./hooks";
export {
default as UNSAFE_MonthPicker,
@@ -90,6 +90,26 @@ export const UseMonthpicker = () => {
);
};
export const UseMonthpickerFormat = () => {
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
disabled: [new Date("Apr 1 2022")],
onMonthChange: console.log,
inputFormat: "MM.yyyy",
});
return (
<div style={{ height: "20rem" }}>
<MonthPicker {...monthpickerProps}>
<MonthPicker.Input
{...inputProps}
label="Velg måned"
variant="monthpicker"
/>
</MonthPicker>
</div>
);
};
export const Required = () => {
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
locale: "nb",
@@ -6,16 +6,16 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
describe("Format date to correct output", () => {
test("formatDateForInput", () => {
expect(formatDateForInput(parse("15/05/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("15/05/2022"), nb, "date")).toEqual(
"15.05.2022"
);
expect(formatDateForInput(parse("1/5/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("1/5/2022"), nb, "date")).toEqual(
"01.05.2022"
);
expect(formatDateForInput(parse("1/05/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("1/05/2022"), nb, "date")).toEqual(
"01.05.2022"
);
expect(formatDateForInput(parse("15/5/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("15/5/2022"), nb, "date")).toEqual(
"15.05.2022"
);
});
@@ -2,7 +2,6 @@ import { parseDate } from "..";
import { isValidDate } from "..";
import nb from "date-fns/locale/nb";
import getMonth from "date-fns/getMonth";
import getYear from "date-fns/getYear";
const check = (inp: string) =>
expect(isValidDate(parseDate(inp, new Date(), nb, "date")));
@@ -11,71 +10,32 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
describe("Parse date-inputs", () => {
test("No spaces", () => {
check("150522").toBeTruthy();
check("11052022").toBeTruthy();
check("15052022").toBeTruthy();
});
test(". divider", () => {
check("1.5.22").toBeTruthy();
check("1.5.2022").toBeTruthy();
check("11.05.22").toBeTruthy();
check("11.05.2022").toBeTruthy();
});
test("/ divider", () => {
check("1/5/22").toBeTruthy();
check("10/5/22").toBeTruthy();
check("1/5/2022").toBeTruthy();
check("10/5/2022").toBeTruthy();
check("1/05/22").toBeTruthy();
check("10/05/22").toBeTruthy();
check("1/05/2022").toBeTruthy();
check("10/05/2022").toBeTruthy();
});
test("- divider", () => {
check("1-5-22").toBeTruthy();
check("10-5-22").toBeTruthy();
check("1-5-2022").toBeTruthy();
check("10-5-2022").toBeTruthy();
check("1-05-22").toBeTruthy();
check("10-05-22").toBeTruthy();
check("1-05-2022").toBeTruthy();
check("10-05-2022").toBeTruthy();
});
});
describe("Parse date-inputs to correct year", () => {
test("No spaces", () => {
expect(getYear(parse("150522"))).toEqual(2022);
});
test(". divider", () => {
expect(getYear(parse("1.05.22"))).toEqual(2022);
expect(getYear(parse("11.05.22"))).toEqual(2022);
expect(getYear(parse("1.5.22"))).toEqual(2022);
expect(getYear(parse("11.5.22"))).toEqual(2022);
});
test("/ divider", () => {
expect(getYear(parse("1/5/22"))).toEqual(2022);
expect(getYear(parse("10/5/22"))).toEqual(2022);
expect(getYear(parse("1/05/22"))).toEqual(2022);
expect(getYear(parse("10/05/22"))).toEqual(2022);
});
test("- divider", () => {
expect(getYear(parse("1-5-22"))).toEqual(2022);
expect(getYear(parse("10-5-22"))).toEqual(2022);
expect(getYear(parse("1-05-22"))).toEqual(2022);
expect(getYear(parse("10-05-22"))).toEqual(2022);
});
});
describe("Parse date-inputs to correct month", () => {
test("No spaces", () => {
expect(getMonth(parse("150522"))).toEqual(4);
expect(getMonth(parse("11052022"))).toEqual(4);
expect(getMonth(parse("15052022"))).toEqual(4);
});
@@ -7,11 +7,13 @@ import {
export const formatDateForInput = (
date: Date,
locale: Locale,
type: "date" | "month"
type: "date" | "month",
inputFormat?: string
) => {
const INPUT_DATE_STRING_FORMAT =
type === "date"
inputFormat ??
(type === "date"
? INPUT_DATE_STRING_FORMAT_DATE
: INPUT_DATE_STRING_FORMAT_MONTH;
: INPUT_DATE_STRING_FORMAT_MONTH);
return format(date, INPUT_DATE_STRING_FORMAT, { locale });
};
@@ -6,16 +6,10 @@ export const INPUT_DATE_STRING_FORMAT_DATE = "dd.MM.yyyy";
export const INPUT_DATE_STRING_FORMAT_MONTH = "MMMM yyyy";
const ALLOWED_INPUT_FORMATS_DATE = [
"ddMMyy",
"d.M.yy",
"dd.MM.yy",
"dd/MM/yy",
"dd-MM-yy",
INPUT_DATE_STRING_FORMAT_DATE,
"ddMMyyyy",
"dd/MM/yyyy",
"dd-MM-yyyy",
"d.M.yyyy",
];
const ALLOWED_INPUT_FORMATS_MONTH = [
@@ -28,20 +22,35 @@ const ALLOWED_INPUT_FORMATS_MONTH = [
...ALLOWED_INPUT_FORMATS_DATE,
];
const isTwoDigitYear = (dateString, today, locale, formats) => {
let parsed;
const newFormat = formats.map((x) => x.replace("yyyy", "yy"));
for (const format of newFormat) {
parsed = parse(dateString, format, today, { locale });
if (isValidDate(parsed)) {
return true;
}
}
return false;
};
export const parseDate = (
date: 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)) {
if (
isValidDate(parsed) &&
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
return parsed;
}
}
return parsed;
return new Date("Invalid date");
};
+1
View File
@@ -16,6 +16,7 @@ export * from "./panel";
export * from "./popover";
export * from "./read-more";
export * from "./chat";
export * from "./chips";
export * from "./stepper";
export * from "./tag";
export * from "./toggle-group";
+20 -8
View File
@@ -3,19 +3,31 @@ import cl from "clsx";
import { BodyShort, Detail } from "..";
export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
/**
* Tag label
*/
children: React.ReactNode;
/**
* Changes background and border color
* Changes visual profile of tag
*/
variant: "warning" | "error" | "info" | "success";
variant:
| "warning"
| "warning-filled"
| "error"
| "error-filled"
| "info"
| "info-filled"
| "success"
| "success-filled"
| "neutral"
| "neutral-filled"
| "alt1"
| "alt1-filled"
| "alt2"
| "alt2-filled"
| "alt3"
| "alt3-filled";
/**
* Changes padding and font-sizes
* @default "medium"
*/
size?: "medium" | "small";
size?: "medium" | "small" | "xsmall";
}
export const Tag = forwardRef<HTMLSpanElement, TagProps>(
@@ -27,7 +39,7 @@ export const Tag = forwardRef<HTMLSpanElement, TagProps>(
{...rest}
ref={ref}
as="span"
size={size}
size={size === "medium" ? "medium" : "small"}
className={cl(
"navds-tag",
className,
+82 -5
View File
@@ -9,17 +9,70 @@ export default {
defaultValue: "info",
control: {
type: "radio",
options: ["error", "warning", "info", "success"],
options: [
"warning",
"error",
"info",
"success",
"neutral",
"alt1",
"alt2",
"alt3",
"warning-filled",
"error-filled",
"info-filled",
"success-filled",
"neutral-filled",
"alt1-filled",
"alt2-filled",
"alt3-filled",
],
},
},
size: {
defaultValue: "medium",
control: {
type: "radio",
options: ["xsmall", "small", "medium"],
},
},
},
};
const variants: Array<"error" | "warning" | "info" | "success"> = [
"error",
const variants: Array<
| "warning"
| "warning-filled"
| "error"
| "error-filled"
| "info"
| "info-filled"
| "success"
| "success-filled"
| "neutral"
| "neutral-filled"
| "alt1"
| "alt1-filled"
| "alt2"
| "alt2-filled"
| "alt3"
| "alt3-filled"
> = [
"warning",
"error",
"info",
"success",
"neutral",
"alt1",
"alt2",
"alt3",
"warning-filled",
"error-filled",
"info-filled",
"success-filled",
"neutral-filled",
"alt1-filled",
"alt2-filled",
"alt3-filled",
];
export const Default = (props) => (
@@ -34,10 +87,34 @@ Default.args = {
export const Small = () => {
return (
<div className="rowgap">
<div className="rowgap rowgap-wrap">
{variants.map((variant, i) => (
<Tag key={variant} variant={variant} size="small">
{new Array(i + 1).fill("Id elit esse")}
{variant}
</Tag>
))}
</div>
);
};
export const xSmall = () => {
return (
<div className="rowgap rowgap-wrap">
{variants.map((variant, i) => (
<Tag key={variant} variant={variant} size="xsmall">
{variant}
</Tag>
))}
</div>
);
};
export const Variants = () => {
return (
<div className="rowgap rowgap-wrap">
{variants.map((variant, i) => (
<Tag key={variant} variant={variant}>
{variant}
</Tag>
))}
</div>
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-tailwind
## 1.5.4
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
## 1.4.1
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "1.4.2",
"version": "1.5.4",
"description": "Auto-generated tailwind config based on @navikt/ds-tokens",
"author": "NAV Designsystem team",
"keywords": [
@@ -22,7 +22,7 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.4.2",
"@navikt/ds-tokens": "^1.5.4",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"jest": "^29.0.0",
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-tokens
## 1.5.4
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
## 1.4.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "1.4.2",
"version": "1.5.4",
"description": "Auto-generated design-tokens for NAV design-systems framework",
"author": "NAV Designsystem team",
"keywords": [
+18
View File
@@ -1,5 +1,23 @@
# @navikt/ds-icons
## 1.5.4
### Patch Changes
- [#1709](https://github.com/navikt/Designsystemet/pull/1709) [`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert ikoner
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
## 1.4.1
+126
View File
@@ -311,6 +311,102 @@
"created_at": "2021-04-28T14:11:08.212Z",
"pageName": "People"
},
{
"name": "ChevronDownCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.965Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.048Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownDouble",
"description": "",
"created_at": "2022-11-02T08:31:54.957Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.949Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.938Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.930Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.040Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.922Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.993Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.985Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.003Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.013Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.906Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.021Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.031Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.914Z",
"pageName": "Arrows"
},
{
"name": "Child",
"description": "",
@@ -761,6 +857,12 @@
"created_at": "2021-01-11T13:37:55.499Z",
"pageName": "Status"
},
{
"name": "ErrorStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.018Z",
"pageName": "Status"
},
{
"name": "Eu",
"description": "",
@@ -1355,6 +1457,12 @@
"created_at": "2021-01-11T13:37:55.736Z",
"pageName": "Status"
},
{
"name": "InformationStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.034Z",
"pageName": "Status"
},
{
"name": "Laptop",
"description": "",
@@ -1613,6 +1721,18 @@
"created_at": "2020-07-01T10:37:42.664Z",
"pageName": "Arrows"
},
{
"name": "NextDouble",
"description": "",
"created_at": "2022-11-02T08:31:54.896Z",
"pageName": "Arrows"
},
{
"name": "NextDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.975Z",
"pageName": "Arrows"
},
{
"name": "NextFilled",
"description": "",
@@ -2651,6 +2771,12 @@
"created_at": "2021-01-11T13:37:55.590Z",
"pageName": "Status"
},
{
"name": "WarningStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.027Z",
"pageName": "Status"
},
{
"name": "Washing",
"description": "",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "1.4.2",
"version": "1.5.4",
"description": "Aksel icons",
"repository": {
"type": "git",
+4
View File
@@ -0,0 +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="M21.25 12C21.25 6.89137 17.1086 2.75 12 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 12ZM12 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 12C1.25 6.06294 6.06294 1.25 12 1.25Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 15.5607L7.46967 11.0303L8.53033 9.96967L12 13.4393L15.4697 9.96967L16.5303 11.0303L12 15.5607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 640 B

@@ -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 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 12C1.25 6.06294 6.06294 1.25 12 1.25ZM12 15.5607L16.5303 11.0303L15.4697 9.96967L12 13.4393L8.53033 9.96967L7.46967 11.0303L12 15.5607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 420 B

+5
View File
@@ -0,0 +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="M21.25 12C21.25 6.89137 17.1086 2.75 12 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 12ZM12 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 12C1.25 6.06294 6.06294 1.25 12 1.25Z" fill="#262626"/>
<path d="M12 13.5607L16.5303 9.03033L15.4697 7.96967L12 11.4393L8.53033 7.96967L7.46967 9.03033L12 13.5607Z" fill="#262626"/>
<path d="M12 17.0607L16.5303 12.5303L15.4697 11.4697L12 14.9393L8.53033 11.4697L7.46967 12.5303L12 17.0607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

@@ -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="M22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12ZM11.9984 13.4579L6.94365 8.40316L8.27389 7.07292L11.9984 10.7974L15.7228 7.07292L17.0531 8.40316L11.9984 13.4579ZM6.94365 13.241L11.9984 18.2957L17.0531 13.241L15.7228 11.9108L11.9984 15.6352L8.27389 11.9108L6.94365 13.241Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

+4
View File
@@ -0,0 +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 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25ZM22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.43934 12L12.9697 7.46967L14.0303 8.53033L10.5607 12L14.0303 15.4697L12.9697 16.5303L8.43934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 641 B

@@ -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="M22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12ZM8.43934 12L12.9697 16.5303L14.0303 15.4697L10.5607 12L14.0303 8.53033L12.9697 7.46967L8.43934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

+5
View File
@@ -0,0 +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 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25ZM22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12Z" fill="#262626"/>
<path d="M10.4393 12L14.9697 16.5303L16.0303 15.4697L12.5607 12L16.0303 8.53033L14.9697 7.46967L10.4393 12Z" fill="#262626"/>
<path d="M6.93934 12L11.4697 16.5303L12.5303 15.4697L9.06066 12L12.5303 8.53033L11.4697 7.46967L6.93934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 727 B

@@ -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 22.75C6.06294 22.75 1.25 17.9371 1.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.75ZM10.5421 11.9984L15.5968 6.94365L16.9271 8.27389L13.2026 11.9984L16.9271 15.7228L15.5968 17.0531L10.5421 11.9984ZM10.759 6.94365L5.70428 11.9984L10.759 17.0531L12.0892 15.7228L8.36477 11.9984L12.0892 8.27389L10.759 6.94365Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

+4
View File
@@ -0,0 +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 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="M15.5607 12L11.0303 16.5303L9.96967 15.4697L13.4393 12L9.96967 8.53033L11.0303 7.46967L15.5607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 639 B

@@ -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="M1.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 12ZM15.5607 12L11.0303 7.46967L9.96967 8.53033L13.4393 12L9.96967 15.4697L11.0303 16.5303L15.5607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 420 B

+5
View File
@@ -0,0 +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 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 d="M13.5607 12L9.03033 7.46967L7.96967 8.53033L11.4393 12L7.96967 15.4697L9.03033 16.5303L13.5607 12Z" fill="#262626"/>
<path d="M17.0607 12L12.5303 7.46967L11.4697 8.53033L14.9393 12L11.4697 15.4697L12.5303 16.5303L17.0607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 725 B

@@ -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 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 12C1.25 6.06294 6.06294 1.25 12 1.25ZM13.4579 12.0016L8.40316 17.0564L7.07292 15.7261L10.7974 12.0016L7.07292 8.27718L8.40316 6.94694L13.4579 12.0016ZM13.241 17.0564L18.2957 12.0016L13.241 6.94694L11.9108 8.27718L15.6352 12.0016L11.9108 15.7261L13.241 17.0564Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 545 B

+4
View File
@@ -0,0 +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.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.75C6.89137 2.75 2.75 6.89137 2.75 12ZM12 22.75C6.06294 22.75 1.25 17.9371 1.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.75Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 8.43934L16.5303 12.9697L15.4697 14.0303L12 10.5607L8.53033 14.0303L7.46967 12.9697L12 8.43934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 640 B

@@ -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 22.75C6.06294 22.75 1.25 17.9371 1.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.75ZM12 8.43934L7.46967 12.9697L8.53033 14.0303L12 10.5607L15.4697 14.0303L16.5303 12.9697L12 8.43934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

+5
View File
@@ -0,0 +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="M2.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.75C6.89137 2.75 2.75 6.89137 2.75 12ZM12 22.75C6.06294 22.75 1.25 17.9371 1.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.75Z" fill="#262626"/>
<path d="M12 10.4393L7.46967 14.9697L8.53033 16.0303L12 12.5607L15.4697 16.0303L16.5303 14.9697L12 10.4393Z" fill="#262626"/>
<path d="M12 6.93934L7.46967 11.4697L8.53033 12.5303L12 9.06066L15.4697 12.5303L16.5303 11.4697L12 6.93934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

@@ -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="M1.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 12ZM12.0016 10.5421L17.0564 15.5968L15.7261 16.9271L12.0016 13.2026L8.27718 16.9271L6.94694 15.5968L12.0016 10.5421ZM17.0564 10.759L12.0016 5.70428L6.94694 10.759L8.27718 12.0892L12.0016 8.36477L15.7261 12.0892L17.0564 10.759Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 545 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="M17 5L19 7L13.9992 12L19 17L17 19L12 13.9992L7 19L5 17L10.0008 12L5 7L7 5L12 10.0008L17 5Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 261 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="M8.57141 20V17.7143H10.8571V12H8.57141V9.71429H13.1428V17.7143H15.4286V20H8.57141ZM12 4C12.9467 4 13.7142 4.76751 13.7142 5.71429C13.7142 6.66106 12.9467 7.42857 12 7.42857C11.0532 7.42857 10.2857 6.66106 10.2857 5.71429C10.2857 4.76751 11.0532 4 12 4Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

+4
View File
@@ -0,0 +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="M14.1213 12L6.41421 19.7071L5 18.2929L11.2929 12L5 5.70711L6.41421 4.29289L14.1213 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.62 12L11.9129 19.7071L10.4987 18.2929L16.7916 12L10.4987 5.70711L11.9129 4.29289L19.62 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 419 B

+4
View File
@@ -0,0 +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="M14.182 12L6.12132 20.0607L4 17.9393L9.93934 12L4 6.06067L6.12132 3.93935L14.182 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2426 12L13.182 20.0607L11.0607 17.9393L17 12L11.0607 6.06067L13.182 3.93935L21.2426 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 414 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="M17.0465 7.67114L18.4456 9.10034L9.71768 17.4992L6 14.0182L7.39516 12.5852L9.71359 14.7034L17.0465 7.67114Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2014 6L20 7.89047L8.77943 19L4 14.3955L5.79361 12.5L8.77418 15.3019L18.2014 6Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 253 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="M10.6667 4V13.3333H13.3333V4H10.6667ZM12 20C13.1046 20 14 19.1046 14 18C14 16.8954 13.1046 16 12 16C10.8954 16 10 16.8954 10 18C10 19.1046 10.8954 20 12 20Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 327 B

+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-css-internal
## 1.5.4
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "1.4.2",
"version": "1.5.4",
"description": "Css for NAV internal Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
+56
View File
@@ -1,5 +1,61 @@
# @navikt/ds-react-internal
## 1.5.4
### Patch Changes
- Updated dependencies [[`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11)]:
- @navikt/ds-icons@1.5.4
- @navikt/ds-react@1.5.4
## 1.5.3
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.3
- @navikt/ds-icons@1.5.3
## 1.5.2
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.2
- @navikt/ds-icons@1.5.2
## 1.5.1
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.1
- @navikt/ds-icons@1.5.1
## 1.5.0
### Patch Changes
- Updated dependencies [[`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f), [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca)]:
- @navikt/ds-react@1.5.0
- @navikt/ds-icons@1.5.0
## 1.4.4
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.4.4
- @navikt/ds-icons@1.4.4
## 1.4.3
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.4.3
- @navikt/ds-icons@1.4.3
## 1.4.2
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "1.4.2",
"version": "1.5.4",
"description": "NAV internal designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -35,8 +35,8 @@
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-icons": "^1.5.4",
"@navikt/ds-react": "^1.5.4",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
+8 -8
View File
@@ -18,14 +18,14 @@
"website"
],
"dependencies": {
"@navikt/ds-codemod": "^1.4.2",
"@navikt/ds-css": "^1.4.2",
"@navikt/ds-css-internal": "^1.4.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-react-internal": "^1.4.2",
"@navikt/ds-tailwind": "^1.4.2",
"@navikt/ds-tokens": "^1.4.2"
"@navikt/ds-codemod": "^1.5.4",
"@navikt/ds-css": "^1.5.4",
"@navikt/ds-css-internal": "^1.5.4",
"@navikt/ds-icons": "^1.5.4",
"@navikt/ds-react": "^1.5.4",
"@navikt/ds-react-internal": "^1.5.4",
"@navikt/ds-tailwind": "^1.5.4",
"@navikt/ds-tokens": "^1.5.4"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.1.13"
@@ -1,5 +1,5 @@
import { Expand } from "@navikt/ds-icons";
import { BodyShort, Detail } from "@navikt/ds-react";
import { BodyShort, Detail, Tag } from "@navikt/ds-react";
import cl from "classnames";
import NextLink from "next/link";
import React, { useContext, useMemo, useState } from "react";
@@ -59,22 +59,23 @@ const NavItem = ({
)}
>
{item.title}
{item?.link?.status &&
["deprecated", "beta"].includes(item.link.status?.tag) && (
<Detail
className={cl(
"font-regular ml-2 rounded-full border-none px-2 capitalize",
{
"text-text bg-gray-200 capitalize ring-1 ring-inset ring-gray-900/10":
item.link.status?.tag === "deprecated",
"text-text bg-purple-50 ring-1 ring-inset ring-purple-900/10":
item.link.status?.tag === "beta",
<span className="ml-2 capitalize">
{item?.link?.status &&
["deprecated", "beta", "new"].includes(item.link.status?.tag) && (
<Tag
size="xsmall"
variant={
item.link.status?.tag === "beta"
? "alt1"
: item.link.status?.tag === "deprecated"
? "neutral"
: "info"
}
)}
>
{item.link.status?.tag}
</Detail>
)}
>
{item.link.status?.tag}
</Tag>
)}
</span>
</BodyShort>
</NextLink>
</li>
@@ -1,9 +1,7 @@
import { capitalize, Snippet } from "@/components";
import { withErrorBoundary } from "@/error-boundary";
import { SanityT } from "@/lib";
import { SuccessStroke } from "@navikt/ds-icons";
import { BodyLong, Link } from "@navikt/ds-react";
import * as Tabs from "@radix-ui/react-tabs";
import { BodyLong, Link, Chips } from "@navikt/ds-react";
import cl from "classnames";
import { useEffect, useState } from "react";
import { CodeSandbox } from "./CodeSandbox";
@@ -57,8 +55,6 @@ const ComponentExamples = ({
str
.replace(/[^\w]|_/g, " ")
.replace(/\s+/g, " ")
.match(/\D/g)
.join("")
.trim()
) ?? str;
@@ -107,51 +103,46 @@ const ComponentExamples = ({
);
}
const active = activeExample ?? node?.dir?.filer?.[0]?.navn;
return (
<>
<Tabs.Root
defaultValue={node.dir.filer[0].navn}
onValueChange={(v) => setActiveExample(v)}
>
<Tabs.List className="mb-5 flex max-w-xl flex-wrap gap-2">
<div>
<div className="mb-5 max-w-xl">
<Chips>
{node.dir.filer.map((fil) => {
return (
<Tabs.Trigger
<Chips.Toggle
key={fil._key}
value={fil.navn}
className={cl(
"flex h-8 items-center justify-center rounded-full text-base ring-inset ring-gray-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-800",
{
"gap-1 bg-gray-200 pr-3 pl-[10px] ring-2 hover:bg-gray-100":
activeExample === fil.navn,
"bg-white px-3 ring-1 hover:bg-gray-100":
activeExample !== fil.navn,
}
)}
selected={active === fil.navn}
onClick={() => setActiveExample(fil.navn)}
>
{activeExample === fil.navn && (
<SuccessStroke aria-hidden className="h-6 w-6" />
)}
{fixName(fil.navn)}
</Tabs.Trigger>
</Chips.Toggle>
);
})}
</Tabs.List>
{node.dir.filer.map((fil) => {
return (
<Tabs.Content key={fil._key} value={fil.navn} tabIndex={-1}>
{fil?.description && (
<BodyLong className="mb-2">{fil.description}</BodyLong>
)}
{element(
`/eksempler/${node.dir.title}/${fil.navn.replace(".tsx", "")}`,
fil.innhold
)}
</Tabs.Content>
);
})}
</Tabs.Root>
</>
</Chips>
</div>
{node.dir.filer.map((fil) => {
return (
<div
key={fil._key}
className={cl({
visible: active === fil.navn,
hidden: active !== fil.navn,
})}
>
{fil?.description && (
<BodyLong className="mb-2">{fil.description}</BodyLong>
)}
{element(
`/eksempler/${node.dir.title}/${fil.navn.replace(".tsx", "")}`,
fil.innhold
)}
</div>
);
})}
</div>
);
};
@@ -1,101 +0,0 @@
import { test, expect } from "@playwright/test";
test("Navigate tema and prinsipp", async ({ page }) => {
await page.goto("http://localhost:3000/tema/innholdsarbeid");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Brukerinnsikt 16 Artikler" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema/brukerinnsikt");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page
.getByRole("link", { name: "Universell utforming 26 Artikler" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/tema/universell-utforming"
);
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Interne flater 3 Artikler" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema/interne-flater");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Aksel" }).click();
await expect(page).toHaveURL("http://localhost:3000/");
await page.getByRole("link", { name: "Utforsk alle prinsippene" }).click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("link", { name: "1. Jeg får tillit og muligheter" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-far-tillit-og-muligheter"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", {
name: "2. Jeg blir møtt på min situasjon og mine behov",
})
.getByRole("link", {
name: "2. Jeg blir møtt på min situasjon og mine behov",
})
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-blir-mott-pa-min-situasjon-og-behov"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", { name: "3. NAV er min støttespiller" })
.getByRole("link", { name: "3. NAV er min støttespiller" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/nav-er-min-stottespiller"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", { name: "4. Jeg blir inkludert" })
.getByRole("link", { name: "4. Jeg blir inkludert" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-blir-inkludert"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
});
-65
View File
@@ -1,65 +0,0 @@
import { test, expect } from "@playwright/test";
test("Test sandbox-examples", async ({ page }) => {
await page.goto("http://localhost:3000/designsystem/komponenter/checkbox");
await page.frameLocator("#Kode-eksempler").getByLabel("Bakerst").check();
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
await page.frameLocator("#Kode-eksempler").getByLabel("Fremst").check();
await page.getByRole("tab", { name: "Small" }).click();
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
await page.getByRole("tab", { name: "Description" }).click();
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
await page.getByRole("tab", { name: "Indeterminate" }).click();
await page.frameLocator("#Kode-eksempler").getByLabel("Fremst").check();
await page.frameLocator("#Kode-eksempler").getByLabel("Bakerst").check();
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
await page.getByRole("link", { name: "Button" }).click();
await expect(page).toHaveURL(
"http://localhost:3000/designsystem/komponenter/button"
);
await page
.frameLocator("#Kode-eksempler")
.getByRole("button", { name: "Primary" })
.click();
await page.getByRole("tab", { name: "Icon" }).click();
await page
.frameLocator("#Kode-eksempler")
.getByRole("button", { name: "Rediger" })
.click();
await page.getByRole("link", { name: "Search" }).click();
await expect(page).toHaveURL(
"http://localhost:3000/designsystem/komponenter/search"
);
await page
.frameLocator("#Kode-eksempler")
.getByLabel("Søk alle NAV sine sider")
.click();
await page
.frameLocator("#Kode-eksempler")
.getByLabel("Søk alle NAV sine sider")
.fill("test");
await page
.frameLocator("#Kode-eksempler")
.getByRole("button", { name: "Søk" })
.click();
});
@@ -0,0 +1,52 @@
import { Chips } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
import { useState } from "react";
const Example = () => {
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
const [filter, setFilter] = useState(options);
return (
<div className="grid gap-4">
<Chips>
{options.map((c) => (
<Chips.Toggle
selected={selected.includes(c)}
key={c}
onClick={() =>
setSelected(
selected.includes(c)
? selected.filter((x) => x !== c)
: [...selected, c]
)
}
>
{c}
</Chips.Toggle>
))}
</Chips>
<Chips>
{filter.map((c) => (
<Chips.Removable
key={c}
onClick={() =>
setFilter((x) =>
x.length === 1 ? options : x.filter((y) => y !== c)
)
}
>
{c}
</Chips.Removable>
))}
</Chips>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 0,
};
@@ -0,0 +1,32 @@
import { Chips } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
import { useState } from "react";
const Example = () => {
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
const [filter, setFilter] = useState(options);
return (
<Chips>
{filter.map((c) => (
<Chips.Removable
key={c}
onClick={() =>
setFilter((x) =>
x.length === 1 ? options : x.filter((y) => y !== c)
)
}
>
{c}
</Chips.Removable>
))}
</Chips>
);
};
export default withDsExample(Example);
export const args = {
index: 2,
};
@@ -0,0 +1,52 @@
import { Chips } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
import { useState } from "react";
const Example = () => {
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
const [filter, setFilter] = useState(options);
return (
<div className="grid gap-4">
<Chips size="small">
{options.map((c) => (
<Chips.Toggle
selected={selected.includes(c)}
key={c}
onClick={() =>
setSelected(
selected.includes(c)
? selected.filter((x) => x !== c)
: [...selected, c]
)
}
>
{c}
</Chips.Toggle>
))}
</Chips>
<Chips size="small">
{filter.map((c) => (
<Chips.Removable
key={c}
onClick={() =>
setFilter((x) =>
x.length === 1 ? options : x.filter((y) => y !== c)
)
}
>
{c}
</Chips.Removable>
))}
</Chips>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 3,
};
@@ -0,0 +1,35 @@
import { Chips } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
import { useState } from "react";
const Example = () => {
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
return (
<Chips>
{options.map((c) => (
<Chips.Toggle
selected={selected.includes(c)}
key={c}
onClick={() =>
setSelected(
selected.includes(c)
? selected.filter((x) => x !== c)
: [...selected, c]
)
}
>
{c}
</Chips.Toggle>
))}
</Chips>
);
};
export default withDsExample(Example);
export const args = {
index: 1,
};
@@ -3,10 +3,13 @@ import { withDsExample } from "components/website-modules/examples/withDsExample
import { useState } from "react";
const Example = () => {
const [day, setDay] = useState<Date | undefined>();
const [hasError, setHasError] = useState(false);
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 23 2019"),
onDateChange: setDay,
onValidate: (val) => {
setHasError(!val.isValidDate);
console.log(val);
},
});
return (
@@ -15,7 +18,7 @@ const Example = () => {
<UNSAFE_DatePicker.Input
{...inputProps}
label="Velg dato"
error={!day && "Må velge en dag"}
error={hasError && "Noe er feil"}
/>
</UNSAFE_DatePicker>
</div>
@@ -26,5 +29,5 @@ export default withDsExample(Example);
export const args = {
index: 9,
desc: "Vi anbefaler å bruke UNSAFE_useDatepicker-hook hvis man har et input-felt",
desc: "Bruk onValidate-callback for å håndtere validering.",
};
@@ -3,12 +3,14 @@ import { withDsExample } from "components/website-modules/examples/withDsExample
import { useState } from "react";
const Example = () => {
const [month, setMonth] = useState<Date | undefined>();
const [hasError, setHasError] = useState(false);
const { monthpickerProps, inputProps } = UNSAFE_useMonthpicker({
fromDate: new Date("Aug 23 2019"),
toDate: new Date("Aug 23 2025"),
onMonthChange: setMonth,
onValidate: (val) => {
setHasError(!val.isValidMonth);
console.log(val);
},
});
return (
@@ -18,7 +20,7 @@ const Example = () => {
<UNSAFE_MonthPicker.Input
{...inputProps}
label="Velg månede"
error={!month && "Du må velge månede"}
error={hasError && "Du må velge månede"}
/>
</div>
</UNSAFE_MonthPicker>
@@ -30,5 +32,5 @@ export default withDsExample(Example);
export const args = {
index: 5,
desc: "Vi anbefaler å bruke UNSAFE_useMonthpicker-hook hvis man har et input-felt",
desc: "Bruk onValidate-callback for å håndtere validering.",
};
@@ -0,0 +1,18 @@
import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex gap-2">
<Tag variant="alt1">Alt1</Tag>
<Tag variant="alt1-filled">Alt1</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 5,
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
};
@@ -0,0 +1,18 @@
import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex gap-2">
<Tag variant="alt2">Alt2</Tag>
<Tag variant="alt2-filled">Alt2</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 6,
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
};
@@ -0,0 +1,18 @@
import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex gap-2">
<Tag variant="alt3">Alt3</Tag>
<Tag variant="alt3-filled">Alt3</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 7,
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
};
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <Tag variant="error">Error</Tag>;
return (
<div className="flex gap-2">
<Tag variant="error">Error</Tag>
<Tag variant="error-filled">Error</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 3,
index: 4,
desc: "Beskriver noe som er farlig, tjenestebrudd, irreversibelt, etc.",
};
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <Tag variant="info">Info</Tag>;
return (
<div className="flex gap-2">
<Tag variant="info">Info</Tag>
<Tag variant="info-filled">Info</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 0,
index: 1,
desc: "Beskriver noe som er til opplysning, nyhet, etc.",
};
@@ -0,0 +1,18 @@
import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex gap-2">
<Tag variant="neutral">Neutral</Tag>
<Tag variant="neutral-filled">Neutral</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 0,
desc: "Beskriver noe nøytralt",
};
@@ -12,5 +12,5 @@ const Example = () => {
export default withDsExample(Example);
export const args = {
index: 4,
index: 20,
};
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <Tag variant="success">Success</Tag>;
return (
<div className="flex gap-2">
<Tag variant="success">Success</Tag>
<Tag variant="success-filled">Success</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 1,
index: 2,
desc: "Beskriver noe som er positivt, gjennomført, vellykket, etc.",
};
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <Tag variant="warning">Warning</Tag>;
return (
<div className="flex gap-2">
<Tag variant="warning">Warning</Tag>
<Tag variant="warning-filled">Warning</Tag>
</div>
);
};
export default withDsExample(Example);
export const args = {
index: 2,
index: 3,
desc: "Beskriver noe som er en advarsel, usikkert, noe som må utbedres, etc.",
};
@@ -0,0 +1,16 @@
import { Tag } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<Tag variant="info" size="xsmall">
Info
</Tag>
);
};
export default withDsExample(Example);
export const args = {
index: 21,
};
+5 -5
View File
@@ -9,16 +9,16 @@
"lint": "next lint"
},
"dependencies": {
"@navikt/ds-css": "^1.4.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-react-internal": "^1.4.2",
"@navikt/ds-css": "^1.5.4",
"@navikt/ds-icons": "^1.5.4",
"@navikt/ds-react": "^1.5.4",
"@navikt/ds-react-internal": "^1.5.4",
"next": "^12.2.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@navikt/ds-tailwind": "^1.4.2",
"@navikt/ds-tailwind": "^1.5.4",
"@types/node": "^17.0.35",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
Binary file not shown.
Binary file not shown.
+26 -26
View File
@@ -3166,7 +3166,7 @@ __metadata:
languageName: node
linkType: hard
"@navikt/ds-codemod@^1.4.0, @navikt/ds-codemod@workspace:@navikt/codemod":
"@navikt/ds-codemod@^1.5.3, @navikt/ds-codemod@workspace:@navikt/codemod":
version: 0.0.0-use.local
resolution: "@navikt/ds-codemod@workspace:@navikt/codemod"
dependencies:
@@ -3193,7 +3193,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css-internal@^1.4.0, @navikt/ds-css-internal@workspace:@navikt/internal/css":
"@navikt/ds-css-internal@^1.5.3, @navikt/ds-css-internal@workspace:@navikt/internal/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css-internal@workspace:@navikt/internal/css"
dependencies:
@@ -3204,11 +3204,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css@*, @navikt/ds-css@^1.4.0, @navikt/ds-css@workspace:@navikt/core/css":
"@navikt/ds-css@*, @navikt/ds-css@^1.5.3, @navikt/ds-css@workspace:@navikt/core/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css@workspace:@navikt/core/css"
dependencies:
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-tokens": ^1.5.3
normalize.css: ^8.0.1
postcss: ^8.4.0
postcss-cli: ^9.0.0
@@ -3217,7 +3217,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-icons@^1.4.0, @navikt/ds-icons@workspace:@navikt/icons":
"@navikt/ds-icons@^1.5.3, @navikt/ds-icons@workspace:@navikt/icons":
version: 0.0.0-use.local
resolution: "@navikt/ds-icons@workspace:@navikt/icons"
dependencies:
@@ -3247,12 +3247,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react-internal@^1.4.0, @navikt/ds-react-internal@workspace:@navikt/internal/react":
"@navikt/ds-react-internal@^1.5.3, @navikt/ds-react-internal@workspace:@navikt/internal/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react-internal@workspace:@navikt/internal/react"
dependencies:
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-icons": ^1.5.3
"@navikt/ds-react": ^1.5.3
"@types/node": ^17.0.35
clsx: ^1.1.1
concurrently: 7.2.1
@@ -3269,12 +3269,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react@*, @navikt/ds-react@^1.4.0, @navikt/ds-react@workspace:@navikt/core/react":
"@navikt/ds-react@*, @navikt/ds-react@^1.5.3, @navikt/ds-react@workspace:@navikt/core/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react@workspace:@navikt/core/react"
dependencies:
"@floating-ui/react-dom-interactions": 0.9.2
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-icons": ^1.5.3
"@radix-ui/react-tabs": 1.0.0
"@radix-ui/react-toggle-group": 1.0.0
"@testing-library/dom": 8.13.0
@@ -3311,11 +3311,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tailwind@^1.4.0, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
"@navikt/ds-tailwind@^1.5.3, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
version: 0.0.0-use.local
resolution: "@navikt/ds-tailwind@workspace:@navikt/core/tailwind"
dependencies:
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-tokens": ^1.5.3
"@types/jest": ^29.0.0
"@types/node": ^17.0.35
jest: ^29.0.0
@@ -3326,7 +3326,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tokens@^1.4.0, @navikt/ds-tokens@workspace:@navikt/core/tokens":
"@navikt/ds-tokens@^1.5.3, @navikt/ds-tokens@workspace:@navikt/core/tokens":
version: 0.0.0-use.local
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
dependencies:
@@ -8341,14 +8341,14 @@ __metadata:
version: 0.0.0-use.local
resolution: "aksel.nav.no@workspace:aksel.nav.no"
dependencies:
"@navikt/ds-codemod": ^1.4.0
"@navikt/ds-css": ^1.4.0
"@navikt/ds-css-internal": ^1.4.0
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-react-internal": ^1.4.0
"@navikt/ds-tailwind": ^1.4.0
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-codemod": ^1.5.3
"@navikt/ds-css": ^1.5.3
"@navikt/ds-css-internal": ^1.5.3
"@navikt/ds-icons": ^1.5.3
"@navikt/ds-react": ^1.5.3
"@navikt/ds-react-internal": ^1.5.3
"@navikt/ds-tailwind": ^1.5.3
"@navikt/ds-tokens": ^1.5.3
prettier-plugin-tailwindcss: ^0.1.13
languageName: unknown
linkType: soft
@@ -21068,11 +21068,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "nextjs-demo@workspace:examples/next"
dependencies:
"@navikt/ds-css": ^1.4.0
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-react-internal": ^1.4.0
"@navikt/ds-tailwind": ^1.4.0
"@navikt/ds-css": ^1.5.3
"@navikt/ds-icons": ^1.5.3
"@navikt/ds-react": ^1.5.3
"@navikt/ds-react-internal": ^1.5.3
"@navikt/ds-tailwind": ^1.5.3
"@types/node": ^17.0.35
"@types/react": ^18.0.0
"@types/react-dom": ^18.0.0