Compare commits

...
Author SHA1 Message Date
github-actions[bot]andgithub-actions[bot] 9a98f0eae4 Version Packages (#1988)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-05-16 13:13:56 +02:00
Ken affcab14c3 ✨ Copybutton-komponent (#1982) 2023-05-16 12:56:16 +02:00
Ken d51b0238d5 💄 Oppdatert ToggleGroup-bruk på ikonsider 2023-05-12 12:58:22 +02:00
72 changed files with 1557 additions and 156 deletions

No files matched your search

+1 -1
View File
@@ -23,7 +23,7 @@ module.exports = {
addons: [
"@storybook/addon-a11y",
"@whitespace/storybook-addon-html",
"@storybook/addon-interactions",
{
name: "@storybook/addon-storysource",
options: {
+2
View File
@@ -1,5 +1,7 @@
# @navikt/aksel-icons
## 3.2.0
## 3.1.3
## 3.1.2
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel-icons",
"version": "3.1.3",
"version": "3.2.0",
"author": "Aksel | NAV",
"homepage": "https://aksel.nav.no/ikoner",
"repository": {
+7
View File
@@ -1,5 +1,12 @@
# @navikt/aksel
## 3.2.0
### Patch Changes
- Updated dependencies [[`affcab14c`](https://github.com/navikt/aksel/commit/affcab14c3d536929dfa64a36f5b43f9d0e8c3b7)]:
- @navikt/ds-css@3.2.0
## 3.1.3
### Patch Changes
+33
View File
@@ -22,6 +22,39 @@ To get started:
npx @navikt/aksel codemod --help
```
### v3
There is no general codemods for migrating from v2 -> v3.
#### CopyButton
`npx @navikt/aksel codemod v3-copybutton ...`
`<CopyToClipboard />` has been renamed to `<CopyButton />` and refactored.
- Namechange
- removed props `popoverText`, `iconPosition`, `popoverPlacement`
- changed variants
- refactored CSS and React-code. ⚠️ Overwritten CSS will not be migrated!
```diff
-import { CopyToClipboard } from "@navikt/ds-react-internal";
+import { CopyButton } from "@navikt/ds-react";
-<CopyToClipboard
+<CopyButton
- popoverText="popoverText"
- iconPosition="left"
- popoverPlacement="bottom-end"
copyText="Text to copy"
size="medium"
>
- text
+</CopyButton>
-</CopyToClipboard>
```
### v1 -> v2
[Documentation](https://aksel.nav.no/grunnleggende/kode/migrering#h76f47744d112)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/aksel",
"version": "3.1.3",
"version": "3.2.0",
"description": "Aksel command line interface. Handles css-imports, codemods and more",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -29,7 +29,7 @@
},
"homepage": "https://aksel.nav.no/grunnleggende/kode/kommandolinje",
"dependencies": {
"@navikt/ds-css": "3.1.3",
"@navikt/ds-css": "3.2.0",
"axios": "1.3.6",
"chalk": "4.1.0",
"clipboardy": "^2.3.0",
+22 -1
View File
@@ -1,7 +1,12 @@
import chalk from "chalk";
export const migrations: {
[key: string]: { description: string; value: string; path: string }[];
[key: string]: {
description: string;
value: string;
path: string;
warning?: string;
}[];
} = {
"1.0.0": [
{
@@ -48,6 +53,16 @@ export const migrations: {
path: "v2.0.0/update-less-tokens/update-less-tokens",
},
],
"v3.0.0": [
{
description:
"Replaces deprecated <CopyToClipboard /> with <CopyButton />",
value: "v3-copybutton",
path: "v3.0.0/copybutton/copybutton",
warning:
"Remember to clean css-import from '@navikt/ds-css-internal' if no longer needed\nIf non-text was used as children, or different locales were handled, you need to manually fix this",
},
],
};
export function getMigrationPath(str: string) {
@@ -56,6 +71,12 @@ export function getMigrationPath(str: string) {
.find((x) => x.value === str)?.path;
}
export function getWarning(str: string) {
return Object.values(migrations)
.reduce((acc, val) => [...val, ...acc], [])
.find((x) => x.value === str)?.warning;
}
export function getMigrationNames() {
return Object.values(migrations).reduce(
(acc, val) => [...val.map((x) => x.value), ...acc],
+5 -1
View File
@@ -2,7 +2,7 @@ import { Command } from "commander";
import fg from "fast-glob";
import * as jscodeshift from "jscodeshift/src/Runner";
import path from "path";
import { getMigrationPath } from "./migrations";
import { getMigrationPath, getWarning } from "./migrations";
import chalk from "chalk";
const ignoreNodeModules = [
@@ -32,6 +32,8 @@ export async function runCodeshift(
options?.glob && console.log(`Using glob: ${chalk.green(options.glob)}\n`);
const warning = getWarning(input);
try {
await jscodeshift.run(codemodPath, filepaths, {
babel: true,
@@ -46,6 +48,8 @@ export async function runCodeshift(
force: options?.force,
print: options?.print,
});
warning && console.log(`\n${chalk.yellow(warning)}\n`);
} catch (error) {
program.error(chalk.red("Error:", error.message));
}
@@ -0,0 +1,89 @@
import chalk from "chalk";
import moveAndRenameImport from "../../../utils/moveAndRenameImport";
import removePropsFromComponent from "../../../utils/removeProps";
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
*/
export default function transformer(file, api, options, ...rest) {
const j = api.jscodeshift;
let root: any;
try {
root = j(file.source);
} catch {
return file.source;
}
const toName = "CopyButton";
const localName = moveAndRenameImport(j, root, {
fromImport: "@navikt/ds-react-internal",
toImport: "@navikt/ds-react",
fromName: "CopyToClipboard",
toName,
});
if (localName === null) {
return root.toSource(options.printOptions);
}
/* Finds and replaces import from CopyToClipboard -> CopyButton */
if (root.findJSXElements(localName)) {
removePropsFromComponent(j, root, localName, [
"popoverText",
"popoverPlacement",
"iconPosition",
"variant",
]);
const component = root.findJSXElements(localName);
component.forEach((node) => {
const children = node.node.children;
let flagged = false;
if (
children.length > 0 &&
!node.node.openingElement.attributes.some(
(attr) => attr.name.name === "text"
)
) {
if (children.length === 1 && children[0].type === "JSXText") {
node.node.openingElement.attributes.push(
j.jsxAttribute(
j.jsxIdentifier("text"),
j.literal(children[0].value.trim())
)
);
} else {
flagged = true;
console.log(
chalk.yellow(
`\n\nWarning: Detected advanced children-type!\nCodemod can't convert into "text" prop so you will need to update this manually.`
)
);
}
}
if (!flagged) {
node.node.children = [];
node.node.openingElement.selfClosing = true;
node.node.closingElement = null;
}
});
const compRoot = root.find(j.JSXElement, {
openingElement: { name: { name: localName } },
});
compRoot.forEach((x) => {
x.node.openingElement.name.name = "CopyButton";
if (x.node.children.length > 0) {
x.node.closingElement.name.name = "CopyButton";
}
});
}
return root.toSource(options.printOptions);
}
@@ -0,0 +1,6 @@
import { CopyToClipboard as DsCpyButton } from "@navikt/ds-react-internal";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <DsCpyButton></DsCpyButton>;
};
@@ -0,0 +1,6 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton />;
};
@@ -0,0 +1,16 @@
import { CopyToClipboard } from "@navikt/ds-react-internal";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return (
<CopyToClipboard
popoverText="popoverText"
copyText="Text to copy"
iconPosition="left"
size="medium"
popoverPlacement="bottom-end"
>
{text}
</CopyToClipboard>
);
};
@@ -0,0 +1,10 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return (
<CopyButton copyText="Text to copy" size="medium" text="text">
{text}
</CopyButton>
);
};
@@ -0,0 +1,6 @@
import { CopyToClipboard } from "@navikt/ds-react-internal";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyToClipboard></CopyToClipboard>;
};
@@ -0,0 +1,6 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton />;
};
@@ -0,0 +1,16 @@
import { CopyToClipboard } from "@navikt/ds-react-internal";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return (
<CopyToClipboard
popoverText="popoverText"
copyText="Text to copy"
iconPosition="left"
size="medium"
popoverPlacement="bottom-end"
>
text
</CopyToClipboard>
);
};
@@ -0,0 +1,6 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton copyText="Text to copy" size="medium" text="text" />;
};
@@ -0,0 +1,12 @@
import { check } from "../../../../utils/check";
const migration = "copybutton";
const fixtures = ["complete", "idempotent", "alias", "cleanup", "import"];
for (const fixture of fixtures) {
check(__dirname, {
fixture,
migration,
extension: "js",
});
}
@@ -0,0 +1,6 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton copyText="Text to copy" size="medium" text={props.text} />;
};
@@ -0,0 +1,6 @@
import { CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton copyText="Text to copy" size="medium" text={props.text} />;
};
@@ -0,0 +1,7 @@
import { CopyToClipboard, Dropdown } from "@navikt/ds-react-internal";
import { Button } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyToClipboard></CopyToClipboard>;
};
@@ -0,0 +1,7 @@
import { Dropdown } from "@navikt/ds-react-internal";
import { Button, CopyButton } from "@navikt/ds-react";
/* eslint-disable react/jsx-no-undef */
export const Page = () => {
return <CopyButton />;
};
@@ -0,0 +1,83 @@
import core, { Collection } from "jscodeshift";
export default function moveAndRenameImport(
j: core.JSCodeshift,
root: Collection<any>,
{
fromImport,
toImport,
fromName,
toName,
}: { fromImport: string; toImport: string; fromName: string; toName: string }
) {
const existingFromImport = root.find(j.ImportDeclaration, {
source: {
value: fromImport,
},
});
if (!existingFromImport.length) {
return null;
}
let localname = fromName;
const existingFromImportSpecifier = existingFromImport?.find(
j.ImportSpecifier,
(node) => {
if (node.imported.name === fromName) {
localname = node.local.name;
}
return node.imported.name === fromName;
}
);
if (!existingFromImport.length || !existingFromImportSpecifier?.length) {
return null;
}
if (existingFromImportSpecifier?.length > 0) {
existingFromImportSpecifier.remove();
}
if (
!existingFromImport.get("specifiers").value?.length ||
existingFromImport.get("specifiers").value?.length === 0
) {
existingFromImport.remove();
}
const existingImport = root.find(j.ImportDeclaration, {
source: {
value: toImport,
},
});
const existingImportSpecifier = existingImport.find(j.ImportSpecifier, {
imported: {
name: toName,
},
});
if (existingImportSpecifier.length <= 0) {
const newImportSpecifier = j.importSpecifier(j.identifier(toName));
if (existingImport.length > 0) {
existingImport.get("specifiers").push(newImportSpecifier);
} else {
const newImport = j.importDeclaration(
[newImportSpecifier],
j.stringLiteral(toImport)
);
const lastImport = root.find(j.ImportDeclaration).at(-1);
if (lastImport.length > 0) {
lastImport.insertAfter(newImport);
} else {
root.get().node.program.body.unshift(newImport);
}
}
}
return localname;
}
@@ -0,0 +1,25 @@
import core, { Collection } from "jscodeshift";
export default function removePropsFromComponent(
j: core.JSCodeshift,
root: Collection<any>,
componentName: string,
propsToRemove: string[]
) {
const component = root.findJSXElements(componentName);
component.forEach((node) => {
const attributes = node.node.openingElement.attributes;
for (let i = attributes.length - 1; i >= 0; i--) {
const attribute = attributes[i];
if (
attribute.type === "JSXAttribute" &&
propsToRemove.includes(attribute.name.name.toString())
) {
attributes.splice(i, 1);
}
}
});
}
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-codemod
## 3.2.0
## 3.1.3
## 3.1.2
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "3.1.3",
"version": "3.2.0",
"description": "Aksel codemods for NAVs designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
+2 -2
View File
@@ -40,8 +40,8 @@
"build-pict": "svgr --silent --index-template index-template.js --out-dir src/pictograms pictograms"
},
"dependencies": {
"@navikt/ds-icons": "^3.1.3",
"@navikt/ds-react": "^3.1.3",
"@navikt/ds-icons": "^3.2.0",
"@navikt/ds-react": "^3.2.0",
"clsx": "^1.1.1"
},
"devDependencies": {
+9
View File
@@ -1,5 +1,14 @@
# @navikt/ds-css
## 3.2.0
### Minor Changes
- [#1982](https://github.com/navikt/aksel/pull/1982) [`affcab14c`](https://github.com/navikt/aksel/commit/affcab14c3d536929dfa64a36f5b43f9d0e8c3b7) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny komponent `<CopyButton />`!
- Erstatter `<CopyToClipboard />` fra `@navikt/ds-react-internal`
- CopyToClipboard er markert som deprecated. Den vil fortsatt fungere, men noen lintere vil kunne ende opp med å klage på den.
## 3.1.3
### Patch Changes
+5
View File
@@ -63,6 +63,11 @@ const StyleMappings = {
component: "ContentContainer",
main: "content-container.css",
},
{
component: "CopyButton",
main: "copybutton.css",
dependencies: [typoCss],
},
{ component: "Detail", main: typoCss },
{ component: "ErrorMessage", main: typoCss },
{ component: "ErrorSummary", main: formCss, dependencies: [typoCss] },
+4 -1
View File
@@ -146,7 +146,10 @@ async function bundleMinified() {
}
function copyToVersionFolder() {
const files = fastglob.sync("**/*.css", { cwd: `./${rootDir}` });
const files = fastglob.sync("**/*.css", {
cwd: `./${rootDir}`,
ignore: "**/version/**",
});
for (let file of files) {
const css = fs.readFileSync(`${rootDir}/${file}`, { encoding: "utf-8" });
+129
View File
@@ -0,0 +1,129 @@
[data-theme="dark"] .navds-copybutton,
[data-theme="dark"].navds-copybutton {
--a-text-action: var(--a-blue-300);
--a-surface-hover: rgb(214 231 255 /0.13);
--a-icon-success: rgb(51 170 95 /1);
--a-text-subtle: rgb(231 240 254 /0.69);
--a-text-default: rgb(251 252 254 /0.96);
}
.navds-copybutton {
--__ac-copybutton-padding: var(--a-spacing-3) var(--a-spacing-5);
cursor: pointer;
margin: 0;
text-decoration: none;
border: none;
background: none;
border-radius: var(--ac-copybutton-border-radius, var(--a-border-radius-medium));
padding: var(--__ac-copybutton-padding);
display: grid;
place-content: center;
}
.navds-copybutton--small {
--__ac-copybutton-padding: var(--a-spacing-1) var(--a-spacing-3);
min-height: 2rem;
}
.navds-copybutton--icon-only {
--__ac-copybutton-padding: var(--a-spacing-3);
}
.navds-copybutton--small.navds-copybutton--icon-only {
--__ac-copybutton-padding: var(--a-spacing-1);
}
.navds-copybutton__icon {
font-size: 1.5rem;
display: flex;
margin-left: -4px;
}
.navds-copybutton__icon:only-child {
margin: 0;
}
.navds-copybutton:focus-visible {
outline: none;
box-shadow: var(--a-shadow-focus);
}
@supports not selector(:focus-visible) {
.navds-copybutton:focus {
outline: none;
box-shadow: var(--a-shadow-focus);
}
}
/* Variant/action */
.navds-copybutton--action {
color: var(--ac-copybutton-action-text, var(--a-text-action));
background-color: var(--ac-copybutton-action-bg, var(--a-surface-transparent));
}
.navds-copybutton--action:hover {
color: var(--ac-copybutton-action-hover-text, var(--a-text-action));
background-color: var(--ac-copybutton-action-hover-bg, var(--a-surface-hover));
}
.navds-copybutton--action:where(:disabled),
.navds-copybutton--action:hover:where(:disabled) {
color: var(--ac-copybutton-action-text, var(--a-text-action));
background-color: var(--ac-copybutton-action-bg, var(--a-surface-transparent));
box-shadow: none;
}
.navds-copybutton--active.navds-copybutton--action {
color: var(--ac-copybutton-action-active-text, var(--a-icon-success));
}
/* Variant/neutral */
.navds-copybutton--neutral {
color: var(--ac-copybutton-neutral-text, var(--a-text-subtle));
background-color: var(--ac-copybutton-neutral-bg, var(--a-surface-transparent));
}
.navds-copybutton--neutral:hover {
color: var(--ac-copybutton-neutral-hover-text, var(--a-text-default));
background-color: var(--ac-copybutton-neutral-hover-bg, var(--a-surface-hover));
}
.navds-copybutton--neutral:where(:disabled, .navds-copybutton--disabled),
.navds-copybutton--neutral:hover:where(:disabled, .navds-copybutton--disabled) {
color: var(--ac-copybutton-neutral-text, var(--a-text-default));
background-color: var(--ac-copybutton-neutral-bg, var(--a-surface-transparent));
box-shadow: none;
}
.navds-copybutton--active.navds-copybutton--neutral {
color: var(--ac-copybutton-neutral-active-text, var(--a-text-default));
}
.navds-copybutton__content {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--a-spacing-2);
}
.navds-copybutton--active > .navds-copybutton__content {
animation: var(--ac-copybutton-animation, akselCopyButtonAnimation 0.4s linear);
}
@keyframes akselCopyButtonAnimation {
0% {
opacity: 0.4;
}
100% {
opacity: 1;
}
}
/* Disabled */
.navds-copybutton:where(:disabled) {
cursor: not-allowed;
opacity: 0.3;
}
+1
View File
@@ -8,6 +8,7 @@
@import "content-container.css";
@import "chat.css";
@import "chips.css";
@import "copybutton.css";
@import "expansioncard.css";
@import "guide-panel.css";
@import "form/index.css";
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "3.1.3",
"version": "3.2.0",
"description": "CSS for NAV Designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -27,7 +27,7 @@
"css:get-version": "node config/get-version.js"
},
"devDependencies": {
"@navikt/ds-tokens": "^3.1.3",
"@navikt/ds-tokens": "^3.2.0",
"cssnano": "6.0.0",
"fast-glob": "3.2.11",
"lodash": "4.17.21",
+14
View File
@@ -104,6 +104,20 @@
"--ac-chip-removable-neutral-hover-bg": "--a-surface-neutral-subtle-hover",
"--ac-chip-removable-neutral-hover-border": "--a-border-strong"
},
"copybutton": {
"--ac-copybutton-border-radius": "--a-border-radius-medium",
"--ac-copybutton-action-text": "--a-text-action",
"--ac-copybutton-action-bg": "--a-surface-transparent",
"--ac-copybutton-action-hover-text": "--a-text-action",
"--ac-copybutton-action-hover-bg": "--a-surface-hover",
"--ac-copybutton-action-active-text": "--a-icon-success",
"--ac-copybutton-neutral-text": "--a-text-subtle",
"--ac-copybutton-neutral-bg": "--a-surface-transparent",
"--ac-copybutton-neutral-hover-text": "--a-text-default",
"--ac-copybutton-neutral-hover-bg": "--a-surface-hover",
"--ac-copybutton-neutral-active-text": "--a-text-default",
"--ac-copybutton-animation": "akselCopyButtonAnimation 0.4s linear"
},
"date": {
"--ac-date-middle-text": "--a-text-on-action",
"--ac-date-middle-bg": "--a-surface-action-selected",
+14
View File
@@ -1,5 +1,19 @@
# @navikt/ds-react
## 3.2.0
### Minor Changes
- [#1982](https://github.com/navikt/aksel/pull/1982) [`affcab14c`](https://github.com/navikt/aksel/commit/affcab14c3d536929dfa64a36f5b43f9d0e8c3b7) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny komponent `<CopyButton />`!
- Erstatter `<CopyToClipboard />` fra `@navikt/ds-react-internal`
- CopyToClipboard er markert som deprecated. Den vil fortsatt fungere, men noen lintere vil kunne ende opp med å klage på den.
### Patch Changes
- Updated dependencies []:
- @navikt/aksel-icons@3.2.0
## 3.1.3
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "3.1.3",
"version": "3.2.0",
"description": "Aksel react-components for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -38,7 +38,7 @@
},
"dependencies": {
"@floating-ui/react": "0.17.0",
"@navikt/aksel-icons": "^3.1.3",
"@navikt/aksel-icons": "^3.2.0",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
@@ -0,0 +1,174 @@
"use client";
import { CheckmarkIcon, FilesIcon } from "@navikt/aksel-icons";
import cl from "clsx";
import React, {
ButtonHTMLAttributes,
forwardRef,
useEffect,
useRef,
useState,
} from "react";
import copy from "../util/copy";
import Label from "../typography/Label";
export interface CopyButtonProps
extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
/**
* @default "medium"
*/
size?: "medium" | "small";
/**
* @default "neutral"
*/
variant?: "action" | "neutral";
/**
* Text to copy to clipboard
*/
copyText: string;
/**
* Optional text in button
*/
text?: string;
/**
* Text shown when button is clicked
* Only set if used with 'text'-prop
*/
activeText?: string;
/**
* Callback when 'copied'-state is active
*/
onActiveChange?: (state: boolean) => void;
/**
* Icon shown when button is not clicked
* @default <FilesIcon />
*/
icon?: React.ReactNode;
/**
* Icon shown when active
* @default <CheckmarkIcon />
*/
activeIcon?: React.ReactNode;
/**
* Timeout duration in milliseconds
* @default 2000
*/
activeDuration?: number;
/**
* * accessible label for icon (ignored if text is set)
* @default 'Kopier'
*/
title?: string;
/**
* accessible label for icon in active-state (ignored if text is set)
* @default 'Kopiert'
*/
activeTitle?: string;
}
export const CopyButton = forwardRef<HTMLButtonElement, CopyButtonProps>(
(
{
className,
copyText,
text,
activeText = "Kopiert!",
variant = "neutral",
size = "medium",
onActiveChange,
icon,
activeIcon,
activeDuration = 2000,
title = "Kopier",
activeTitle = "Kopiert",
...rest
},
ref
) => {
const [active, setActive] = useState(false);
const timeoutRef = useRef<number>();
useEffect(() => {
return () => {
timeoutRef.current && clearTimeout(timeoutRef.current);
};
}, []);
const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
timeoutRef.current && clearTimeout(timeoutRef.current);
copy(copyText);
setActive(true);
onActiveChange?.(true);
rest.onClick?.(event);
timeoutRef.current = window.setTimeout(() => {
setActive(false);
onActiveChange?.(false);
}, activeDuration);
};
return (
<button
ref={ref}
type="button"
{...rest}
aria-live="polite"
className={cl(
"navds-copybutton",
className,
`navds-copybutton--${size}`,
`navds-copybutton--${variant}`,
{
"navds-copybutton--icon-only": !text,
"navds-copybutton--active": active,
}
)}
onClick={handleClick}
>
<span className="navds-copybutton__content">
{active ? (
<span className="navds-copybutton__icon">
{activeIcon ?? (
<CheckmarkIcon
aria-hidden={!!text}
title={text ? undefined : activeTitle}
/>
)}
</span>
) : (
<span className="navds-copybutton__icon">
{icon ?? (
<FilesIcon
aria-hidden={!!text}
title={text ? undefined : title}
/>
)}
</span>
)}
{text &&
(active ? (
<Label
as="span"
size={size === "medium" ? "medium" : "small"}
aria-live="polite"
>
{activeText}
</Label>
) : (
<Label
as="span"
size={size === "medium" ? "medium" : "small"}
aria-live="polite"
>
{text}
</Label>
))}
</span>
</button>
);
}
);
export default CopyButton;
@@ -0,0 +1,168 @@
import { LinkIcon, ThumbUpIcon } from "@navikt/aksel-icons";
import { userEvent, within } from "@storybook/testing-library";
import React from "react";
import { CopyButton } from ".";
import { Tooltip } from "../tooltip";
export default {
title: "ds-react/CopyButton",
component: CopyButton,
argTypes: {
size: {
defaultValue: "medium",
control: { type: "radio" },
options: ["small", "medium"],
},
variant: {
defaultValue: undefined,
control: { type: "radio" },
options: ["neutral", "action"],
},
},
};
export const Default = {
render: (args) => <CopyButton {...args} />,
args: {
size: "medium",
duration: 2000,
copyText: "3.14",
text: "",
activeText: "",
},
};
export const Interaction = {
render: () => (
<CopyButton
copyText="3.14"
variant="action"
text="Kopier"
data-testid="copy-button"
/>
),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByTestId("copy-button");
userEvent.click(button);
},
};
export const Variants = {
render: () => (
<div className="colgap">
<CopyButton copyText="3.14" variant="action" text="Kopier" />
<CopyButton copyText="3.14" variant="neutral" text="Kopier" />
</div>
),
};
export const Sizes = {
render: () => (
<div className="colgap">
<div className="rowgap">
<CopyButton copyText="3.14" variant="action" />
<CopyButton copyText="3.14" variant="neutral" />
<CopyButton copyText="3.14" variant="action" text="Kopier" />
<CopyButton copyText="3.14" variant="neutral" text="Kopier" />
</div>
<div className="rowgap">
<CopyButton size="small" copyText="3.14" variant="action" />
<CopyButton size="small" copyText="3.14" variant="neutral" />
<CopyButton
size="small"
copyText="3.14"
variant="action"
text="Kopier"
/>
<CopyButton
size="small"
copyText="3.14"
variant="neutral"
text="Kopier"
/>
</div>
</div>
),
};
export const Texts = {
render: () => (
<div className="colgap">
<div>
<CopyButton
copyText="3.14"
text="Kopier XYZ"
activeText="Kopierte XYZ"
/>
</div>
<div>
<CopyButton
copyText="3.14"
size="small"
text="Kopier XYZ"
activeText="Kopierte XYZ"
/>
</div>
</div>
),
};
export const Icons = {
render: () => (
<div className="rowgap">
<div>
<CopyButton
copyText="3.14"
icon={<LinkIcon title="Kopier" />}
activeIcon={<ThumbUpIcon title="Kopiert" />}
/>
</div>
<div>
<CopyButton
copyText="3.14"
size="small"
icon={<LinkIcon title="Kopier" />}
activeIcon={<ThumbUpIcon title="Kopiert" />}
/>
</div>
</div>
),
};
export const InlineDemo = {
render: () => (
<div style={{ display: "flex", gap: "0.5rem", alignItems: "center" }}>
<CopyButton size="small" copyText="3.14" /> Kopier dette feltet
</div>
),
};
export const WithTooltip = {
render: () => {
return (
<div>
<Tooltip content="Kopier fødselsnummer">
<CopyButton copyText="3.14" />
</Tooltip>
</div>
);
},
};
export const Duration = {
render: () => <CopyButton copyText="3.14" activeDuration={300} />,
};
export const Disabled = {
render: () => (
<div className="colgap">
<CopyButton copyText="3.14" disabled />
<CopyButton copyText="3.14" size="small" disabled />
<CopyButton copyText="3.14" disabled variant="action" />
</div>
),
};
@@ -0,0 +1 @@
export { default as CopyButton, type CopyButtonProps } from "./CopyButton";
+2 -1
View File
@@ -3,9 +3,10 @@ export * from "./alert";
export * from "./button";
export * from "./chat";
export * from "./chips";
export * from "./copybutton";
export * from "./date";
export * from "./form";
export * from "./expansion-card";
export * from "./form";
export * from "./grid";
export * from "./guide-panel";
export * from "./help-text";
+81
View File
@@ -0,0 +1,81 @@
// https://github.com/sudodoki/copy-to-clipboard/blob/main/index.js
const defaultMessage = "Kopier til utklippstavle: #{key}, Enter";
function format(message) {
const copyKey = (/mac os x/i.test(navigator.userAgent) ? "⌘" : "Ctrl") + "+C";
return message.replace(/#{\s*key\s*}/g, copyKey);
}
export default function copy(text) {
let debug,
message,
range,
selection,
mark,
success = false;
debug = process.env.NODE_ENV !== "production";
try {
range = document.createRange();
selection = document.getSelection();
mark = document.createElement("span");
mark.textContent = text;
// avoid screen readers from reading out loud the text
mark.ariaHidden = "true";
// reset user styles for span element
mark.style.all = "unset";
// prevents scrolling to the end of the page
mark.style.position = "fixed";
mark.style.top = 0;
mark.style.clip = "rect(0, 0, 0, 0)";
// used to preserve spaces and line breaks
mark.style.whiteSpace = "pre";
// do not inherit user-select (it may be `none`)
mark.style.webkitUserSelect = "text";
mark.style.MozUserSelect = "text";
mark.style.msUserSelect = "text";
mark.style.userSelect = "text";
mark.addEventListener("copy", function (e) {
e.stopPropagation();
});
document.body.appendChild(mark);
range.selectNodeContents(mark);
selection.addRange(range);
const successful = document.execCommand("copy");
if (!successful) {
throw new Error("copy command was unsuccessful");
}
success = true;
} catch (err) {
debug && console.error("unable to copy using execCommand: ", err);
debug && console.warn("trying IE specific stuff");
try {
(window as any).clipboardData.setData("text", text);
success = true;
} catch (err) {
debug && console.error("unable to copy using clipboardData: ", err);
debug && console.error("falling back to prompt");
message = format(defaultMessage);
window.prompt(message, text);
}
} finally {
if (selection) {
if (typeof selection.removeRange == "function") {
selection.removeRange(range);
} else {
selection.removeAllRanges();
}
}
if (mark) {
document.body.removeChild(mark);
}
}
return success;
}
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-tailwind
## 3.2.0
## 3.1.3
## 3.1.2
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "3.1.3",
"version": "3.2.0",
"description": "Tailwind config based on @navikt/ds-tokens",
"author": "Aksel | NAV designsystem team",
"keywords": [
@@ -22,7 +22,7 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^3.1.3",
"@navikt/ds-tokens": "^3.2.0",
"@types/jest": "^29.0.0",
"color": "4.2.3",
"jest": "^29.0.0",
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-tokens
## 3.2.0
## 3.1.3
## 3.1.2
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "3.1.3",
"version": "3.2.0",
"description": "Design-tokens for NAV designsystem",
"author": "Aksel | NAV designsystem team",
"keywords": [
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-icons
## 3.2.0
## 3.1.3
## 3.1.2
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "3.1.3",
"version": "3.2.0",
"description": "Aksel icons for NAV",
"author": "Aksel | NAV designsystem team",
"repository": {
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-css-internal
## 3.2.0
## 3.1.3
## 3.1.2
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "3.1.3",
"version": "3.2.0",
"description": "CSS for NAV internal Designsystem-components",
"author": "Aksel | NAV designsystem team",
"keywords": [
+15
View File
@@ -1,5 +1,20 @@
# @navikt/ds-react-internal
## 3.2.0
### Minor Changes
- [#1982](https://github.com/navikt/aksel/pull/1982) [`affcab14c`](https://github.com/navikt/aksel/commit/affcab14c3d536929dfa64a36f5b43f9d0e8c3b7) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Ny komponent `<CopyButton />`!
- Erstatter `<CopyToClipboard />` fra `@navikt/ds-react-internal`
- CopyToClipboard er markert som deprecated. Den vil fortsatt fungere, men noen lintere vil kunne ende opp med å klage på den.
### Patch Changes
- Updated dependencies [[`affcab14c`](https://github.com/navikt/aksel/commit/affcab14c3d536929dfa64a36f5b43f9d0e8c3b7)]:
- @navikt/ds-react@3.2.0
- @navikt/aksel-icons@3.2.0
## 3.1.3
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "3.1.3",
"version": "3.2.0",
"description": "Aksel react components for internal UIs in NAV",
"author": "Aksel | NAV designsystem team",
"license": "MIT",
@@ -36,8 +36,8 @@
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/aksel-icons": "^3.1.3",
"@navikt/ds-react": "^3.1.3",
"@navikt/aksel-icons": "^3.2.0",
"@navikt/ds-react": "^3.2.0",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
@@ -10,6 +10,9 @@ import {
mergeRefs,
} from "@navikt/ds-react";
/**
* @deprecated Use import { CopyButton } from "@navikt/ds-react" instead
*/
export interface CopyToClipboardProps
extends Omit<ButtonProps, "children" | "onClick" | "variant" | "loading"> {
/**
@@ -57,6 +60,9 @@ export interface CopyToClipboardProps
variant?: "tertiary";
}
/**
* @deprecated Use <CopyButton /> instead: import { CopyButton } from "@navikt/ds-react";
*/
export const CopyToClipboard = forwardRef<
HTMLButtonElement,
CopyToClipboardProps
+3 -3
View File
@@ -32,12 +32,12 @@
├── internal/react # @navikt/ds-react-internal, komponenter interne flater
├── internal/css # @navikt/ds-css-internal, css interne flater
├── aksel-icons # @navikt/aksel-icons, ikonpakke
├── icons # @navikt/ds-icons (ikke lengre i bruk)
└── codemod # @navikt/ds-codemod, migrerings-scripts
└── aksel # @navikt/aksel, kommandolinje-verktøy
aksel.nav.no/
├── website # NEXT.JS app (v13)
├── website # NEXT.JS app (v13)
└── website/sanity # Sanity CMS-app (v3)
```
## Commands
+9 -9
View File
@@ -15,15 +15,15 @@
"website"
],
"dependencies": {
"@navikt/aksel-icons": "^3.1.3",
"@navikt/ds-codemod": "^3.1.3",
"@navikt/ds-css": "^3.1.3",
"@navikt/ds-css-internal": "^3.1.3",
"@navikt/ds-icons": "^3.1.3",
"@navikt/ds-react": "^3.1.3",
"@navikt/ds-react-internal": "^3.1.3",
"@navikt/ds-tailwind": "^3.1.3",
"@navikt/ds-tokens": "^3.1.3"
"@navikt/aksel-icons": "^3.2.0",
"@navikt/ds-codemod": "^3.2.0",
"@navikt/ds-css": "^3.2.0",
"@navikt/ds-css-internal": "^3.2.0",
"@navikt/ds-icons": "^3.2.0",
"@navikt/ds-react": "^3.2.0",
"@navikt/ds-react-internal": "^3.2.0",
"@navikt/ds-tailwind": "^3.2.0",
"@navikt/ds-tokens": "^3.2.0"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.2.3"
@@ -3,9 +3,8 @@ import { TokenTableT } from "@/types";
import { ChevronDownCircleIcon } from "@navikt/aksel-icons";
import internal from "@navikt/ds-css-internal/tokens.json";
import core from "@navikt/ds-css/tokens.json";
import { BodyLong, Label, Link } from "@navikt/ds-react";
import { BodyLong, CopyButton, Label, Link } from "@navikt/ds-react";
import cl from "classnames";
import CopyButton from "components/sanity-modules/code/CopyButton";
import NextLink from "next/link";
import { useState } from "react";
@@ -53,10 +52,9 @@ const TokenTable = ({ node }: { node: TokenTableT }) => {
</tbody>
</table>
{(open || !showMore) && (
<div className="border-border-divider bg-surface-neutral-subtle relative w-full rounded-b border border-t-0 p-2">
<div className="border-border-divider bg-surface-neutral-subtle relative w-full rounded-b border border-t-0 p-2 pr-14">
<CopyButton
variant="tokentable"
content={Object.entries(tokens).reduce(
copyText={Object.entries(tokens).reduce(
(prev, cur) =>
prev +
`${cur[0]}: ${
@@ -64,6 +62,7 @@ const TokenTable = ({ node }: { node: TokenTableT }) => {
};\n`,
""
)}
className="absolute top-2 right-2 z-10"
/>
<Label size="small" as="span" spacing>
Hva er dette?
@@ -1,78 +0,0 @@
import { useRef, useState, useEffect } from "react";
import copy from "copy-to-clipboard";
import React from "react";
import cl from "clsx";
import style from "./index.module.css";
import { CheckmarkIcon, ClipboardIcon } from "@navikt/aksel-icons";
const copyCode = (content: string) =>
copy(content, {
format: "text/plain",
});
interface CopyButtonProps {
content: string;
variant?: "tokentable" | "codeblock";
}
const CopyButton = React.forwardRef<HTMLButtonElement, CopyButtonProps>(
({ content, variant = "codeblock" }, ref) => {
const [active, setActive] = useState(false);
const timeoutRef = useRef<NodeJS.Timeout>();
useEffect(() => {
return () => timeoutRef.current && clearTimeout(timeoutRef.current);
}, []);
const handleCopy = () => {
copyCode(content);
setActive(true);
timeoutRef.current && clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => setActive(false), 1000);
};
return (
<button
ref={ref}
aria-live={active ? "polite" : "off"}
role={active ? "alert" : undefined}
className={cl(
style.copybutton,
"navds-body-short group/button absolute top-2 right-2 z-10 flex h-10 w-10 items-center justify-center overflow-hidden rounded backdrop-blur transition duration-75 focus:outline-none",
{
"hover:text-text-on-inverted focus-visible:shadow-focus-inverted text-3xl text-gray-100 hover:bg-white/20 ":
variant === "codeblock",
"hover:text-deepblue-800 focus-visible:shadow-focus text-text-subtle hover:bg-surface-hover text-2xl":
variant === "tokentable",
}
)}
onClick={handleCopy}
>
<span
aria-hidden={!active}
className={cl(
"absolute inset-0 grid place-content-center transition duration-300",
{
"pointer-events-none translate-y-1.5 opacity-0": !active,
}
)}
>
<CheckmarkIcon title="Kopierte kodesnutt" />
</span>
<span
aria-hidden={active}
className={cl("flex items-center transition duration-300", {
"pointer-events-none -translate-y-1.5 opacity-0": active,
"group-hover/button:opacity-100": !active,
})}
>
<ClipboardIcon title="Kopier kodesnutt" />
</span>
</button>
);
}
);
export default CopyButton;
@@ -2,8 +2,9 @@ import { withErrorBoundary } from "@/error-boundary";
import cl from "clsx";
import Highlight, { defaultProps, Language } from "prism-react-renderer";
import React from "react";
import CopyButton from "./CopyButton";
import { CodeSnippetT } from "@/types";
import { CopyButton } from "@navikt/ds-react";
import style from "./index.module.css";
const CodeSnippet = ({
node: { code },
@@ -43,7 +44,11 @@ const CodeSnippet = ({
)}
{...props}
>
<CopyButton content={code.code} />
<CopyButton
data-theme="dark"
copyText={code.code}
className={cl(style.copybutton, "absolute top-2 right-2 z-10")}
/>
<Highlight
code={code.code}
language={language}
@@ -51,7 +56,7 @@ const CodeSnippet = ({
theme={undefined}
>
{({ tokens, getLineProps, getTokenProps }) => (
<pre className="text-text-on-inverted relative m-0 overflow-x-auto overflow-y-auto rounded-lg bg-[#0f172a] p-4 pr-16 font-mono">
<pre className="text-text-on-inverted relative m-0 mr-16 overflow-x-auto overflow-y-auto rounded-lg bg-[#0f172a] p-4 font-mono">
{tokens.map((line, i) => (
<div
key={i}
@@ -126,11 +126,11 @@ export const IconPage = ({ name }: { name: string }) => {
onSubmit={(e) => e.preventDefault()}
className="flex h-fit w-full items-center gap-4 py-2 px-4"
>
<div className="min-w-fit">
<div className="min-w-40">
<ToggleGroup
size="small"
value={toggle}
onChange={(v) => setToggle(v as any)}
variant="neutral"
>
<ToggleGroup.Item value="stroke">Stroke</ToggleGroup.Item>
<ToggleGroup.Item value="fill">Fill</ToggleGroup.Item>
@@ -0,0 +1,17 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <CopyButton copyText="3.14" variant="action" />;
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 1,
};
@@ -0,0 +1,24 @@
import { LinkBrokenIcon, LinkIcon } from "@navikt/aksel-icons";
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<CopyButton
copyText="3.14"
icon={<LinkIcon title="Kopier lenke" />}
activeIcon={<LinkBrokenIcon title="Kopierte lenke" />}
/>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 6,
};
@@ -0,0 +1,19 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<CopyButton copyText="3.14" text="Kopier XYZ" activeText="Kopierte XYZ" />
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 4,
};
@@ -0,0 +1,20 @@
import { LinkIcon } from "@navikt/aksel-icons";
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<CopyButton copyText="3.14" icon={<LinkIcon title="Kopier lenke" />} />
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 5,
};
@@ -0,0 +1,41 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div>
<Hr />
<Row text="Addresse 1:"> Osloveien 99, 0111 Oslo</Row>
<Row text="Addresse 2:"> Bergenveien 99, 2233 Bergen</Row>
<Row text="Telefon:">4040404040</Row>
<Row text="E-mail:">nav@naversen.no</Row>
</div>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 10,
desc: "Ved utlisting av mye relevant innhold, kan CopyButton brukes for å enklere kopiere informasjonen.",
};
const Hr = () => (
<span className="border-t-1 border-t-border-divider my-1 w-full" />
);
const Row = ({ children, text }: any) => (
<>
<div className="grid grid-cols-[1fr_4fr_auto] items-center gap-2">
<span>{text}</span>
<span>{children}</span>
<CopyButton size="small" copyText={children} />
</div>
<Hr />
</>
);
@@ -0,0 +1,23 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex items-center gap-2">
<CopyButton size="small" copyText="Maguer Gorge 14b, 56430 Tatooine" />{" "}
Adresse: Maguer Gorge 14b, 56430 Tatooine
</div>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 7,
desc: "CopyButton kan settes inline med tekst for å forenkle repetive oppgaver.",
};
@@ -0,0 +1,17 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <CopyButton copyText="3.14" />;
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 0,
};
@@ -0,0 +1,22 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex items-center gap-2">
<CopyButton size="small" copyText="3.14" />
<CopyButton size="small" copyText="3.14" text="Kopier" />
</div>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 2,
};
@@ -0,0 +1,17 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return <CopyButton copyText="3.14" text="Kopier" />;
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 3,
};
@@ -0,0 +1,22 @@
import { CopyButton, Tooltip } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<Tooltip content="Kopier fødselsnummer">
<CopyButton copyText="12003045000" />
</Tooltip>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 8,
desc: "Tooltip kan hjelpe med å gi mer kontekst om hva man kopierer. Vi har testet dette med skjermleser og funnet ut at statisk tekst som 'kopier ...' fungerer bedre enn dynamisk tekst ved klikk i tooltip.",
};
@@ -0,0 +1,28 @@
import { CopyButton } from "@navikt/ds-react";
import { withDsExample } from "components/website-modules/examples/withDsExample";
const Example = () => {
return (
<div className="flex items-center gap-1">
<span>Flere statsborgerskap: Norge, Danmark, Finland</span>
<span>/</span>
<span className="flex items-center gap-1">
17029645183 <CopyButton size="small" copyText="17029645183" />
</span>
<span>/</span>
<span>Gift</span>
</div>
);
};
export default withDsExample(Example);
/* Storybook story */
export const Demo = {
render: Example,
};
export const args = {
index: 9,
desc: "CopyButton kan eksempelvis inlines i breadcrumbs for kopi av fødselsnummer.",
};
+2 -2
View File
@@ -10,8 +10,8 @@
"preview": "vite preview"
},
"dependencies": {
"@navikt/ds-css": "3.1.3",
"@navikt/ds-react": "3.1.3",
"@navikt/ds-css": "3.2.0",
"@navikt/ds-react": "3.2.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
+3
View File
@@ -198,11 +198,14 @@
"@storybook/addon-a11y": "7.0.4",
"@storybook/addon-actions": "7.0.4",
"@storybook/addon-essentials": "7.0.4",
"@storybook/addon-interactions": "7.0.4",
"@storybook/addon-storysource": "7.0.4",
"@storybook/addons": "7.0.4",
"@storybook/csf-tools": "7.0.4",
"@storybook/jest": "^0.1.0",
"@storybook/react": "7.0.4",
"@storybook/react-vite": "7.0.4",
"@storybook/testing-library": "^0.1.0",
"@storybook/theming": "7.0.4",
"@typescript-eslint/parser": "^5.41.0",
"@whitespace/storybook-addon-html": "^5.0.3",
+248 -31
View File
@@ -3571,6 +3571,19 @@ __metadata:
languageName: node
linkType: hard
"@jest/types@npm:^27.5.1":
version: 27.5.1
resolution: "@jest/types@npm:27.5.1"
dependencies:
"@types/istanbul-lib-coverage": ^2.0.0
"@types/istanbul-reports": ^3.0.0
"@types/node": "*"
"@types/yargs": ^16.0.0
chalk: ^4.0.0
checksum: d1f43cc946d87543ddd79d49547aab2399481d34025d5c5f2025d3d99c573e1d9832fa83cef25e9d9b07a8583500229d15bbb07b8e233d127d911d133e2f14b1
languageName: node
linkType: hard
"@jest/types@npm:^29.4.1":
version: 29.4.1
resolution: "@jest/types@npm:29.4.1"
@@ -3885,7 +3898,7 @@ __metadata:
languageName: node
linkType: hard
"@navikt/aksel-icons@^3.0.1, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
"@navikt/aksel-icons@^3.1.3, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
version: 0.0.0-use.local
resolution: "@navikt/aksel-icons@workspace:@navikt/aksel-icons"
dependencies:
@@ -3912,7 +3925,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@navikt/aksel@workspace:@navikt/aksel"
dependencies:
"@navikt/ds-css": 3.0.1
"@navikt/ds-css": 3.1.3
"@types/inquirer": ^9.0.3
"@types/jest": ^29.0.0
axios: 1.3.6
@@ -3936,7 +3949,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-codemod@^3.0.1, @navikt/ds-codemod@workspace:@navikt/codemod":
"@navikt/ds-codemod@^3.1.3, @navikt/ds-codemod@workspace:@navikt/codemod":
version: 0.0.0-use.local
resolution: "@navikt/ds-codemod@workspace:@navikt/codemod"
dependencies:
@@ -3963,7 +3976,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css-internal@^3.0.1, @navikt/ds-css-internal@workspace:@navikt/internal/css":
"@navikt/ds-css-internal@^3.1.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:
@@ -3974,11 +3987,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css@3.0.1, @navikt/ds-css@^3.0.1, @navikt/ds-css@workspace:@navikt/core/css":
"@navikt/ds-css@3.1.3, @navikt/ds-css@^3.1.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": ^3.0.1
"@navikt/ds-tokens": ^3.1.3
cssnano: 6.0.0
fast-glob: 3.2.11
lodash: 4.17.21
@@ -3991,7 +4004,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-icons@^3.0.1, @navikt/ds-icons@workspace:@navikt/icons":
"@navikt/ds-icons@^3.1.3, @navikt/ds-icons@workspace:@navikt/icons":
version: 0.0.0-use.local
resolution: "@navikt/ds-icons@workspace:@navikt/icons"
dependencies:
@@ -4027,8 +4040,8 @@ __metadata:
"@babel/preset-env": 7.19.4
"@babel/preset-react": 7.18.6
"@babel/preset-typescript": 7.18.6
"@navikt/ds-icons": ^3.0.1
"@navikt/ds-react": ^3.0.1
"@navikt/ds-icons": ^3.1.3
"@navikt/ds-react": ^3.1.3
"@rollup/plugin-babel": 6.0.2
"@rollup/plugin-commonjs": 23.0.2
"@rollup/plugin-node-resolve": ^15.0.1
@@ -4053,12 +4066,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react-internal@^3.0.1, @navikt/ds-react-internal@workspace:@navikt/internal/react":
"@navikt/ds-react-internal@^3.1.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/aksel-icons": ^3.0.1
"@navikt/ds-react": ^3.0.1
"@navikt/aksel-icons": ^3.1.3
"@navikt/ds-react": ^3.1.3
clsx: ^1.1.1
concurrently: 7.2.1
copy-to-clipboard: ^3.3.1
@@ -4074,12 +4087,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react@3.0.1, @navikt/ds-react@^3.0.1, @navikt/ds-react@workspace:@navikt/core/react":
"@navikt/ds-react@3.1.3, @navikt/ds-react@^3.1.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": 0.17.0
"@navikt/aksel-icons": ^3.0.1
"@navikt/aksel-icons": ^3.1.3
"@radix-ui/react-tabs": 1.0.0
"@radix-ui/react-toggle-group": 1.0.0
"@testing-library/dom": 8.13.0
@@ -4115,11 +4128,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tailwind@^3.0.1, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
"@navikt/ds-tailwind@^3.1.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": ^3.0.1
"@navikt/ds-tokens": ^3.1.3
"@types/jest": ^29.0.0
color: 4.2.3
jest: ^29.0.0
@@ -4130,7 +4143,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tokens@^3.0.1, @navikt/ds-tokens@workspace:@navikt/core/tokens":
"@navikt/ds-tokens@^3.1.3, @navikt/ds-tokens@workspace:@navikt/core/tokens":
version: 0.0.0-use.local
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
dependencies:
@@ -5552,6 +5565,35 @@ __metadata:
languageName: node
linkType: hard
"@storybook/addon-interactions@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/addon-interactions@npm:7.0.4"
dependencies:
"@storybook/client-logger": 7.0.4
"@storybook/components": 7.0.4
"@storybook/core-common": 7.0.4
"@storybook/core-events": 7.0.4
"@storybook/global": ^5.0.0
"@storybook/instrumenter": 7.0.4
"@storybook/manager-api": 7.0.4
"@storybook/preview-api": 7.0.4
"@storybook/theming": 7.0.4
"@storybook/types": 7.0.4
jest-mock: ^27.0.6
polished: ^4.2.2
ts-dedent: ^2.2.0
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
react:
optional: true
react-dom:
optional: true
checksum: cce4e214d3f37e7ee4fc62f848aea80462965ab549a9cd626fb356b798ed5e11ac5cd84f2b8371f71f039350ce86ff0dfe81a1fa0a32c08cea6bb98410f40e96
languageName: node
linkType: hard
"@storybook/addon-measure@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/addon-measure@npm:7.0.4"
@@ -5782,6 +5824,20 @@ __metadata:
languageName: node
linkType: hard
"@storybook/channel-postmessage@npm:7.0.10":
version: 7.0.10
resolution: "@storybook/channel-postmessage@npm:7.0.10"
dependencies:
"@storybook/channels": 7.0.10
"@storybook/client-logger": 7.0.10
"@storybook/core-events": 7.0.10
"@storybook/global": ^5.0.0
qs: ^6.10.0
telejson: ^7.0.3
checksum: 5fe13e6be29ca1a1ec67f2b0f838e837d5ed7b386dfc1a7007bef071822854b9e4fe7153da3b679de32a0644d66fb5f1b1c5e095140d24ed1457bb4b8deb8507
languageName: node
linkType: hard
"@storybook/channel-postmessage@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/channel-postmessage@npm:7.0.4"
@@ -5808,6 +5864,13 @@ __metadata:
languageName: node
linkType: hard
"@storybook/channels@npm:7.0.10":
version: 7.0.10
resolution: "@storybook/channels@npm:7.0.10"
checksum: 6aed7cc0ef8ef3f398112c79ed4eb61c8b6ba4bbb7ac29125f9dd2e3ccf7f0d13cca0e91ca237c7464e32fffd6797ce1ac96dfe25ea8666dd0af612340ee7d2a
languageName: node
linkType: hard
"@storybook/channels@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/channels@npm:7.0.4"
@@ -5864,6 +5927,15 @@ __metadata:
languageName: node
linkType: hard
"@storybook/client-logger@npm:7.0.10, @storybook/client-logger@npm:^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0":
version: 7.0.10
resolution: "@storybook/client-logger@npm:7.0.10"
dependencies:
"@storybook/global": ^5.0.0
checksum: 6a1824476bc49304e0d6274c6f53c70a018e390430accfd942a5e288a1d13be7e4851c8e8a9cde5535bac711c42c6531739a6eb36d878b388e45fe498709f3ef
languageName: node
linkType: hard
"@storybook/client-logger@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/client-logger@npm:7.0.4"
@@ -5950,6 +6022,13 @@ __metadata:
languageName: node
linkType: hard
"@storybook/core-events@npm:7.0.10":
version: 7.0.10
resolution: "@storybook/core-events@npm:7.0.10"
checksum: 4bc6f35f763524aabc3d41307be427049dc93562cfb1ff79a0788fba8268c29b6438b1691e9bfecd17206a6f4e5705dad2f3b30ebf7d2f89376290139babc044
languageName: node
linkType: hard
"@storybook/core-events@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/core-events@npm:7.0.4"
@@ -6065,6 +6144,15 @@ __metadata:
languageName: node
linkType: hard
"@storybook/expect@npm:storybook-jest":
version: 27.5.2-0
resolution: "@storybook/expect@npm:27.5.2-0"
dependencies:
"@types/jest": ">=26.0.0"
checksum: 09738a8f8e0b9d3d5a909c80ce0c101080cf376316ceca1f3820e88877d6b5ef92abd847b4c4a4e9687c43c2168a6e3e8cdd74947b6af622688797f74cf523df
languageName: node
linkType: hard
"@storybook/global@npm:^5.0.0":
version: 5.0.0
resolution: "@storybook/global@npm:5.0.0"
@@ -6072,6 +6160,44 @@ __metadata:
languageName: node
linkType: hard
"@storybook/instrumenter@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/instrumenter@npm:7.0.4"
dependencies:
"@storybook/channels": 7.0.4
"@storybook/client-logger": 7.0.4
"@storybook/core-events": 7.0.4
"@storybook/global": ^5.0.0
"@storybook/preview-api": 7.0.4
checksum: d5f22fcea3efefd6bb0523c3164ffb7f0287c89a4f6485ac8165658d35b699d6665c964ba01fd3f0dff0938913e6c0b08341796acc9d3fe21e63ebd441147bd9
languageName: node
linkType: hard
"@storybook/instrumenter@npm:^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0":
version: 7.0.10
resolution: "@storybook/instrumenter@npm:7.0.10"
dependencies:
"@storybook/channels": 7.0.10
"@storybook/client-logger": 7.0.10
"@storybook/core-events": 7.0.10
"@storybook/global": ^5.0.0
"@storybook/preview-api": 7.0.10
checksum: c4687c61e30bd3b16652f0ba09638f0ae0b39ffc6eeef629ec17bc0b66ce819c3fa5dedba0a0832d3ae79a1ab1bc1bc9d8dd807c69b3a0fb246592b5a4cffee0
languageName: node
linkType: hard
"@storybook/jest@npm:^0.1.0":
version: 0.1.0
resolution: "@storybook/jest@npm:0.1.0"
dependencies:
"@storybook/expect": storybook-jest
"@storybook/instrumenter": ^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0
"@testing-library/jest-dom": ^5.16.2
jest-mock: ^27.3.0
checksum: 74a4b9dc0ce921f72c2f4fbba053e4a4c84a6a16d07406492a26733f55438229197e547364d0848ac3df38ab5ce9e20829029196d376a267033d8e75904ab611
languageName: node
linkType: hard
"@storybook/manager-api@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/manager-api@npm:7.0.4"
@@ -6131,6 +6257,29 @@ __metadata:
languageName: node
linkType: hard
"@storybook/preview-api@npm:7.0.10":
version: 7.0.10
resolution: "@storybook/preview-api@npm:7.0.10"
dependencies:
"@storybook/channel-postmessage": 7.0.10
"@storybook/channels": 7.0.10
"@storybook/client-logger": 7.0.10
"@storybook/core-events": 7.0.10
"@storybook/csf": ^0.1.0
"@storybook/global": ^5.0.0
"@storybook/types": 7.0.10
"@types/qs": ^6.9.5
dequal: ^2.0.2
lodash: ^4.17.21
memoizerific: ^1.11.3
qs: ^6.10.0
synchronous-promise: ^2.0.15
ts-dedent: ^2.0.0
util-deprecate: ^1.0.2
checksum: 04063b650ae4de687b368de0fbec62b1acddadcedddd70ce471b0dd7819bd574af965834985133a7b6a8409dbdf4196b1206d84ee71737ed4abc0c7c01ed1612
languageName: node
linkType: hard
"@storybook/preview-api@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/preview-api@npm:7.0.4"
@@ -6273,6 +6422,19 @@ __metadata:
languageName: node
linkType: hard
"@storybook/testing-library@npm:^0.1.0":
version: 0.1.0
resolution: "@storybook/testing-library@npm:0.1.0"
dependencies:
"@storybook/client-logger": ^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0
"@storybook/instrumenter": ^7.0.0-beta.0 || ^7.0.0-rc.0 || ^7.0.0
"@testing-library/dom": ^8.3.0
"@testing-library/user-event": ^13.2.1
ts-dedent: ^2.2.0
checksum: a413110dafe80f8fe64da912fddb653bc3c695c94bd023b8cb918e519e9f94119bae559909bfb8ad229041a4f17a12b33425c61572270702c116d0b727b4d4ba
languageName: node
linkType: hard
"@storybook/theming@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/theming@npm:7.0.4"
@@ -6288,6 +6450,18 @@ __metadata:
languageName: node
linkType: hard
"@storybook/types@npm:7.0.10":
version: 7.0.10
resolution: "@storybook/types@npm:7.0.10"
dependencies:
"@storybook/channels": 7.0.10
"@types/babel__core": ^7.0.0
"@types/express": ^4.7.0
file-system-cache: ^2.0.0
checksum: c6ce373863c8c33f8a2e1409b6452934762f3e89b152952f558e1970e25c8b9dd32a5f71a239ca483736bd5ecc2b265bec413dada23349791dac6ace532dd11b
languageName: node
linkType: hard
"@storybook/types@npm:7.0.4":
version: 7.0.4
resolution: "@storybook/types@npm:7.0.4"
@@ -6658,7 +6832,7 @@ __metadata:
languageName: node
linkType: hard
"@testing-library/dom@npm:^8.5.0":
"@testing-library/dom@npm:^8.3.0, @testing-library/dom@npm:^8.5.0":
version: 8.20.0
resolution: "@testing-library/dom@npm:8.20.0"
dependencies:
@@ -6674,7 +6848,7 @@ __metadata:
languageName: node
linkType: hard
"@testing-library/jest-dom@npm:^5.16.0":
"@testing-library/jest-dom@npm:^5.16.0, @testing-library/jest-dom@npm:^5.16.2":
version: 5.16.5
resolution: "@testing-library/jest-dom@npm:5.16.5"
dependencies:
@@ -6705,6 +6879,17 @@ __metadata:
languageName: node
linkType: hard
"@testing-library/user-event@npm:^13.2.1":
version: 13.5.0
resolution: "@testing-library/user-event@npm:13.5.0"
dependencies:
"@babel/runtime": ^7.12.5
peerDependencies:
"@testing-library/dom": ">=7.21.4"
checksum: 16319de685fbb7008f1ba667928f458b2d08196918002daca56996de80ef35e6d9de26e9e1ece7d00a004692b95a597cf9142fff0dc53f2f51606a776584f549
languageName: node
linkType: hard
"@testing-library/user-event@npm:^14.2.0":
version: 14.4.3
resolution: "@testing-library/user-event@npm:14.4.3"
@@ -7115,6 +7300,16 @@ __metadata:
languageName: node
linkType: hard
"@types/jest@npm:>=26.0.0":
version: 29.5.1
resolution: "@types/jest@npm:29.5.1"
dependencies:
expect: ^29.0.0
pretty-format: ^29.0.0
checksum: 0a22491dec86333c0e92b897be2c809c922a7b2b0aa5604ac369810d6b2360908b4a3f2c6892e8a237a54fa1f10ecefe0e823ec5fcb7915195af4dfe88d2197e
languageName: node
linkType: hard
"@types/jscodeshift@npm:0.11.5":
version: 0.11.5
resolution: "@types/jscodeshift@npm:0.11.5"
@@ -7526,6 +7721,15 @@ __metadata:
languageName: node
linkType: hard
"@types/yargs@npm:^16.0.0":
version: 16.0.5
resolution: "@types/yargs@npm:16.0.5"
dependencies:
"@types/yargs-parser": "*"
checksum: 22697f7cc8aa32dcc10981a87f035e183303a58351c537c81fb450270d5c494b1d918186210e445b0eb2e4a8b34a8bda2a595f346bdb1c9ed2b63d193cb00430
languageName: node
linkType: hard
"@types/yargs@npm:^17.0.8":
version: 17.0.22
resolution: "@types/yargs@npm:17.0.22"
@@ -8093,15 +8297,15 @@ __metadata:
version: 0.0.0-use.local
resolution: "aksel.nav.no@workspace:aksel.nav.no"
dependencies:
"@navikt/aksel-icons": ^3.0.1
"@navikt/ds-codemod": ^3.0.1
"@navikt/ds-css": ^3.0.1
"@navikt/ds-css-internal": ^3.0.1
"@navikt/ds-icons": ^3.0.1
"@navikt/ds-react": ^3.0.1
"@navikt/ds-react-internal": ^3.0.1
"@navikt/ds-tailwind": ^3.0.1
"@navikt/ds-tokens": ^3.0.1
"@navikt/aksel-icons": ^3.1.3
"@navikt/ds-codemod": ^3.1.3
"@navikt/ds-css": ^3.1.3
"@navikt/ds-css-internal": ^3.1.3
"@navikt/ds-icons": ^3.1.3
"@navikt/ds-react": ^3.1.3
"@navikt/ds-react-internal": ^3.1.3
"@navikt/ds-tailwind": ^3.1.3
"@navikt/ds-tokens": ^3.1.3
prettier-plugin-tailwindcss: ^0.2.3
languageName: unknown
linkType: soft
@@ -8115,11 +8319,14 @@ __metadata:
"@storybook/addon-a11y": 7.0.4
"@storybook/addon-actions": 7.0.4
"@storybook/addon-essentials": 7.0.4
"@storybook/addon-interactions": 7.0.4
"@storybook/addon-storysource": 7.0.4
"@storybook/addons": 7.0.4
"@storybook/csf-tools": 7.0.4
"@storybook/jest": ^0.1.0
"@storybook/react": 7.0.4
"@storybook/react-vite": 7.0.4
"@storybook/testing-library": ^0.1.0
"@storybook/theming": 7.0.4
"@typescript-eslint/parser": ^5.41.0
"@whitespace/storybook-addon-html": ^5.0.3
@@ -16662,6 +16869,16 @@ __metadata:
languageName: node
linkType: hard
"jest-mock@npm:^27.0.6, jest-mock@npm:^27.3.0":
version: 27.5.1
resolution: "jest-mock@npm:27.5.1"
dependencies:
"@jest/types": ^27.5.1
"@types/node": "*"
checksum: f5b5904bb1741b4a1687a5f492535b7b1758dc26534c72a5423305f8711292e96a601dec966df81bb313269fb52d47227e29f9c2e08324d79529172f67311be0
languageName: node
linkType: hard
"jest-mock@npm:^29.4.1":
version: 29.4.1
resolution: "jest-mock@npm:29.4.1"
@@ -23123,8 +23340,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "shadow-dom@workspace:examples/shadow-dom"
dependencies:
"@navikt/ds-css": 3.0.1
"@navikt/ds-react": 3.0.1
"@navikt/ds-css": 3.1.3
"@navikt/ds-react": 3.1.3
"@types/react": ^18.0.0
"@types/react-dom": ^18.0.0
"@vitejs/plugin-react": ^2.1.0
@@ -24854,7 +25071,7 @@ __metadata:
languageName: node
linkType: hard
"ts-dedent@npm:^2.0.0":
"ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0":
version: 2.2.0
resolution: "ts-dedent@npm:2.2.0"
checksum: 93ed8f7878b6d5ed3c08d99b740010eede6bccfe64bce61c5a4da06a2c17d6ddbb80a8c49c2d15251de7594a4f93ffa21dd10e7be75ef66a4dc9951b4a94e2af