mirror of
https://github.com/navikt/aksel.git
synced 2026-10-15 10:12:03 +00:00
Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd14eb272e | ||
|
|
022d3a6a6f | ||
|
|
fcbd614a34 | ||
|
|
0a9aa6d3a1 | ||
|
|
926437f06f | ||
|
|
288456a460 | ||
|
|
61f6b62c9e | ||
|
|
dc9ffdebaf | ||
|
|
c80cb199a1 | ||
|
|
5ec431456e | ||
|
|
9e0af943a1 | ||
|
|
9ed31d5401 | ||
|
|
5248625027 | ||
|
|
f62b9a6f7b | ||
|
|
c07dd59399 | ||
|
|
88e2c2b2fe | ||
|
|
924c21365b | ||
|
|
9e1b0ab1d1 | ||
|
|
9c4d41e4c8 | ||
|
|
16e141a624 | ||
|
|
08be6c0e8b | ||
|
|
becb01d429 |
No files matched your search
@@ -20,10 +20,22 @@ html {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
:root,
|
||||
[data-theme="light"] {
|
||||
--navds-shadow-focus: 0 0 0 3px var(--navds-semantic-color-focus);
|
||||
|
||||
color: var(--navds-semantic-color-text);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--navds-shadow-focus: var(--navds-shadow-focus-inverted);
|
||||
|
||||
color: var(--navds-semantic-color-text-inverted);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--navds-font-family);
|
||||
line-height: 1.333;
|
||||
color: var(--navds-semantic-color-text);
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
:root {
|
||||
:root,
|
||||
[data-theme="light"] {
|
||||
/* Primary */
|
||||
--navds-button-color-primary-text: var(--navds-semantic-color-text-inverted);
|
||||
--navds-button-color-primary-border-focus: var(
|
||||
@@ -19,7 +20,7 @@
|
||||
--navds-semantic-color-interaction-primary
|
||||
);
|
||||
--navds-button-color-secondary-text-hover: var(
|
||||
--navds-semantic-color-text-inverted
|
||||
--navds-semantic-color-interaction-primary
|
||||
);
|
||||
--navds-button-color-secondary-text-active: var(
|
||||
--navds-semantic-color-text-inverted
|
||||
@@ -34,7 +35,7 @@
|
||||
--navds-semantic-color-component-background-light
|
||||
);
|
||||
--navds-button-color-secondary-background-hover: var(
|
||||
--navds-semantic-color-interaction-primary-hover
|
||||
--navds-semantic-color-interaction-primary-hover-subtle
|
||||
);
|
||||
--navds-button-color-secondary-background-active: var(
|
||||
--navds-semantic-color-interaction-primary-selected
|
||||
@@ -47,8 +48,8 @@
|
||||
--navds-button-color-tertiary-text-active: var(
|
||||
--navds-semantic-color-text-inverted
|
||||
);
|
||||
--navds-button-color-tertiary-border-hover: var(
|
||||
--navds-semantic-color-interaction-primary
|
||||
--navds-button-color-tertiary-background-hover: var(
|
||||
--navds-semantic-color-interaction-primary-hover-subtle
|
||||
);
|
||||
--navds-button-color-tertiary-border-focus: var(
|
||||
--navds-semantic-color-interaction-primary
|
||||
@@ -80,6 +81,39 @@
|
||||
--navds-loader-color-on-button-foreground: currentColor;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
/* Primary */
|
||||
--navds-button-color-primary-text: var(--navds-semantic-color-text);
|
||||
--navds-button-color-primary-border-focus: var(--navds-semantic-color-text);
|
||||
--navds-button-color-primary-background: var(--navds-global-color-blue-200);
|
||||
--navds-button-color-primary-background-hover: var(
|
||||
--navds-global-color-blue-300
|
||||
);
|
||||
--navds-button-color-primary-background-active: var(
|
||||
--navds-global-color-blue-400
|
||||
);
|
||||
|
||||
/* Secondary */
|
||||
--navds-button-color-secondary-text: var(--navds-global-color-blue-200);
|
||||
--navds-button-color-secondary-text-hover: var(--navds-global-color-blue-200);
|
||||
--navds-button-color-secondary-text-active: var(
|
||||
--navds-global-color-blue-200
|
||||
);
|
||||
--navds-button-color-secondary-border: var(--navds-global-color-blue-200);
|
||||
--navds-button-color-secondary-border-focus-active-hover: var(
|
||||
--navds-semantic-color-text
|
||||
);
|
||||
--navds-button-color-secondary-background: var(
|
||||
--navds-semantic-color-component-background-inverted
|
||||
);
|
||||
--navds-button-color-secondary-background-hover: var(
|
||||
--navds-global-color-blue-900
|
||||
);
|
||||
--navds-button-color-secondary-background-active: var(
|
||||
--navds-global-color-blue-800
|
||||
);
|
||||
}
|
||||
|
||||
.navds-button {
|
||||
display: inline-flex;
|
||||
cursor: pointer;
|
||||
@@ -165,7 +199,6 @@
|
||||
.navds-button--secondary:hover {
|
||||
color: var(--navds-button-color-secondary-text-hover);
|
||||
background-color: var(--navds-button-color-secondary-background-hover);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-button--secondary:focus {
|
||||
@@ -179,7 +212,6 @@
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navds-button--secondary:focus:hover,
|
||||
.navds-button--secondary:focus:active {
|
||||
box-shadow: inset 0 0 0 1px
|
||||
var(--navds-button-color-secondary-border-focus-active-hover),
|
||||
@@ -202,7 +234,7 @@
|
||||
}
|
||||
|
||||
.navds-button--tertiary:hover {
|
||||
box-shadow: inset 0 0 0 2px var(--navds-button-color-tertiary-border-hover);
|
||||
background-color: var(--navds-button-color-tertiary-background-hover);
|
||||
}
|
||||
|
||||
.navds-button--tertiary:focus {
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
:root {
|
||||
:root,
|
||||
[data-theme="light"] {
|
||||
--navds-search-color-text: var(--navds-semantic-color-text);
|
||||
--navds-search-color-border: var(--navds-semantic-color-border);
|
||||
--navds-search-color-border-hover: var(
|
||||
--navds-semantic-color-interaction-primary
|
||||
);
|
||||
--navds-search-color-clear-hover: var(--navds-global-color-blue-500);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--navds-search-color-text: var(--navds-semantic-color-text-inverted);
|
||||
--navds-search-color-border: var(--navds-semantic-color-border-inverted);
|
||||
--navds-search-color-border-hover: var(--navds-global-color-blue-200);
|
||||
--navds-search-color-clear-hover: var(--navds-global-color-blue-200);
|
||||
}
|
||||
|
||||
.navds-search {
|
||||
@@ -22,22 +32,45 @@
|
||||
}
|
||||
|
||||
.navds-search__input {
|
||||
padding-right: var(--navds-spacing-12);
|
||||
padding-right: var(--navds-spacing-10);
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-search__input {
|
||||
padding-right: var(--navds-spacing-8);
|
||||
}
|
||||
|
||||
.navds-search__input--simple {
|
||||
padding-left: var(--navds-spacing-11);
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-search__input--simple {
|
||||
padding-left: var(--navds-spacing-7);
|
||||
}
|
||||
|
||||
.navds-search__input:not(.navds-search__input--simple) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-search__input {
|
||||
min-height: 32px;
|
||||
padding: 0.15rem;
|
||||
padding-right: var(--navds-spacing-8);
|
||||
.navds-search__search-icon {
|
||||
position: absolute;
|
||||
left: var(--navds-spacing-3);
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-search__search-icon {
|
||||
left: var(--navds-spacing-2);
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.navds-search__button-clear {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
border-radius: var(--navds-border-radius-medium);
|
||||
color: var(--navds-semantic-color-text);
|
||||
color: var(--navds-search-color-text);
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
top: 50%;
|
||||
@@ -59,7 +92,7 @@
|
||||
}
|
||||
|
||||
.navds-search__button-clear:hover {
|
||||
color: var(--navds-global-color-blue-500);
|
||||
color: var(--navds-search-color-clear-hover);
|
||||
}
|
||||
|
||||
.navds-search__button-clear:focus {
|
||||
@@ -84,13 +117,13 @@
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.navds-search__button-search.navds-button--tertiary {
|
||||
.navds-search__button-search.navds-button--secondary {
|
||||
box-shadow: -1px 0 0 0 var(--navds-search-color-border) inset,
|
||||
0 1px 0 0 var(--navds-search-color-border) inset,
|
||||
0 -1px 0 0 var(--navds-search-color-border) inset;
|
||||
}
|
||||
|
||||
.navds-search__button-search.navds-button--tertiary:hover {
|
||||
.navds-search__button-search.navds-button--secondary:hover {
|
||||
box-shadow: -1px 0 0 0 var(--navds-search-color-border-hover) inset,
|
||||
0 1px 0 0 var(--navds-search-color-border-hover) inset,
|
||||
0 -1px 0 0 var(--navds-search-color-border-hover) inset,
|
||||
@@ -99,21 +132,21 @@
|
||||
}
|
||||
|
||||
.navds-search__wrapper-inner:focus-within
|
||||
+ .navds-search__button-search.navds-button--tertiary:hover {
|
||||
+ .navds-search__button-search.navds-button--secondary:hover {
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
.navds-search__button-search.navds-button--tertiary:focus {
|
||||
.navds-search__button-search.navds-button--secondary:focus {
|
||||
box-shadow: 0 0 0 1px var(--navds-search-color-border) inset,
|
||||
var(--navds-shadow-focus);
|
||||
}
|
||||
|
||||
.navds-search__button-search.navds-button--tertiary:focus:hover {
|
||||
.navds-search__button-search.navds-button--secondary:focus:hover {
|
||||
box-shadow: 0 0 0 1px var(--navds-search-color-border-hover) inset,
|
||||
var(--navds-shadow-focus);
|
||||
}
|
||||
|
||||
.navds-search__button-search.navds-button--tertiary:focus:active {
|
||||
.navds-search__button-search.navds-button--secondary:focus:active {
|
||||
box-shadow: 0 0 0 1px white inset, var(--navds-shadow-focus);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
:root {
|
||||
:root,
|
||||
[data-theme="light"] {
|
||||
--navds-text-field-color-text: var(--navds-semantic-color-text);
|
||||
--navds-text-field-color-background: var(
|
||||
--navds-semantic-color-component-background-light
|
||||
@@ -18,11 +19,24 @@
|
||||
--navds-semantic-color-component-background-alternate
|
||||
);
|
||||
--navds-text-field-color-text-disabled: var(--navds-semantic-color-text);
|
||||
--navds-text-field-color-placeholder-text: var(
|
||||
--navds-semantic-color-text-muted
|
||||
);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--navds-text-field-color-text: var(--navds-semantic-color-text-inverted);
|
||||
--navds-text-field-color-background: var(
|
||||
--navds-semantic-color-component-background-dark
|
||||
);
|
||||
--navds-text-field-color-border: var(--navds-semantic-color-border-inverted);
|
||||
--navds-text-field-color-border-hover: var(--navds-global-color-blue-200);
|
||||
--navds-text-field-color-placeholder-text: var(--navds-global-color-gray-500);
|
||||
}
|
||||
|
||||
.navds-text-field__input {
|
||||
appearance: none;
|
||||
padding: 0.5rem;
|
||||
padding: var(--navds-spacing-2);
|
||||
background-color: var(--navds-text-field-color-background);
|
||||
border-radius: var(--navds-border-radius-medium);
|
||||
border: 1px solid var(--navds-text-field-color-border);
|
||||
@@ -31,7 +45,11 @@
|
||||
color: var(--navds-text-field-color-text);
|
||||
}
|
||||
|
||||
.navds-form-field--small > .navds-text-field__input {
|
||||
.navds-text-field__input::placeholder {
|
||||
color: var(--navds-text-field-color-placeholder-text);
|
||||
}
|
||||
|
||||
.navds-form-field--small .navds-text-field__input {
|
||||
padding: 0 0.25rem;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
@import "pagination.css";
|
||||
@import "popover.css";
|
||||
@import "tag.css";
|
||||
@import "tooltip.css";
|
||||
@import "toggle-group.css";
|
||||
@import "panel.css";
|
||||
@import "link-panel.css";
|
||||
@import "read-more.css";
|
||||
@import "speech-bubble.css";
|
||||
@import "step-indicator.css";
|
||||
@import "stepper.css";
|
||||
@import "table.css";
|
||||
@import "tabs.css";
|
||||
|
||||
/* Navno spesific packages */
|
||||
@import "page-header.css";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "0.16.8",
|
||||
"version": "0.16.14",
|
||||
"private": false,
|
||||
"description": "Css for NAV Designsystem components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -21,7 +21,7 @@
|
||||
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^0.8.4",
|
||||
"@navikt/ds-tokens": "^0.8.6",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.3.6",
|
||||
"postcss-cli": "^8.3.1",
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
.navds-stepper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* Step */
|
||||
.navds-stepper__step {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
padding: calc(2.25rem / 2) 0;
|
||||
display: flex;
|
||||
background: none;
|
||||
border: none;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
color: var(--navds-semantic-color-text);
|
||||
text-decoration: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.navds-stepper__step-number {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
margin-right: var(--navds-spacing-3);
|
||||
border-radius: var(--navds-border-radius-full);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--navds-semantic-color-interaction-primary);
|
||||
box-shadow: inset 0 0 0 2px var(--navds-semantic-color-interaction-primary);
|
||||
background-color: var(--navds-semantic-color-component-background-light);
|
||||
}
|
||||
|
||||
/* Step-states: focus, active, hover */
|
||||
.navds-stepper__step-wrapper:hover
|
||||
> .navds-stepper__step
|
||||
> .navds-stepper__step-number {
|
||||
background-color: var(
|
||||
--navds-semantic-color-interaction-primary-hover-subtle
|
||||
);
|
||||
}
|
||||
|
||||
.navds-stepper__step--active > .navds-stepper__step-number,
|
||||
.navds-stepper__step-wrapper:hover
|
||||
> .navds-stepper__step--active
|
||||
> .navds-stepper__step-number {
|
||||
color: var(--navds-semantic-color-text-inverted);
|
||||
background-color: var(--navds-semantic-color-interaction-primary-selected);
|
||||
box-shadow: inset 0 0 0 2px
|
||||
var(--navds-semantic-color-interaction-primary-selected);
|
||||
}
|
||||
|
||||
.navds-stepper__step:focus {
|
||||
box-shadow: var(--navds-shadow-focus);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.navds-stepper__step--active {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Step label */
|
||||
.navds-stepper__step-label {
|
||||
margin-top: 2px;
|
||||
color: var(--navds-semantic-color-interaction-primary);
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.navds-stepper__step:hover > .navds-stepper__step-label {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.navds-stepper__step--active > .navds-stepper__step-label {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.navds-stepper__step--active:hover > .navds-stepper__step-label {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Step Horizontal Lines */
|
||||
|
||||
.navds-stepper__step-wrapper:not(:last-child) > .navds-stepper__step::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: calc(28px + 8px + (2.25rem / 2));
|
||||
left: 13px;
|
||||
height: calc(100% - 2.75rem);
|
||||
display: block;
|
||||
border-left: 2px solid var(--navds-semantic-color-border-muted);
|
||||
border-radius: var(--navds-border-radius-medium);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
@@ -141,3 +141,80 @@
|
||||
font-size: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.navds-table__expandable-row--open .navds-table__header-cell,
|
||||
.navds-table__expandable-row--open .navds-table__data-cell {
|
||||
border-color: var(--navds-semantic-color-border-muted);
|
||||
}
|
||||
|
||||
.navds-table__expandable-row--open .navds-table__toggle-expand-cell--open {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-cell {
|
||||
padding: 0;
|
||||
width: 56px;
|
||||
}
|
||||
|
||||
.navds-table--small .navds-table__toggle-expand-cell {
|
||||
padding: 0;
|
||||
width: 36px;
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-button {
|
||||
all: unset;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: var(--navds-spacing-4);
|
||||
}
|
||||
|
||||
.navds-table--small .navds-table__toggle-expand-button {
|
||||
padding: var(--navds-spacing-2);
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-button:focus {
|
||||
box-shadow: inset var(--navds-shadow-focus);
|
||||
}
|
||||
|
||||
.navds-table__expandable-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.navds-table--small .navds-table__expandable-icon {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-button:hover .navds-table__expandable-icon,
|
||||
.navds-table__expandable-icon--filled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-button:hover .navds-table__expandable-icon--filled {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.navds-table__toggle-expand-cell--open .navds-table__expandable-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.navds-table__expanded-row-cell {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.navds-table__expanded-row-cell:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.navds-table__expanded-row-collapse {
|
||||
transition: height 250ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border-bottom: 1px solid var(--navds-table-cell-color-border);
|
||||
}
|
||||
|
||||
.navds-table__expanded-row-content {
|
||||
padding: var(--navds-spacing-4) 4.25rem;
|
||||
}
|
||||
|
||||
.navds-table--small .navds-table__expanded-row-content {
|
||||
padding: var(--navds-spacing-2) var(--navds-spacing-12);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
.navds-tabs__tablist-wrapper {
|
||||
box-shadow: inset 0 -1px 0 0 var(--navds-global-color-gray-300);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.navds-tabs__tablist {
|
||||
display: flex;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
scroll-behavior: smooth;
|
||||
-ms-overflow-style: none; /* for Internet Explorer, Edge */
|
||||
scrollbar-width: none; /* for Firefox */
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.navds-tabs__tablist::-webkit-scrollbar {
|
||||
display: none; /* for Chrome, Safari, and Opera */
|
||||
}
|
||||
|
||||
.navds-tabs__scroll-button {
|
||||
padding: var(--navds-spacing-3) var(--navds-spacing-4);
|
||||
width: 44px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navds-tabs__scroll-button--hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.navds-tabs__scroll-button svg {
|
||||
font-size: 1.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.navds-tabs--small .navds-tabs__scroll-button {
|
||||
padding: 0.375rem var(--navds-spacing-4);
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.navds-tabs__tab {
|
||||
min-height: 48px;
|
||||
padding: var(--navds-spacing-3) var(--navds-spacing-4);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--navds-semantic-color-text-muted);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navds-tabs__tab:hover {
|
||||
box-shadow: inset 0 -3px 0 0 var(--navds-global-color-gray-300);
|
||||
}
|
||||
|
||||
.navds-tabs__tab[aria-selected="true"] {
|
||||
box-shadow: inset 0 -3px 0 0 var(--navds-semantic-color-interaction-primary);
|
||||
color: var(--navds-semantic-color-text);
|
||||
}
|
||||
|
||||
.navds-tabs__tab:focus {
|
||||
outline: none;
|
||||
box-shadow: inset var(--navds-shadow-focus);
|
||||
color: var(--navds-semantic-color-text);
|
||||
}
|
||||
|
||||
.navds-tabs__tab-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-tabs__tab-icon--top > .navds-tabs__tab-inner {
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.navds-tabs__tab--small {
|
||||
min-height: 32px;
|
||||
padding: 0.375rem var(--navds-spacing-4);
|
||||
}
|
||||
|
||||
.navds-tabs__tab-icon--top,
|
||||
.navds-tabs__tab--small.navds-tabs__tab-icon--top {
|
||||
padding: var(--navds-spacing-1) var(--navds-spacing-4);
|
||||
}
|
||||
|
||||
.navds-tabs__tab svg,
|
||||
.navds-tabs__tab--small.navds-tabs__tab--icon-only svg,
|
||||
.navds-tabs__tab--small.navds-tabs__tab-icon--top svg {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.navds-tabs__tab--small svg {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.navds-tabs__tab--icon-only svg,
|
||||
.navds-tabs__tab-icon--top svg {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.navds-tabs__tabpanel:focus {
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
@keyframes tooltipFadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.navds-tooltip {
|
||||
z-index: var(--navds-z-index-tooltip);
|
||||
}
|
||||
|
||||
.navds-tooltip__inner {
|
||||
background-color: var(--navds-semantic-color-component-background-inverted);
|
||||
color: var(--navds-semantic-color-text-inverted);
|
||||
border-radius: var(--navds-border-radius-small);
|
||||
padding: 0 var(--navds-spacing-2);
|
||||
align-items: center;
|
||||
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.05))
|
||||
drop-shadow(0 1px 3px rgba(0, 0, 0, 0.1));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation-duration: 0.2s;
|
||||
animation-name: tooltipFadeIn;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.navds-tooltip__arrow {
|
||||
height: 7px;
|
||||
width: 7px;
|
||||
transform: rotate(45deg);
|
||||
z-index: -1;
|
||||
background-color: var(--navds-semantic-color-component-background-inverted);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.navds-tooltip__keys {
|
||||
padding-bottom: var(--navds-spacing-1);
|
||||
display: flex;
|
||||
gap: var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-tooltip__key {
|
||||
font-family: var(--navds-font-family);
|
||||
background-color: var(--navds-global-color-gray-700);
|
||||
color: var(--navds-semantic-color-text-inverted);
|
||||
border-radius: var(--navds-border-radius-small);
|
||||
padding: 0 var(--navds-spacing-1);
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "0.17.11",
|
||||
"version": "0.17.18",
|
||||
"private": false,
|
||||
"description": "NAV designsystem react components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -34,9 +34,11 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "0.6.0",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@navikt/ds-icons": "^0.8.6",
|
||||
"@popperjs/core": "^2.10.1",
|
||||
"@radix-ui/react-tabs": "0.1.5",
|
||||
"@radix-ui/react-toggle-group": "0.1.5",
|
||||
"classnames": "^2.2.6",
|
||||
"react-collapse": "^5.1.0",
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface ConfirmationPanelProps extends Partial<CheckboxProps> {
|
||||
/**
|
||||
* Checkbox label
|
||||
*/
|
||||
label: string;
|
||||
label: React.ReactNode;
|
||||
/**
|
||||
* Checked state for checkbox
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface SelectProps
|
||||
/**
|
||||
* Label for select
|
||||
*/
|
||||
label: string;
|
||||
label: React.ReactNode;
|
||||
/**
|
||||
* If enabled shows the label and description for screenreaders only
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Close } from "@navikt/ds-icons";
|
||||
import { Close, Search as SearchIcon } from "@navikt/ds-icons";
|
||||
import cl from "classnames";
|
||||
import React, {
|
||||
forwardRef,
|
||||
InputHTMLAttributes,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
@@ -59,9 +58,9 @@ export interface SearchProps
|
||||
clearButton?: boolean;
|
||||
/**
|
||||
* Changes button-variant
|
||||
* @default "tertiary"
|
||||
* @default "primary"
|
||||
*/
|
||||
variant?: "tertiary" | "primary";
|
||||
variant?: "primary" | "secondary" | "simple";
|
||||
}
|
||||
|
||||
interface SearchComponent
|
||||
@@ -74,8 +73,8 @@ interface SearchComponent
|
||||
export interface SearchContextProps {
|
||||
disabled?: boolean;
|
||||
size: "medium" | "small";
|
||||
variant?: "tertiary" | "primary";
|
||||
onSearch?: () => void;
|
||||
variant: "primary" | "secondary" | "simple";
|
||||
onSearch: () => void;
|
||||
}
|
||||
|
||||
export const SearchContext = React.createContext<SearchContextProps | null>(
|
||||
@@ -99,7 +98,9 @@ const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
|
||||
clearButton = true,
|
||||
children,
|
||||
onSearch,
|
||||
variant = "tertiary",
|
||||
variant = "primary",
|
||||
defaultValue,
|
||||
onChange,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@@ -107,26 +108,23 @@ const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
|
||||
const mergedRef = mergeRefs([searchRef, ref]);
|
||||
const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
const [controlledValue, setControlledValue] = useState(value ?? "");
|
||||
const [internalValue, setInternalValue] = useState(defaultValue ?? "");
|
||||
|
||||
const handleChange = useCallback(
|
||||
(v: string) => {
|
||||
searchRef.current && value === undefined && setControlledValue(v);
|
||||
props?.onChange?.(v);
|
||||
value === undefined && setInternalValue(v);
|
||||
onChange?.(v);
|
||||
},
|
||||
[props, value]
|
||||
[onChange, value]
|
||||
);
|
||||
|
||||
const handleClear = useCallback(
|
||||
(event: SearchClearEvent) => {
|
||||
onClear?.(event);
|
||||
handleChange("");
|
||||
if (searchRef.current && value === undefined) {
|
||||
searchRef.current.value = "";
|
||||
}
|
||||
searchRef.current && searchRef.current?.focus?.();
|
||||
},
|
||||
[handleChange, onClear, value]
|
||||
[handleChange, onClear]
|
||||
);
|
||||
|
||||
useEventListener(
|
||||
@@ -143,10 +141,6 @@ const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
|
||||
wrapperRef
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
value !== undefined && setControlledValue(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={setWrapperRef}
|
||||
@@ -184,23 +178,27 @@ const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
|
||||
)}
|
||||
<div className="navds-search__wrapper">
|
||||
<div className="navds-search__wrapper-inner">
|
||||
{variant === "simple" && (
|
||||
<SearchIcon aria-hidden className="navds-search__search-icon" />
|
||||
)}
|
||||
<input
|
||||
ref={mergedRef}
|
||||
{...omit(rest, ["size"])}
|
||||
{...inputProps}
|
||||
{...(props.value !== undefined && { value: props.value })}
|
||||
value={value ?? internalValue}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
type="search"
|
||||
role="searchbox"
|
||||
className={cl(
|
||||
className,
|
||||
"navds-search__input",
|
||||
`navds-search__input--${variant}`,
|
||||
"navds-text-field__input",
|
||||
"navds-body-short",
|
||||
`navds-body-${size ?? "medium"}`
|
||||
`navds-body-${size}`
|
||||
)}
|
||||
/>
|
||||
{controlledValue && clearButton && (
|
||||
{(value ?? internalValue) && clearButton && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => handleClear({ trigger: "Click", event: e })}
|
||||
@@ -218,10 +216,10 @@ const Search = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {
|
||||
size,
|
||||
disabled: inputProps.disabled,
|
||||
variant,
|
||||
onSearch: () => onSearch?.(controlledValue),
|
||||
onSearch: () => onSearch?.(value ?? internalValue),
|
||||
}}
|
||||
>
|
||||
{children ? children : <SearchButton />}
|
||||
{children ? children : variant !== "simple" && <SearchButton />}
|
||||
</SearchContext.Provider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@ const SearchButton: SearchButtonType = forwardRef(
|
||||
{...rest}
|
||||
ref={ref}
|
||||
size={size}
|
||||
variant={variant}
|
||||
variant={variant === "secondary" ? "secondary" : "primary"}
|
||||
className={cl("navds-search__button-search", className)}
|
||||
disabled={context?.disabled ?? disabled}
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import React from "react";
|
||||
import { Heading } from "../..";
|
||||
import { Search } from "..";
|
||||
|
||||
export default {
|
||||
title: "ds-react/form/search",
|
||||
component: Search,
|
||||
} as Meta;
|
||||
|
||||
export const LightTheme = () => (
|
||||
<div
|
||||
style={{ maxWidth: 400, display: "flex", flexDirection: "column", gap: 16 }}
|
||||
>
|
||||
<Heading size="xlarge">Search</Heading>
|
||||
<Heading level="2" size="large">
|
||||
size medium
|
||||
</Heading>
|
||||
<Search label="hidden label" placeholder="Søk" />
|
||||
<Search label="hidden label" variant="secondary" defaultValue="dagpenger" />
|
||||
<Search label="hidden label" variant="simple" placeholder="Søk" />
|
||||
<Search label="with label" hideLabel={false} />
|
||||
|
||||
<Heading level="2" size="large">
|
||||
size small
|
||||
</Heading>
|
||||
<Search label="hidden label" size="small" placeholder="Søk" />
|
||||
<Search
|
||||
label="hidden label"
|
||||
variant="secondary"
|
||||
size="small"
|
||||
defaultValue="dagpenger"
|
||||
/>
|
||||
<Search
|
||||
label="hidden label"
|
||||
variant="simple"
|
||||
size="small"
|
||||
placeholder="Søk"
|
||||
/>
|
||||
<Search label="with label" hideLabel={false} size="small" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const DarkTheme = () => (
|
||||
<div data-theme="dark">
|
||||
<LightTheme />
|
||||
</div>
|
||||
);
|
||||
|
||||
DarkTheme.parameters = {
|
||||
backgrounds: { default: "dark" },
|
||||
};
|
||||
@@ -21,11 +21,18 @@ export const All = () => {
|
||||
<h1>Search</h1>
|
||||
|
||||
<Search label="Søk alle sider om X og Y" onSearch={console.log}></Search>
|
||||
<h2>Primary search</h2>
|
||||
<h2>Secondary</h2>
|
||||
<Search
|
||||
label="Søk alle sider om X og Y"
|
||||
onSearch={console.log}
|
||||
variant="primary"
|
||||
variant="secondary"
|
||||
></Search>
|
||||
|
||||
<h2>No button</h2>
|
||||
<Search
|
||||
label="Søk alle sider om X og Y"
|
||||
onSearch={console.log}
|
||||
variant="simple"
|
||||
></Search>
|
||||
|
||||
<h2>Search small</h2>
|
||||
@@ -42,7 +49,7 @@ export const All = () => {
|
||||
description="Beskrivelse av søket"
|
||||
size="small"
|
||||
hideLabel
|
||||
variant="primary"
|
||||
variant="secondary"
|
||||
>
|
||||
<Search.Button />
|
||||
</Search>
|
||||
|
||||
@@ -16,9 +16,12 @@ export * from "./popover";
|
||||
export * from "./read-more";
|
||||
export * from "./speech-bubble";
|
||||
export * from "./step-indicator";
|
||||
export * from "./stepper";
|
||||
export * from "./tag";
|
||||
export * from "./toggle-group";
|
||||
export * from "./table";
|
||||
export * from "./tabs";
|
||||
export * from "./tooltip";
|
||||
export * from "./typography";
|
||||
export * from "./util";
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ const ReadMore = forwardRef<HTMLButtonElement, ReadMoreProps>(
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
{...rest}
|
||||
className={cl(
|
||||
"navds-read-more",
|
||||
|
||||
@@ -28,7 +28,7 @@ Du må nå selv styre state med `activeStep` og `onStepChange`.
|
||||
|
||||
## responsive
|
||||
|
||||
Bruk `responsive`-prop for å skjule labels med en gang StepIndicator begynner å overlfowe.
|
||||
Bruk `responsive`-prop for å skjule labels med en gang StepIndicator begynner å overflowe.
|
||||
|
||||
```jsx
|
||||
<StepIndicator
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import cl from "classnames";
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import { StepperContext } from ".";
|
||||
import { Label, OverridableComponent } from "..";
|
||||
|
||||
export interface StepperStepProps
|
||||
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
/**
|
||||
* Text content under indicator
|
||||
*/
|
||||
children: string;
|
||||
/**
|
||||
* Handled by Stepper
|
||||
*/
|
||||
index?: number;
|
||||
}
|
||||
|
||||
export interface StepperStepType
|
||||
extends OverridableComponent<StepperStepProps, HTMLAnchorElement> {}
|
||||
|
||||
const StepComponent: OverridableComponent<
|
||||
StepperStepProps,
|
||||
HTMLAnchorElement
|
||||
> = forwardRef(
|
||||
({ className, children, as: Component = "a", index = 0, ...rest }, ref) => {
|
||||
const context = useContext(StepperContext);
|
||||
if (context === null) {
|
||||
console.error(
|
||||
"<StepIndicator.Step> has to be used within an <StepIndicator>"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
const activeStep = context.activeStep === index;
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
aria-current={Boolean(activeStep)}
|
||||
ref={ref}
|
||||
className={cl("navds-stepper__step", className, {
|
||||
"navds-stepper__step--active": activeStep,
|
||||
})}
|
||||
onClick={(e) => {
|
||||
context.onStepChange(index);
|
||||
rest?.onClick?.(e);
|
||||
}}
|
||||
>
|
||||
<Label className="navds-stepper__step-number" as="span">
|
||||
{activeStep ? `${index + 1}` : index + 1}
|
||||
</Label>
|
||||
<Label className="navds-stepper__step-label">{children}</Label>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const Step = StepComponent as StepperStepType;
|
||||
|
||||
export default Step;
|
||||
@@ -0,0 +1,73 @@
|
||||
import React, { createContext, forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import Step, { StepperStepProps, StepperStepType } from "./Step";
|
||||
|
||||
export interface StepperProps extends React.HTMLAttributes<HTMLOListElement> {
|
||||
/**
|
||||
* <Stepper.Step /> elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Adds classname to wrapper
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Current active step index
|
||||
*/
|
||||
activeStep: number;
|
||||
/**
|
||||
* Callback for clicked step index
|
||||
*/
|
||||
onStepChange?: (step: number) => void;
|
||||
}
|
||||
|
||||
interface StepperComponent
|
||||
extends React.ForwardRefExoticComponent<
|
||||
StepperProps & React.RefAttributes<HTMLOListElement>
|
||||
> {
|
||||
Step: StepperStepType;
|
||||
}
|
||||
|
||||
interface StepperContextProps {
|
||||
activeStep: number;
|
||||
onStepChange: (step: number) => void;
|
||||
lastIndex: number;
|
||||
}
|
||||
|
||||
export const StepperContext = createContext<StepperContextProps | null>(null);
|
||||
|
||||
const Stepper: StepperComponent = forwardRef<HTMLOListElement, StepperProps>(
|
||||
(
|
||||
{ children, className, activeStep, onStepChange = () => {}, ...rest },
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<ol {...rest} ref={ref} className={cl("navds-stepper", className)}>
|
||||
<StepperContext.Provider
|
||||
value={{
|
||||
activeStep,
|
||||
onStepChange,
|
||||
lastIndex: React.Children.count(children),
|
||||
}}
|
||||
>
|
||||
{React.Children.map(children, (step, index) => {
|
||||
return (
|
||||
<li
|
||||
className={cl("navds-stepper__step-wrapper")}
|
||||
key={index + (children?.toString?.() ?? "")}
|
||||
>
|
||||
{React.isValidElement<StepperStepProps>(step)
|
||||
? React.cloneElement(step, { ...step.props, index })
|
||||
: step}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</StepperContext.Provider>
|
||||
</ol>
|
||||
);
|
||||
}
|
||||
) as StepperComponent;
|
||||
|
||||
Stepper.Step = Step;
|
||||
|
||||
export default Stepper;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as Stepper } from "./Stepper";
|
||||
export * from "./Stepper";
|
||||
@@ -0,0 +1,28 @@
|
||||
import React, { useState } from "react";
|
||||
import { Stepper } from "..";
|
||||
|
||||
export const Example = (props) => {
|
||||
const [activeStep, setActiveStep] = useState(
|
||||
props.initialStep ? props.initialStep : 1
|
||||
);
|
||||
|
||||
const anchorProps = {
|
||||
href: "",
|
||||
onClick: (e) => e.preventDefault(),
|
||||
};
|
||||
|
||||
return (
|
||||
<Stepper {...props} activeStep={activeStep} onStepChange={setActiveStep}>
|
||||
<Stepper.Step {...anchorProps}>Start</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>
|
||||
Sunt deserunt qui sit sunt culpa nisi
|
||||
</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>
|
||||
Nulla nisi pariatur nulla cupidatat elit.
|
||||
</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>
|
||||
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
||||
</Stepper.Step>
|
||||
</Stepper>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import { Meta, Canvas } from "@storybook/addon-docs";
|
||||
import { Stepper } from "..";
|
||||
import { Example } from "./Example";
|
||||
|
||||
<Meta title="ds-react/stepper/intro" />
|
||||
|
||||
# Hvordan ta i bruk Stepper
|
||||
|
||||
Stepper er det vertikale søskenet til step-indicator/stegindikator.
|
||||
Du må nå selv styre state med `activeStep` og `onStepChange`.
|
||||
|
||||
## Eksempel
|
||||
|
||||
```jsx
|
||||
<Stepper activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
|
||||
<Stepper.Step href="" onClick={(e) => e.preventDefault()}>
|
||||
Start
|
||||
</Stepper.Step>
|
||||
<Stepper.Step href="" onClick={(e) => e.preventDefault()}>
|
||||
Sunt deserunt qui sit sunt culpa nisi
|
||||
</Stepper.Step>
|
||||
<Stepper.Step href="" onClick={(e) => e.preventDefault()}>
|
||||
Nulla nisi pariatur nulla cupidatat elit.
|
||||
</Stepper.Step>
|
||||
<Stepper.Step href="" onClick={(e) => e.preventDefault()}>
|
||||
Nulla laborum proident consequat laborum elit et dolore ut sunt.
|
||||
</Stepper.Step>
|
||||
</Stepper>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<Example />
|
||||
</Canvas>
|
||||
|
||||
## Override tags
|
||||
|
||||
`Stepper.Step` er implementert med Overridable-component noe som gjør at du kan endre taggen til
|
||||
det du vil med `as`-prop. Merk at Step åakkes inn i en `<li>`-wrapper for tilgjengelighet.
|
||||
|
||||
```jsx
|
||||
<Stepper activeStep={activeStep} onStepChange={(x) => setActiveStep(x)}>
|
||||
{/* <button> er default */}
|
||||
<Stepper.Step
|
||||
href=""
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>{`Dette er default, et <a>-element`}</Stepper.Step>
|
||||
<Stepper.Step as="button">{`Dette er et <button>-element`}</Stepper.Step>
|
||||
<Stepper.Step as="span">{`Dette er et <span>-element`}</Stepper.Step>
|
||||
</Stepper>
|
||||
```
|
||||
|
||||
<Canvas>
|
||||
<Stepper activeStep={1} onStepChange={console.log}>
|
||||
<Stepper.Step
|
||||
href=""
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>{`Dette er default, et <a>-element`}</Stepper.Step>
|
||||
<Stepper.Step as="button">{`Dette er et <button>-element`}</Stepper.Step>
|
||||
<Stepper.Step as="span">{`Dette er et <span>-element`}</Stepper.Step>
|
||||
</Stepper>
|
||||
</Canvas>
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import React, { useState } from "react";
|
||||
import Stepper from "../Stepper";
|
||||
import { BodyLong } from "../../typography";
|
||||
|
||||
export default {
|
||||
title: "ds-react/stepper",
|
||||
component: Stepper,
|
||||
} as Meta;
|
||||
|
||||
export const All = () => {
|
||||
const storyTexts = [
|
||||
"Minimize backwards overflow agile. Horsehead offer commitment to the cause nor copy and paste from stack overflow problem territories, innovation is hot right now for can you slack it to me?. High touch client table the discussion , and get buy-in so manage expectations loop back, please advise soonest. We need a paradigm shift dogpile that, and i need to pee and then go to another meeting for let's prioritize the low-hanging fruit.",
|
||||
"Customer centric sorry i didn't get your email proceduralize, and first-order optimal strategies. I dont care if you got some copy, why you dont use officeipsumcom or something like that ? wheelhouse. Viral engagement new economy, this proposal is a win-win situation which will cause a stellar paradigm shift, and produce a multi-fold increase in deliverables Bob called an all-hands this afternoon. Fire up your browser touch base innovation is hot right now so this medium needs to be more dynamic.",
|
||||
"Touch base define the underlying principles that drive decisions and strategy for your design language. I have zero cycles for this. Cadence social currency, for low engagement execute . Deliverables rehydrate the team or let's circle back to that those options are already baked in with this model teams were able to drive adoption and awareness we need to start advertising on social media circle back. Through the lens of face time.",
|
||||
"Take five, punch the tree, and come back in here with a clear head those options are already baked in with this model ultimate measure of success and we need to crystallize a plan yet open door policy who's responsible for the ask for this request? what do you feel you would bring to the table if you were hired for this position. Wiggle room guerrilla marketing shelfware. Code feature creep can we parallel path lose client to 10:00 meeting hire the best manage expectations root-and-branch review.",
|
||||
"Curate downselect tread it daily cc me on that due diligence, or close the loop. All hands on deck my supervisor didn't like the latest revision you gave me can you switch back to the first revision? ping me or game-plan, yet make it a priority, on this journey win-win. Our competitors are jumping the shark we need to build it so that it scales post launch future-proof can we align on lunch orders. Deliverables message the initiative.",
|
||||
"Out of scope poop, so pre launch. I just wanted to give you a heads-up wiggle room cc me on that I have been doing some research this morning and we need to better, nor dog and pony show prioritize these line items so UX. Big data upstream selling circle back, in an ideal world. Get all your ducks in a row land it in region so code so one-sheet. Action item we need to think big start small and scale fast to energize our clients. Cta due diligence, for this vendor is incompetent nor forcing function and circle back and low engagement.",
|
||||
"Move the needle a loss a day will keep you focus yet can you put it into a banner that is not alarming, but eye catching and not too giant or strategic fit, nor it is all exactly as i said, but i don't like it or streamline. We've bootstrapped the model. This proposal is a win-win situation which will cause a stellar paradigm shift, and produce a multi-fold increase in deliverables the horse is out of the barn usabiltiy, for going forward but going forward.",
|
||||
];
|
||||
const [activeStep, setActiveStep] = useState(1);
|
||||
|
||||
const anchorProps = {
|
||||
href: "",
|
||||
onClick: (e) => e.preventDefault(),
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", gap: "10rem" }}>
|
||||
<div>
|
||||
<h2 id="stepper-heading">Stepper</h2>
|
||||
<Stepper
|
||||
aria-labelledby="stepper-heading"
|
||||
activeStep={activeStep}
|
||||
onStepChange={setActiveStep}
|
||||
>
|
||||
<Stepper.Step {...anchorProps}>Start søknad</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>Personopplysninger</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>Saksopplysninger</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>
|
||||
Søknadstekst for en veldig spesifikk prosess i NAV som jeg må skrive
|
||||
om her i denne labelen
|
||||
</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>Vedlegg</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>Oppsummering</Stepper.Step>
|
||||
<Stepper.Step {...anchorProps}>Innsending</Stepper.Step>
|
||||
</Stepper>
|
||||
</div>
|
||||
<BodyLong style={{ marginTop: "5rem" }}>
|
||||
{storyTexts[activeStep]}
|
||||
</BodyLong>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,115 @@
|
||||
import React, { forwardRef, useState } from "react";
|
||||
import cl from "classnames";
|
||||
import Row, { RowProps } from "./Row";
|
||||
import DataCell from "./DataCell";
|
||||
import { UnmountClosed } from "react-collapse";
|
||||
import { Expand, ExpandFilled } from "@navikt/ds-icons";
|
||||
import { useId } from "..";
|
||||
|
||||
interface ExpandableRowProps extends RowProps {
|
||||
/**
|
||||
* Content of the expanded row
|
||||
*/
|
||||
content: React.ReactNode;
|
||||
/**
|
||||
* Placement of toggle button
|
||||
* @default "left"
|
||||
*/
|
||||
togglePlacement?: "left" | "right";
|
||||
/**
|
||||
* Opens component if 'true', closes if 'false'
|
||||
* Using this props removes automatic control of open-state
|
||||
*/
|
||||
open?: boolean;
|
||||
/**
|
||||
* Opened state default
|
||||
* @default false
|
||||
*/
|
||||
defaultOpen?: boolean;
|
||||
/**
|
||||
* Change handler for open
|
||||
*/
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}
|
||||
|
||||
export interface ExpandableRowType
|
||||
extends React.ForwardRefExoticComponent<
|
||||
ExpandableRowProps & React.RefAttributes<HTMLTableRowElement>
|
||||
> {}
|
||||
|
||||
const ExpandableRow: ExpandableRowType = forwardRef(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
content,
|
||||
togglePlacement = "left",
|
||||
defaultOpen = false,
|
||||
open,
|
||||
onOpenChange,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [internalOpen, setInternalOpen] = useState<boolean>(defaultOpen);
|
||||
const id = `expandable-${useId()}`;
|
||||
|
||||
const isOpen = open ?? internalOpen;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-table__expandable-row", className, {
|
||||
"navds-table__expandable-row--open": isOpen,
|
||||
})}
|
||||
>
|
||||
{togglePlacement === "right" && children}
|
||||
<DataCell
|
||||
className={cl("navds-table__toggle-expand-cell", {
|
||||
"navds-table__toggle-expand-cell--open": isOpen,
|
||||
})}
|
||||
>
|
||||
<button
|
||||
className="navds-table__toggle-expand-button"
|
||||
aria-controls={id}
|
||||
aria-expanded={isOpen}
|
||||
onClick={() => {
|
||||
onOpenChange?.(!isOpen);
|
||||
if (open === undefined) {
|
||||
setInternalOpen((open) => !open);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Expand
|
||||
className="navds-table__expandable-icon"
|
||||
title={isOpen ? "Vis mindre" : "Vis mer"}
|
||||
/>
|
||||
<ExpandFilled
|
||||
className="navds-table__expandable-icon navds-table__expandable-icon--filled"
|
||||
title={isOpen ? "Vis mindre" : "Vis mer"}
|
||||
/>
|
||||
</button>
|
||||
</DataCell>
|
||||
{togglePlacement === "left" && children}
|
||||
</Row>
|
||||
<tr className="navds-table__expanded-row" aria-hidden={!isOpen} id={id}>
|
||||
<td colSpan={999} className="navds-table__expanded-row-cell">
|
||||
<UnmountClosed
|
||||
isOpened={isOpen}
|
||||
theme={{
|
||||
collapse: "navds-table__expanded-row-collapse",
|
||||
content: "navds-table__expanded-row-content",
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</UnmountClosed>
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ExpandableRow;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
|
||||
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
||||
export interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
||||
/**
|
||||
* Row is selected
|
||||
* @default false
|
||||
|
||||
@@ -6,6 +6,7 @@ import Row, { RowType } from "./Row";
|
||||
import ColumnHeader, { ColumnHeaderType } from "./ColumnHeader";
|
||||
import HeaderCell, { HeaderCellType } from "./HeaderCell";
|
||||
import DataCell, { DataCellType } from "./DataCell";
|
||||
import ExpandableRow, { ExpandableRowType } from "./ExpandableRow";
|
||||
|
||||
export interface SortState {
|
||||
orderBy: string;
|
||||
@@ -44,6 +45,7 @@ export interface TableType
|
||||
DataCell: DataCellType;
|
||||
HeaderCell: HeaderCellType;
|
||||
ColumnHeader: ColumnHeaderType;
|
||||
ExpandableRow: ExpandableRowType;
|
||||
}
|
||||
|
||||
export interface TableContextProps {
|
||||
@@ -84,5 +86,6 @@ Table.Row = Row;
|
||||
Table.ColumnHeader = ColumnHeader;
|
||||
Table.HeaderCell = HeaderCell;
|
||||
Table.DataCell = DataCell;
|
||||
Table.ExpandableRow = ExpandableRow;
|
||||
|
||||
export default Table;
|
||||
@@ -0,0 +1,201 @@
|
||||
import React, { useState } from "react";
|
||||
import { Table } from "..";
|
||||
import { Link } from "../..";
|
||||
|
||||
export default {
|
||||
title: "ds-react/table",
|
||||
component: Table,
|
||||
};
|
||||
|
||||
export const Expandable = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
{columns.map(({ key, name }) => (
|
||||
<Table.HeaderCell key={key}>{name}</Table.HeaderCell>
|
||||
))}
|
||||
<Table.HeaderCell />
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{data.map((data) => (
|
||||
<Table.ExpandableRow
|
||||
content={data.content}
|
||||
key={data.name}
|
||||
togglePlacement="right"
|
||||
>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{data[key]}</Table.DataCell>
|
||||
))}
|
||||
</Table.ExpandableRow>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
<h2>defaultOpen/controlled + small</h2>
|
||||
<Table size="small">
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell />
|
||||
{columns.map(({ key, name }) => (
|
||||
<Table.HeaderCell key={key}>{name}</Table.HeaderCell>
|
||||
))}
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{data.slice(0, 1).map((data) => (
|
||||
<Table.ExpandableRow
|
||||
content={data.content}
|
||||
key={data.name}
|
||||
defaultOpen
|
||||
>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{data[key]}</Table.DataCell>
|
||||
))}
|
||||
</Table.ExpandableRow>
|
||||
))}
|
||||
{data.slice(1, 2).map((data) => (
|
||||
<Table.ExpandableRow
|
||||
content={data.content}
|
||||
key={data.name}
|
||||
open={open}
|
||||
onOpenChange={(open) => setOpen(open)}
|
||||
>
|
||||
{columns.map(({ key }) => (
|
||||
<Table.DataCell key={key}>{data[key]}</Table.DataCell>
|
||||
))}
|
||||
</Table.ExpandableRow>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: "Navn",
|
||||
key: "name",
|
||||
},
|
||||
{
|
||||
name: "Favoritt dyr",
|
||||
key: "animal",
|
||||
},
|
||||
{
|
||||
name: "Favoritt farge",
|
||||
key: "color",
|
||||
},
|
||||
{
|
||||
name: "Minst favoritt dyr",
|
||||
key: "leastAnimal",
|
||||
},
|
||||
{
|
||||
name: "Minst favoritt farge",
|
||||
key: "leastColor",
|
||||
},
|
||||
{
|
||||
name: "Status",
|
||||
key: "status",
|
||||
},
|
||||
];
|
||||
|
||||
const data = [
|
||||
{
|
||||
name: "Ola Conny Brakkestad",
|
||||
animal: "Ku",
|
||||
color: "Brun",
|
||||
leastAnimal: "Sel",
|
||||
leastColor: "Lyseblå",
|
||||
status: "Inaktiv",
|
||||
content: (
|
||||
<>
|
||||
Ola Conny Brakkestad sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="#">link.</Link>
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Henriette Kristensen",
|
||||
animal: "Bjørn",
|
||||
color: "Hvit",
|
||||
leastAnimal: "Grevling",
|
||||
leastColor: "Transparent",
|
||||
status: <Link href="http://example.com">Hissig</Link>,
|
||||
content: (
|
||||
<>
|
||||
Henriette Kristensen sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="http://example.com">lenke</Link>. I forhold til en betydelig
|
||||
avveining synliggjøres potensialet med sikte på satsingsområdet. Gitt en
|
||||
manglende avveining synliggjøres instrumentet på bakgrunn av forholdene.
|
||||
Under hensyntagen til en inkluderende avveining stimuleres resultatene
|
||||
med henblikk på løsningen. På grunn av en integrert organisasjon
|
||||
initieres kunnskapene eller sagt på en annen måte: evalueringen. Grunnet
|
||||
en gjeldende målsetting dokumenteres relasjonene hva angår egenarten.
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Suki Clydesdale",
|
||||
animal: "Sel",
|
||||
color: "Grønn",
|
||||
leastAnimal: "Serval",
|
||||
leastColor: "Rosa",
|
||||
status: "Deaktivert",
|
||||
content: (
|
||||
<>
|
||||
Suki Clydesdale sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="http://example.com">link</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Hans-Hermann Hoppe",
|
||||
animal: "Mudkip",
|
||||
color: "Oransje",
|
||||
leastAnimal: "Skare",
|
||||
leastColor: "Hvit",
|
||||
status: <Link href="#">Starter</Link>,
|
||||
content: (
|
||||
<>
|
||||
Hans-Hermann Hoppe sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="http://example.com">link</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Max Kraft",
|
||||
animal: "Løve",
|
||||
color: "Blå",
|
||||
leastAnimal: "Hund",
|
||||
leastColor: "Cyan",
|
||||
status: <Link href="#">Eksplodert</Link>,
|
||||
content: (
|
||||
<>
|
||||
Max Kraft sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="http://example.com">link</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
name: "Pat Ole",
|
||||
animal: "Bjørnedyr",
|
||||
color: "Gul",
|
||||
leastAnimal: "Meitemark",
|
||||
leastColor: "Svart",
|
||||
status: <Link href="#">Gunstig</Link>,
|
||||
content: (
|
||||
<>
|
||||
Pat Ole sier "hei". Her er litt innhold med en{" "}
|
||||
<Link href="http://example.com">lenke</Link>.
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,79 @@
|
||||
import * as RadixTabs from "@radix-ui/react-tabs";
|
||||
import cl from "classnames";
|
||||
import React, { forwardRef, useContext } from "react";
|
||||
import { Label, OverridableComponent } from "..";
|
||||
import { TabsContext } from "./Tabs";
|
||||
|
||||
export interface TabProps
|
||||
extends Omit<React.HTMLAttributes<HTMLButtonElement>, "children"> {
|
||||
/**
|
||||
* Content
|
||||
*/
|
||||
label?: React.ReactNode;
|
||||
/**
|
||||
* Icon
|
||||
*/
|
||||
icon?: React.ReactNode;
|
||||
/**
|
||||
* Value for state-handling
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* Icon position
|
||||
* @default "left"
|
||||
*/
|
||||
iconPosition?: "left" | "top";
|
||||
}
|
||||
|
||||
export type TabType = OverridableComponent<TabProps, HTMLButtonElement>;
|
||||
|
||||
const Tab: TabType = forwardRef(
|
||||
(
|
||||
{
|
||||
className,
|
||||
as: Component = "button",
|
||||
label,
|
||||
icon,
|
||||
iconPosition,
|
||||
value,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const context = useContext(TabsContext);
|
||||
|
||||
if (!label && !icon) {
|
||||
console.error("<Tabs.Tab/> needs label/icon");
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<RadixTabs.Trigger value={value} asChild>
|
||||
<Component
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-tabs__tab",
|
||||
`navds-tabs__tab--${context?.size ?? "medium"}`,
|
||||
`navds-tabs__tab-icon--${iconPosition}`,
|
||||
className,
|
||||
{
|
||||
"navds-tabs__tab--icon-only": icon && !label,
|
||||
}
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<Label
|
||||
as="span"
|
||||
className="navds-tabs__tab-inner"
|
||||
size={context?.size}
|
||||
>
|
||||
{icon}
|
||||
{label}
|
||||
</Label>
|
||||
</Component>
|
||||
</RadixTabs.Trigger>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Tab;
|
||||
@@ -0,0 +1,127 @@
|
||||
import { debounce } from "@material-ui/core";
|
||||
import { Back, Next } from "@navikt/ds-icons";
|
||||
import { TabsList } from "@radix-ui/react-tabs";
|
||||
import cl from "classnames";
|
||||
import React, { forwardRef, useEffect, useMemo, useRef, useState } from "react";
|
||||
import mergeRefs from "react-merge-refs";
|
||||
|
||||
export interface ListProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Tab elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Loops back to start when navigating past last item
|
||||
*/
|
||||
loop?: boolean;
|
||||
}
|
||||
|
||||
export type ListType = React.ForwardRefExoticComponent<
|
||||
ListProps & React.RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
const List = forwardRef<HTMLDivElement, ListProps>(
|
||||
({ className, ...rest }, ref) => {
|
||||
const listRef = useRef<HTMLDivElement | null>(null);
|
||||
const mergedRef = mergeRefs([listRef, ref]);
|
||||
const [displayScroll, setDisplayScroll] = useState({
|
||||
start: false,
|
||||
end: false,
|
||||
});
|
||||
|
||||
const updateScrollButtonState = useMemo(
|
||||
() =>
|
||||
debounce(() => {
|
||||
if (!listRef?.current) return;
|
||||
const { scrollWidth, clientWidth } = listRef?.current;
|
||||
let showStartScroll;
|
||||
let showEndScroll;
|
||||
|
||||
const scrollLeft = listRef?.current?.scrollLeft;
|
||||
// use 1 for the potential rounding error with browser zooms.
|
||||
showStartScroll = scrollLeft > 1;
|
||||
showEndScroll = scrollLeft < scrollWidth - clientWidth - 1;
|
||||
|
||||
setDisplayScroll((displayScroll) =>
|
||||
showStartScroll === displayScroll.start &&
|
||||
showEndScroll === displayScroll.end
|
||||
? displayScroll
|
||||
: { start: showStartScroll, end: showEndScroll }
|
||||
);
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => updateScrollButtonState();
|
||||
const win = listRef.current?.ownerDocument ?? document ?? window;
|
||||
win.addEventListener("resize", handleResize);
|
||||
|
||||
let resizeObserver;
|
||||
|
||||
if (typeof ResizeObserver !== "undefined") {
|
||||
resizeObserver = new ResizeObserver(handleResize);
|
||||
resizeObserver.observe(listRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
win.removeEventListener("resize", handleResize);
|
||||
if (resizeObserver) {
|
||||
resizeObserver.disconnect();
|
||||
}
|
||||
};
|
||||
}, [updateScrollButtonState]);
|
||||
|
||||
useEffect(() => {
|
||||
updateScrollButtonState();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
updateScrollButtonState.clear();
|
||||
};
|
||||
}, [updateScrollButtonState]);
|
||||
|
||||
const ScrollButton = ({
|
||||
dir,
|
||||
hidden,
|
||||
}: {
|
||||
dir: 1 | -1;
|
||||
hidden: boolean;
|
||||
}) => (
|
||||
<div
|
||||
className={cl("navds-tabs__scroll-button", {
|
||||
"navds-tabs__scroll-button--hidden": hidden,
|
||||
})}
|
||||
onClick={() => {
|
||||
if (!listRef.current) return;
|
||||
listRef.current.scrollLeft += dir * 100;
|
||||
}}
|
||||
>
|
||||
{dir === -1 ? (
|
||||
<Back title="scroll tilbake" />
|
||||
) : (
|
||||
<Next title="scroll neste" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
const showSteppers = displayScroll.end || displayScroll.start;
|
||||
return (
|
||||
<div className="navds-tabs__tablist-wrapper">
|
||||
{showSteppers && (
|
||||
<ScrollButton dir={-1} hidden={!displayScroll.start} />
|
||||
)}
|
||||
<TabsList
|
||||
{...rest}
|
||||
ref={mergedRef}
|
||||
onScroll={updateScrollButtonState}
|
||||
className={cl("navds-tabs__tablist", className)}
|
||||
/>
|
||||
{showSteppers && <ScrollButton dir={1} hidden={!displayScroll.end} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
) as ListType;
|
||||
|
||||
export default List;
|
||||
@@ -0,0 +1,30 @@
|
||||
import { TabsContent } from "@radix-ui/react-tabs";
|
||||
import cl from "classnames";
|
||||
import React, { forwardRef } from "react";
|
||||
|
||||
export interface PanelProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Tab panel
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Value for state-handling
|
||||
*/
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type PanelType = React.ForwardRefExoticComponent<
|
||||
PanelProps & React.RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
const Panel = forwardRef<HTMLDivElement, PanelProps>(
|
||||
({ className, ...rest }, ref) => (
|
||||
<TabsContent
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-tabs__tabpanel", className)}
|
||||
/>
|
||||
)
|
||||
) as PanelType;
|
||||
|
||||
export default Panel;
|
||||
@@ -0,0 +1,188 @@
|
||||
import { Cup, Dishwasher, Freezer } from "@navikt/ds-icons";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import React, { useState } from "react";
|
||||
import { Tabs } from ".";
|
||||
import { Link } from "../link";
|
||||
|
||||
export default {
|
||||
title: "ds-react/tabs",
|
||||
component: Tabs,
|
||||
} as Meta;
|
||||
|
||||
export const UUDemo = () => (
|
||||
<Tabs defaultValue="skap" lang="no">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="skap" label="Skap" icon={<Cup aria-hidden />} />
|
||||
<Tabs.Tab
|
||||
value="oppvaskmaskin"
|
||||
label="Oppvaskmaskin"
|
||||
icon={<Dishwasher aria-hidden />}
|
||||
/>
|
||||
<Tabs.Tab value="fryser" icon={<Freezer aria-hidden />} label="Fryser" />
|
||||
</Tabs.List>
|
||||
<Tabs.Panel
|
||||
value="skap"
|
||||
style={{ background: "var(--navds-global-color-gray-50)", height: 300 }}
|
||||
>
|
||||
Innholdspanel for skap med lenke <Link href="#">Dette er en lenke</Link>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel
|
||||
value="oppvaskmaskin"
|
||||
style={{ background: "var(--navds-global-color-green-50)", height: 300 }}
|
||||
>
|
||||
Innholdspanel for oppvaskmaskin med lenke{" "}
|
||||
<Link href="#">Dette er en lenke</Link>
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel
|
||||
value="fryser"
|
||||
style={{ background: "var(--navds-global-color-red-50)", height: 300 }}
|
||||
>
|
||||
Innholdspanel for fryser med lenke <Link href="#">Dette er en lenke</Link>
|
||||
</Tabs.Panel>
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
const Panel = () => {
|
||||
return (
|
||||
<>
|
||||
<Tabs.Panel
|
||||
value="test1"
|
||||
style={{ background: "var(--navds-global-color-gray-50)", height: 100 }}
|
||||
>
|
||||
Innholdspanel for Skap-tab
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel
|
||||
value="test2"
|
||||
style={{
|
||||
background: "var(--navds-global-color-green-50)",
|
||||
height: 100,
|
||||
}}
|
||||
>
|
||||
Innholdspanel for Oppvaskmaskin-tab
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel
|
||||
value="test3"
|
||||
style={{ background: "var(--navds-global-color-red-50)", height: 100 }}
|
||||
>
|
||||
Innholdspanel for Fryser-tab
|
||||
</Tabs.Panel>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const All = () => {
|
||||
const [activeValue, setActiveValue] = useState("test1");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Tabs</h2>
|
||||
<Tabs defaultValue="test2">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} label="Skap" />
|
||||
<Tabs.Tab value="test2" label="Oppvaskmaskin" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} label="Fryser" />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
|
||||
<h2>Controlled</h2>
|
||||
<Tabs value={activeValue} onChange={setActiveValue}>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} label="Skap" />
|
||||
<Tabs.Tab value="test2" label="Oppvaskmaskin" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} label="Fryser" />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
|
||||
<h2>selectionFollowsFocus</h2>
|
||||
<Tabs defaultValue="test2" selectionFollowsFocus>
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} label="Skap" />
|
||||
<Tabs.Tab value="test2" label="Oppvaskmaskin" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} label="Fryser" />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
|
||||
<h2>Tabs iconPosition="top"</h2>
|
||||
<Tabs defaultValue="test2">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
value="test1"
|
||||
icon={<Cup />}
|
||||
label="Skap"
|
||||
iconPosition="top"
|
||||
/>
|
||||
<Tabs.Tab
|
||||
value="test2"
|
||||
label="Oppvaskmaskin"
|
||||
icon={<Dishwasher />}
|
||||
iconPosition="top"
|
||||
/>
|
||||
<Tabs.Tab
|
||||
value="test3"
|
||||
icon={<Freezer />}
|
||||
label="Fryser"
|
||||
iconPosition="top"
|
||||
/>
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
|
||||
<h2>Tabs small</h2>
|
||||
<Tabs defaultValue="test2" size="small">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} label="Skap" />
|
||||
<Tabs.Tab value="test2" label="Oppvaskmaskin" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} label="Fryser" />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
<br />
|
||||
<Tabs defaultValue="test2" size="small">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab
|
||||
value="test1"
|
||||
icon={<Cup />}
|
||||
label="Skap"
|
||||
iconPosition="top"
|
||||
/>
|
||||
|
||||
<Tabs.Tab
|
||||
value="test2"
|
||||
label="Oppvaskmaskin"
|
||||
icon={<Dishwasher />}
|
||||
iconPosition="top"
|
||||
/>
|
||||
<Tabs.Tab
|
||||
value="test3"
|
||||
icon={<Freezer />}
|
||||
label="Fryser"
|
||||
iconPosition="top"
|
||||
/>
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
|
||||
<h2>Tabs Icon-only</h2>
|
||||
<Tabs defaultValue="test2">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} />
|
||||
<Tabs.Tab value="test2" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
<br />
|
||||
<Tabs defaultValue="test2" size="small">
|
||||
<Tabs.List>
|
||||
<Tabs.Tab value="test1" icon={<Cup />} />
|
||||
<Tabs.Tab value="test2" icon={<Dishwasher />} />
|
||||
<Tabs.Tab value="test3" icon={<Freezer />} />
|
||||
</Tabs.List>
|
||||
<Panel />
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
import cl from "classnames";
|
||||
import React, { createContext, forwardRef, HTMLAttributes } from "react";
|
||||
import * as RadixTabs from "@radix-ui/react-tabs";
|
||||
import Tab, { TabType } from "./Tab";
|
||||
import List, { ListType } from "./TabList";
|
||||
import Panel, { PanelType } from "./TabPanel";
|
||||
|
||||
export interface TabsProps
|
||||
extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "dir"> {
|
||||
/**
|
||||
* Tabs elements
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes padding and font-size
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
/**
|
||||
* onChange
|
||||
*/
|
||||
onChange?: (value: string) => void;
|
||||
/**
|
||||
* Controlled selected value
|
||||
*/
|
||||
value?: string;
|
||||
/**
|
||||
* If not controlled, a default-value needs to be set
|
||||
*/
|
||||
defaultValue?: string;
|
||||
/**
|
||||
* Automatically activates tab on focus/navigation
|
||||
* @default false
|
||||
*/
|
||||
selectionFollowsFocus?: boolean;
|
||||
}
|
||||
|
||||
interface TabsComponent
|
||||
extends React.ForwardRefExoticComponent<
|
||||
TabsProps & React.RefAttributes<HTMLDivElement>
|
||||
> {
|
||||
Tab: TabType;
|
||||
List: ListType;
|
||||
Panel: PanelType;
|
||||
}
|
||||
|
||||
interface TabsContextProps {
|
||||
size: "medium" | "small";
|
||||
}
|
||||
|
||||
export const TabsContext = createContext<TabsContextProps | null>(null);
|
||||
|
||||
const Tabs = forwardRef<HTMLDivElement, TabsProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
onChange,
|
||||
size = "medium",
|
||||
selectionFollowsFocus = false,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<RadixTabs.Root
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-tabs", className, `navds-tabs--${size}`)}
|
||||
activationMode={selectionFollowsFocus ? "automatic" : "manual"}
|
||||
onValueChange={onChange}
|
||||
>
|
||||
<TabsContext.Provider
|
||||
value={{
|
||||
size,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</TabsContext.Provider>
|
||||
</RadixTabs.Root>
|
||||
);
|
||||
}
|
||||
) as TabsComponent;
|
||||
|
||||
Tabs.Tab = Tab;
|
||||
Tabs.List = List;
|
||||
Tabs.Panel = Panel;
|
||||
|
||||
export default Tabs;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as Tabs, TabsProps } from "./Tabs";
|
||||
export { TabProps } from "./Tab";
|
||||
@@ -0,0 +1,301 @@
|
||||
import cl from "classnames";
|
||||
import React, {
|
||||
cloneElement,
|
||||
forwardRef,
|
||||
HTMLAttributes,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { composeEventHandlers, Detail, useEventListener } from "..";
|
||||
import {
|
||||
useFloating,
|
||||
arrow as flArrow,
|
||||
shift,
|
||||
autoUpdate,
|
||||
flip,
|
||||
hide,
|
||||
} from "@floating-ui/react-dom";
|
||||
import mergeRefs from "react-merge-refs";
|
||||
import Portal from "./portal";
|
||||
import { useId } from "../util";
|
||||
|
||||
export interface TooltipProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Element tooltip anchors to
|
||||
*/
|
||||
children: React.ReactElement & React.RefAttributes<HTMLElement>;
|
||||
/**
|
||||
* Open state for contolled tooltip
|
||||
*/
|
||||
open?: boolean;
|
||||
/**
|
||||
* Tells tooltip to start in open state
|
||||
* @note "open"-prop overwrites this
|
||||
*/
|
||||
defaultOpen?: boolean;
|
||||
/**
|
||||
* Orientation for tooltip
|
||||
* @default "top"
|
||||
*/
|
||||
placement?: "top" | "right" | "bottom" | "left";
|
||||
/**
|
||||
* Toggles rendering of arrow
|
||||
* @default true
|
||||
*/
|
||||
arrow?: boolean;
|
||||
/**
|
||||
* Distance from anchor to tooltip
|
||||
* @default 10px with arrow, 2px without arrow
|
||||
*/
|
||||
offset?: number;
|
||||
/**
|
||||
* Content shown in tooltip
|
||||
*/
|
||||
content: string;
|
||||
/**
|
||||
* Sets max allowed character length
|
||||
* @default 80
|
||||
*/
|
||||
maxChar?: number;
|
||||
/**
|
||||
* Adds a delay in milliseconds before opening tooltip
|
||||
* @default 300
|
||||
*/
|
||||
delay?: number;
|
||||
/**
|
||||
* List of Keyboard-keys for shortcuts
|
||||
*/
|
||||
keys?: string[];
|
||||
}
|
||||
|
||||
const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
className,
|
||||
arrow: _arrow = true,
|
||||
placement: _placement = "top",
|
||||
open,
|
||||
defaultOpen = false,
|
||||
offset: _offset,
|
||||
content,
|
||||
delay = 150,
|
||||
id,
|
||||
keys,
|
||||
maxChar = 80,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const arrowRef = useRef<HTMLDivElement | null>(null);
|
||||
const [isOpen, setIsOpen] = useState(defaultOpen);
|
||||
const openTimerRef = useRef(0);
|
||||
const leaveTimerRef = useRef(0);
|
||||
const isMouseDownRef = useRef(false);
|
||||
|
||||
const ariaId = useId(id);
|
||||
|
||||
const {
|
||||
x,
|
||||
y,
|
||||
update,
|
||||
placement,
|
||||
refs,
|
||||
middlewareData: {
|
||||
arrow: { x: arrowX, y: arrowY } = {},
|
||||
hide: { referenceHidden } = {},
|
||||
},
|
||||
} = useFloating({
|
||||
placement: _placement,
|
||||
middleware: [
|
||||
shift(),
|
||||
flip({ padding: 5, fallbackPlacements: ["bottom", "top"] }),
|
||||
flArrow({ element: arrowRef, padding: 5 }),
|
||||
hide(),
|
||||
],
|
||||
});
|
||||
|
||||
/* https://floating-ui.com/docs/react-dom#updating */
|
||||
useEffect(() => {
|
||||
if (!refs.reference.current || !refs.floating.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only call this when the floating element is rendered
|
||||
return autoUpdate(refs.reference.current, refs.floating.current, update);
|
||||
}, [refs.reference, refs.floating, update, open, isOpen]);
|
||||
|
||||
const handleOpen = useCallback(() => {
|
||||
window.clearTimeout(openTimerRef.current);
|
||||
window.clearTimeout(leaveTimerRef.current);
|
||||
setIsOpen(true);
|
||||
}, [setIsOpen]);
|
||||
|
||||
const handleDelayedOpen = useCallback(() => {
|
||||
window.clearTimeout(openTimerRef.current);
|
||||
window.clearTimeout(leaveTimerRef.current);
|
||||
openTimerRef.current = window.setTimeout(() => {
|
||||
setIsOpen(true);
|
||||
}, delay);
|
||||
}, [delay, setIsOpen]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
window.clearTimeout(openTimerRef.current);
|
||||
leaveTimerRef.current = window.setTimeout(() => {
|
||||
setIsOpen(false);
|
||||
}, 50);
|
||||
}, [setIsOpen]);
|
||||
|
||||
const handleMouseUp = useCallback(
|
||||
() => (isMouseDownRef.current = false),
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
return () => window.clearTimeout(openTimerRef.current);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
return () => document.removeEventListener("mouseup", handleMouseUp);
|
||||
}, [handleMouseUp]);
|
||||
|
||||
useEventListener(
|
||||
"keydown",
|
||||
useCallback((e) => e.key === "Escape" && handleClose(), [handleClose]),
|
||||
document
|
||||
);
|
||||
|
||||
/* https://floating-ui.com/docs/react-dom#stable-ref-prop */
|
||||
const stableRef = useMemo(() => mergeRefs([ref, refs.floating]), [
|
||||
ref,
|
||||
refs.floating,
|
||||
]);
|
||||
|
||||
if (
|
||||
!children ||
|
||||
children?.type === React.Fragment ||
|
||||
(children as any) === React.Fragment
|
||||
) {
|
||||
console.error(
|
||||
"<Tooltip> children needs to be a single ReactElement and not <React.Fragment/>/<></>"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (content?.length > maxChar) {
|
||||
console.error(
|
||||
`Because of strict accessibility concers we encourage all Tooltips to have less than 80 characters. Can be overwritten with the maxChar-prop`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{cloneElement(children, {
|
||||
...children.props,
|
||||
"aria-describedby":
|
||||
open || isOpen
|
||||
? cl(ariaId, children?.props["aria-describedby"])
|
||||
: children?.props["aria-describedby"],
|
||||
ref: mergeRefs([(children as any).ref, refs.reference]),
|
||||
onMouseEnter: composeEventHandlers(
|
||||
children.props.onMouseEnter,
|
||||
handleDelayedOpen
|
||||
),
|
||||
onMouseLeave: composeEventHandlers(
|
||||
children.props.onMouseLeave,
|
||||
handleClose
|
||||
),
|
||||
onMouseDown: composeEventHandlers(children.props.onMouseDown, () => {
|
||||
isMouseDownRef.current = true;
|
||||
document.addEventListener("mouseup", handleMouseUp, { once: true });
|
||||
}),
|
||||
onFocus: composeEventHandlers(
|
||||
children.props.onFocus,
|
||||
() => !isMouseDownRef.current && handleOpen()
|
||||
),
|
||||
onBlur: composeEventHandlers(children.props.onBlur, handleClose),
|
||||
})}
|
||||
{(open ?? isOpen) && (
|
||||
<Portal>
|
||||
<div
|
||||
ref={stableRef}
|
||||
{...rest}
|
||||
onMouseEnter={handleOpen}
|
||||
onMouseLeave={handleClose}
|
||||
role="tooltip"
|
||||
id={ariaId}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: y ?? "",
|
||||
left: x ?? "",
|
||||
visibility: referenceHidden ? "hidden" : "visible",
|
||||
}}
|
||||
data-side={placement}
|
||||
className={cl(
|
||||
"navds-tooltip",
|
||||
"navds-detail navds-detail--small",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="navds-tooltip__inner"
|
||||
style={{
|
||||
[{
|
||||
top: "marginBottom",
|
||||
right: "marginLeft",
|
||||
bottom: "marginTop",
|
||||
left: "marginRight",
|
||||
}[placement]]: _offset ? _offset : _arrow ? 10 : 2,
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
{keys && (
|
||||
<span className="navds-tooltip__keys">
|
||||
{keys.map((key) => (
|
||||
<Detail
|
||||
size="small"
|
||||
as="kbd"
|
||||
key={key}
|
||||
className="navds-tooltip__key"
|
||||
>
|
||||
{key}
|
||||
</Detail>
|
||||
))}
|
||||
</span>
|
||||
)}
|
||||
{_arrow && (
|
||||
<div
|
||||
ref={(node) => {
|
||||
arrowRef.current = node;
|
||||
}}
|
||||
className="navds-tooltip__arrow"
|
||||
style={{
|
||||
left: arrowX != null ? `${arrowX}px` : "",
|
||||
top: arrowY != null ? `${arrowY}px` : "",
|
||||
right: "",
|
||||
bottom: "",
|
||||
|
||||
[{
|
||||
top: "bottom",
|
||||
right: "left",
|
||||
bottom: "top",
|
||||
left: "right",
|
||||
}[placement]]: "-3.5px",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Portal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Tooltip;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { default as Tooltip } from "./Tooltip";
|
||||
export * from "./Tooltip";
|
||||
@@ -0,0 +1,15 @@
|
||||
/* https://github.com/radix-ui/primitives/blob/main/packages/react/portal/src/Portal.tsx */
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const Portal = ({ children }) => {
|
||||
const hostElement = globalThis?.document?.body;
|
||||
|
||||
if (hostElement) {
|
||||
return ReactDOM.createPortal(children, hostElement);
|
||||
}
|
||||
|
||||
// bail out of ssr
|
||||
return null;
|
||||
};
|
||||
|
||||
export default Portal;
|
||||
@@ -0,0 +1,144 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Tooltip } from "../index";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import { Refresh } from "@navikt/ds-icons";
|
||||
import { Button } from "../..";
|
||||
import { ToggleGroup } from "../toggle-group";
|
||||
|
||||
export default {
|
||||
title: "ds-react/tooltip",
|
||||
component: Tooltip,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
export const Demo = () => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const testRef = useRef(null);
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 32,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
content="Tooltip example"
|
||||
keys={["Cmd", "K"]}
|
||||
placement="right"
|
||||
open={open}
|
||||
ref={testRef}
|
||||
>
|
||||
<Button aria-describedby="test123" onClick={() => setOpen(!open)}>
|
||||
Tooltip C
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
content="Tooltip example"
|
||||
keys={["Cmd", "K"]}
|
||||
placement="right"
|
||||
defaultOpen
|
||||
>
|
||||
<Button onClick={() => console.log(testRef.current)}>Tooltip C</Button>
|
||||
</Tooltip>
|
||||
<ToggleGroup onChange={null} defaultValue="321">
|
||||
<Tooltip content="Tooltip" placement="bottom">
|
||||
<ToggleGroup.Item value="123">Tekst</ToggleGroup.Item>
|
||||
</Tooltip>
|
||||
<Tooltip content="Tooltip" placement="bottom">
|
||||
<ToggleGroup.Item value="321">tekst 2</ToggleGroup.Item>
|
||||
</Tooltip>
|
||||
<Tooltip content="Tooltip" placement="bottom">
|
||||
<ToggleGroup.Item value="3212">tekst 2</ToggleGroup.Item>
|
||||
</Tooltip>
|
||||
<Tooltip content="Tooltip" placement="bottom">
|
||||
<ToggleGroup.Item value="3213">tekst 2</ToggleGroup.Item>
|
||||
</Tooltip>
|
||||
<Tooltip content="Tooltip" placement="bottom">
|
||||
<ToggleGroup.Item value="3214">tekst 2</ToggleGroup.Item>
|
||||
</Tooltip>
|
||||
</ToggleGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const All = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
return (
|
||||
<div style={{ margin: "4rem 8rem 4rem 8rem" }}>
|
||||
<h2>Controlled</h2>
|
||||
<Tooltip open={open} content="Controlled tooltip example" placement="top">
|
||||
<Button onClick={() => setOpen((x) => !x)}>Toggle tooltip</Button>
|
||||
</Tooltip>
|
||||
|
||||
<h2>no arrow</h2>
|
||||
<Tooltip content="no arrow" placement="top" arrow={false}>
|
||||
<Button>Tooltip</Button>
|
||||
</Tooltip>
|
||||
|
||||
<h2>Keys</h2>
|
||||
<Tooltip content="Tooltip" placement="top" open keys={["Cmd", "K"]}>
|
||||
<Button>Tooltip</Button>
|
||||
</Tooltip>
|
||||
<h2>more offset</h2>
|
||||
<Tooltip content="Tooltip" placement="top" open offset={20}>
|
||||
<Button>Tooltip</Button>
|
||||
</Tooltip>
|
||||
|
||||
<h2>all placements</h2>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
gap: "3rem",
|
||||
}}
|
||||
>
|
||||
{["top", "left", "bottom", "right"].map((placement) => (
|
||||
<div key={placement}>
|
||||
<h3>{placement}</h3>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flexWrap: "wrap",
|
||||
gap: "3rem",
|
||||
}}
|
||||
>
|
||||
<Tooltip
|
||||
key={placement}
|
||||
defaultOpen
|
||||
content={placement}
|
||||
placement={placement as any}
|
||||
>
|
||||
<Refresh aria-hidden tabIndex={0} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const UUDemo = () => {
|
||||
return (
|
||||
<div>
|
||||
<Button>Placeholder</Button>
|
||||
<br />
|
||||
<br />
|
||||
<Tooltip content="Shortcut" placement="right" keys={["Cmd", "S"]}>
|
||||
<Button>Lagre</Button>
|
||||
</Tooltip>
|
||||
<br />
|
||||
<br />
|
||||
<Button>Placeholder</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -44,3 +44,17 @@ export const useEventListener = <T extends ListenerT>(
|
||||
};
|
||||
}, [name, handler, target]);
|
||||
};
|
||||
|
||||
/* https://github.com/radix-ui/primitives/blob/main/packages/core/primitive/src/primitive.tsx */
|
||||
export const composeEventHandlers = <E>(
|
||||
originalEventHandler?: (event: E) => void,
|
||||
ourEventHandler?: (event: E) => void
|
||||
) => {
|
||||
return function handleEvent(event: E) {
|
||||
originalEventHandler?.(event);
|
||||
|
||||
if (!((event as unknown) as Event).defaultPrevented) {
|
||||
return ourEventHandler?.(event);
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tailwind",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.8",
|
||||
"private": false,
|
||||
"description": "Auto-generated tailwind config based on @navikt/ds-tokens",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -23,7 +23,7 @@
|
||||
"directory": "@navikt/core/tailwind"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^0.8.4",
|
||||
"@navikt/ds-tokens": "^0.8.6",
|
||||
"@types/jest": "^27.0.1",
|
||||
"jest": "^27.2.0",
|
||||
"lodash": "^4.17.21",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "0.8.4",
|
||||
"version": "0.8.6",
|
||||
"private": false,
|
||||
"description": "Auto-generated design-tokens for NAV design-systems framework",
|
||||
"author": "NAV Designsystem team",
|
||||
|
||||
@@ -396,7 +396,7 @@
|
||||
},
|
||||
"focus": {
|
||||
"inverted": {
|
||||
"value": "{navds.global.color.blue.200.value}"
|
||||
"value": "{navds.global.color.blue.300.value}"
|
||||
},
|
||||
"@": {
|
||||
"value": "{navds.global.color.blue.800.value}"
|
||||
|
||||
@@ -43,6 +43,7 @@ module.exports = {
|
||||
modal: { value: 2000 },
|
||||
popover: { value: 1000 },
|
||||
focus: { value: 10 },
|
||||
tooltip: { value: 3000 },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,9 +1,9 @@
|
||||
:root {
|
||||
--navdsi-header-color-text: var(--navds-semantic-color-text-inverted);
|
||||
--navdsi-header-color-background: var(
|
||||
--navds-semantic-color-component-background-inverted
|
||||
);
|
||||
--navdsi-header-color-border: var(--navds-semantic-color-border-muted);
|
||||
--navdsi-header-color-text: var(--navds-semantic-color-text-inverted);
|
||||
--navdsi-header-focus: inset 0 0 0 2px var(--navds-global-color-blue-100);
|
||||
--navdsi-header-color-hover: var(--navds-global-color-gray-800);
|
||||
--navdsi-header-color-active: var(--navds-global-color-gray-600);
|
||||
@@ -37,7 +37,6 @@ button.navdsi-header__title {
|
||||
}
|
||||
|
||||
.navdsi-header__user {
|
||||
color: var(--navdsi-header-color-text);
|
||||
padding: 0 var(--navds-spacing-5);
|
||||
border-left: 1px solid var(--navdsi-header-color-border);
|
||||
display: flex;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css-internal",
|
||||
"version": "0.7.1",
|
||||
"version": "0.7.2",
|
||||
"private": false,
|
||||
"description": "Css for NAV internal Designsystem components",
|
||||
"author": "NAV Designsystem team",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react-internal",
|
||||
"version": "0.12.11",
|
||||
"version": "0.12.18",
|
||||
"private": false,
|
||||
"description": "NAV internal designsystem react components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@navikt/ds-icons": "^0.8.6",
|
||||
"@navikt/ds-react": "^0.17.11",
|
||||
"@navikt/ds-react": "^0.17.18",
|
||||
"@popperjs/core": "^2.10.1",
|
||||
"classnames": "^2.3.1",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
|
||||
@@ -23,7 +23,12 @@ interface HeaderComponent
|
||||
}
|
||||
|
||||
const Header = forwardRef(({ className, ...rest }, ref) => (
|
||||
<header {...rest} ref={ref} className={cl("navdsi-header", className)} />
|
||||
<header
|
||||
data-theme="dark"
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navdsi-header", className)}
|
||||
/>
|
||||
)) as HeaderComponent;
|
||||
|
||||
Header.Title = HeaderTitle;
|
||||
|
||||
@@ -32,7 +32,7 @@ Repoet inneholder følgende:
|
||||
|
||||
## Endringslogg
|
||||
|
||||
[Alle relevante kode-endringer blir dokumentert her](https://design.nav.no/designsystem/side/endringslogg)
|
||||
[Alle relevante kode-endringer blir dokumentert her](https://aksel.nav.no/designsystem/side/changelog)
|
||||
|
||||
## Bidra
|
||||
|
||||
|
||||
@@ -1312,6 +1312,26 @@
|
||||
minimatch "^3.0.4"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@floating-ui/core@^0.6.1":
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.6.1.tgz#aed861a1b6dbebadf14a9dd829ba67f4f3ae795c"
|
||||
integrity sha512-Y30eVMcZva8o84c0HcXAtDO4BEzPJMvF6+B7x7urL2xbAqVsGJhojOyHLaoQHQYjb6OkqRq5kO+zeySycQwKqg==
|
||||
|
||||
"@floating-ui/dom@^0.4.0":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.4.1.tgz#3e164482d7f036527f65a794bdf054d2cc44fcbf"
|
||||
integrity sha512-VAdIkn+zc4VB3pSemBk2JwjXlbVEBUbQft4V5jGpUeA9Vxd1fQD5eL3dMIMLVW003NYCOoW42JjjyBPNTpr8uQ==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^0.6.1"
|
||||
|
||||
"@floating-ui/react-dom@0.6.0":
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.6.0.tgz#e58abf75bec1eac01f0adfff1454106bf9d3dd50"
|
||||
integrity sha512-/dF+jpAUtoonjs2lO0F+miqEQlzA9XJGOxWBiJsq/COhK2kz7XzryyJdxfaNEH+RN63vRs9osDolOJXlst50hg==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "^0.4.0"
|
||||
use-isomorphic-layout-effect "^1.1.1"
|
||||
|
||||
"@gar/promisify@^1.0.1":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
@@ -2671,6 +2691,19 @@
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "0.1.0"
|
||||
|
||||
"@radix-ui/react-tabs@0.1.5":
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-0.1.5.tgz#ddcf860cc32e186d76477ae767dbb216d1944252"
|
||||
integrity sha512-ieVQS1TFr0dX1XA8B+CsSFKOE7kcgEaNWWEfItxj9D1GZjn1o3WqPkW+FhQWDAWZLSKCH2PezYF3MNyO41lgJg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/primitive" "0.1.0"
|
||||
"@radix-ui/react-context" "0.1.1"
|
||||
"@radix-ui/react-id" "0.1.5"
|
||||
"@radix-ui/react-primitive" "0.1.4"
|
||||
"@radix-ui/react-roving-focus" "0.1.5"
|
||||
"@radix-ui/react-use-controllable-state" "0.1.0"
|
||||
|
||||
"@radix-ui/react-toggle-group@0.1.5":
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-toggle-group/-/react-toggle-group-0.1.5.tgz#9e4d65e22c4fc0ba3a42fbc8d5496c430e5e9852"
|
||||
@@ -4185,10 +4218,17 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
||||
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
|
||||
|
||||
"@types/react-collapse@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-collapse/-/react-collapse-5.0.1.tgz#078ea1ad15e00ba2063f2e4d8d6760c9375a2023"
|
||||
integrity sha512-Iq3OrqvzCIP0DmAawU4T2VKH6XAplbjo/D7Qk14mcfQ92plU+OrA2SF10r2XrcFg1Wvya/5f8w1vS29RVpdoLQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@*":
|
||||
version "17.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.13.tgz#a3323b974ee4280070982b3112351bb1952a7809"
|
||||
integrity sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==
|
||||
version "17.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.12.tgz#f08dfbc3c6d35084ffd3db6f09bdea8913de8494"
|
||||
integrity sha512-SeJ430ndLI15JtRSHuzotn7AIdUtr8bdk6XW8mMfzjZo3vahRgJGHZqHiI4nAzCHTVG4qC21ObfsHBVUEHcDhg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
@@ -4324,9 +4364,9 @@
|
||||
source-map "^0.6.0"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
|
||||
integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
|
||||
version "20.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129"
|
||||
integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==
|
||||
|
||||
"@types/yargs@^15.0.0":
|
||||
version "15.0.14"
|
||||
@@ -5936,9 +5976,9 @@ camelize@^1.0.0:
|
||||
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
|
||||
|
||||
caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001312:
|
||||
version "1.0.30001313"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001313.tgz#a380b079db91621e1b7120895874e2fd62ed2e2f"
|
||||
integrity sha512-rI1UN0koZUiKINjysQDuRi2VeSCce3bYJNmDcj3PIKREiAmjakugBul1QSkg/fPrlULYl6oWfGg3PbgOSY9X4Q==
|
||||
version "1.0.30001312"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f"
|
||||
integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==
|
||||
|
||||
capital-case@^1.0.4:
|
||||
version "1.0.4"
|
||||
@@ -7027,14 +7067,14 @@ cssstyle@^2.3.0:
|
||||
cssom "~0.3.6"
|
||||
|
||||
csstype@^2.5.2, csstype@^2.5.7:
|
||||
version "2.6.20"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.20.tgz#9229c65ea0b260cf4d3d997cb06288e36a8d6dda"
|
||||
integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
|
||||
version "2.6.19"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.19.tgz#feeb5aae89020bb389e1f63669a5ed490e391caa"
|
||||
integrity sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==
|
||||
|
||||
csstype@^3.0.2:
|
||||
version "3.0.11"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
|
||||
integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5"
|
||||
integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==
|
||||
|
||||
cyclist@^1.0.1:
|
||||
version "1.0.1"
|
||||
@@ -7633,10 +7673,10 @@ enhanced-resolve@^4.5.0:
|
||||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
enhanced-resolve@^5.9.2:
|
||||
version "5.9.2"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9"
|
||||
integrity sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==
|
||||
enhanced-resolve@^5.8.3:
|
||||
version "5.9.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.1.tgz#e898cea44d9199fd92137496cff5691b910fb43e"
|
||||
integrity sha512-jdyZMwCQ5Oj4c5+BTnkxPgDZO/BJzh/ADDmKebayyzNwjVX1AFCeGkOfxNx0mHi2+8BKC5VxUYiw3TIvoT7vhw==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
@@ -7895,9 +7935,9 @@ eslint-plugin-react-hooks@^4.1.2:
|
||||
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
|
||||
|
||||
eslint-plugin-react@^7.21.2:
|
||||
version "7.29.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05"
|
||||
integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg==
|
||||
version "7.29.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.2.tgz#2d4da69d30d0a736efd30890dc6826f3e91f3f7c"
|
||||
integrity sha512-ypEBTKOy5liFQXZWMchJ3LN0JX1uPI6n7MN7OPHKacqXAxq5gYC30TdO7wqGYQyxD1OrzpobdHC3hDmlRWDg9w==
|
||||
dependencies:
|
||||
array-includes "^3.1.4"
|
||||
array.prototype.flatmap "^1.2.5"
|
||||
@@ -11962,9 +12002,9 @@ minimist-options@4.1.0:
|
||||
kind-of "^6.0.3"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||
|
||||
minipass-collect@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -16319,9 +16359,9 @@ ts-pnp@^1.1.6:
|
||||
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
||||
|
||||
tsconfig-paths@^3.12.0:
|
||||
version "3.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7"
|
||||
integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
|
||||
integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==
|
||||
dependencies:
|
||||
"@types/json5" "^0.0.29"
|
||||
json5 "^1.0.1"
|
||||
@@ -16763,7 +16803,7 @@ use-composed-ref@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849"
|
||||
integrity sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==
|
||||
|
||||
use-isomorphic-layout-effect@^1.0.0:
|
||||
use-isomorphic-layout-effect@^1.0.0, use-isomorphic-layout-effect@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225"
|
||||
integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==
|
||||
@@ -17133,9 +17173,9 @@ webpack@4:
|
||||
webpack-sources "^1.4.1"
|
||||
|
||||
webpack@^5.4.0, webpack@^5.9.0:
|
||||
version "5.70.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.70.0.tgz#3461e6287a72b5e6e2f4872700bc8de0d7500e6d"
|
||||
integrity sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==
|
||||
version "5.69.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5"
|
||||
integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^0.0.51"
|
||||
@@ -17146,7 +17186,7 @@ webpack@^5.4.0, webpack@^5.9.0:
|
||||
acorn-import-assertions "^1.7.6"
|
||||
browserslist "^4.14.5"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.9.2"
|
||||
enhanced-resolve "^5.8.3"
|
||||
es-module-lexer "^0.9.0"
|
||||
eslint-scope "5.1.1"
|
||||
events "^3.2.0"
|
||||
|
||||
Reference in new issue
Block a user