mirror of
https://github.com/navikt/aksel.git
synced 2026-10-13 09:12:03 +00:00
Compare commits
44
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffcfe79c18 | ||
|
|
5d8d2ffba9 | ||
|
|
c785316086 | ||
|
|
7087f160e8 | ||
|
|
235e48a843 | ||
|
|
93fc5dc6ae | ||
|
|
5c49902ffb | ||
|
|
c9c148e050 | ||
|
|
adf9de3c63 | ||
|
|
26612e371d | ||
|
|
b194506943 | ||
|
|
79dbffff1d | ||
|
|
0359934bb9 | ||
|
|
2723363fa0 | ||
|
|
d56bc72977 | ||
|
|
e203d669e1 | ||
|
|
90c06964a3 | ||
|
|
c35850a5e5 | ||
|
|
fd2ebe2629 | ||
|
|
206cdaa2ce | ||
|
|
42bc4288f5 | ||
|
|
3d7cc1112c | ||
|
|
00fec86f80 | ||
|
|
d631e4b611 | ||
|
|
3097afe082 | ||
|
|
fe22c83bef | ||
|
|
4684d487af | ||
|
|
7485befdfa | ||
|
|
313fd1558a | ||
|
|
e184e872a1 | ||
|
|
65bd0a8be6 | ||
|
|
1eadf5d287 | ||
|
|
541ef45b8e | ||
|
|
709c20ed6d | ||
|
|
6530211445 | ||
|
|
88a665f772 | ||
|
|
dc2b063fda | ||
|
|
1414f85484 | ||
|
|
2fd93bb2be | ||
|
|
1360789bc3 | ||
|
|
cecc905f58 | ||
|
|
1cda942e61 | ||
|
|
ab3a4289ea | ||
|
|
9bafdd3c06 |
No files matched your search
@@ -71,7 +71,7 @@ jobs:
|
||||
- run: git remote set-url origin https://github-actions[bot]:$NAV_DS_TOKEN@github.com/$GITHUB_REPOSITORY.git
|
||||
env:
|
||||
NAV_DS_TOKEN: ${{secrets.GIT_REPO}}
|
||||
- run: yarn lerna version patch --include-merged-tags --no-private --yes
|
||||
- run: yarn lerna version patch --include-merged-tags --yes
|
||||
- run: yarn lerna publish from-package --yes
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_AUTOMATION}}
|
||||
|
||||
@@ -111,3 +111,7 @@ utilities/**/css
|
||||
@navikt/ds-icons/NAV-ikonpakke-svg.zip
|
||||
*/**/NAV-ikonpakke-png.zip
|
||||
*/**/NAV-ikonpakke-svg.zip
|
||||
|
||||
react-docgen.json
|
||||
cjs
|
||||
esm
|
||||
+28
-3
@@ -1,7 +1,32 @@
|
||||
module.exports = {
|
||||
webpackFinal: async (config, { configType }) => {
|
||||
config.devServer = { stats: "errors-only" };
|
||||
return config;
|
||||
},
|
||||
devServer: { stats: "errors-only" },
|
||||
stories: [
|
||||
"../packages/**/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../@navikt/**/*.stories.@(js|jsx|ts|tsx)",
|
||||
"../.storybook/**/*.stories.@(mdx)",
|
||||
"../packages/**/*.stories.@(js|jsx|ts|tsx|mdx)",
|
||||
"../@navikt/**/*.stories.@(js|jsx|ts|tsx|mdx)",
|
||||
],
|
||||
addons: [
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-docs",
|
||||
{
|
||||
name: "@storybook/addon-storysource",
|
||||
options: {
|
||||
loaderOptions: {
|
||||
injectStoryParameters: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "@storybook/addon-essentials",
|
||||
options: {
|
||||
actions: false,
|
||||
controls: { hideNoControlsWarning: true },
|
||||
},
|
||||
},
|
||||
"@whitespace/storybook-addon-html",
|
||||
],
|
||||
addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
import { addons } from "@storybook/addons";
|
||||
import NavTheme from "./theme.js";
|
||||
|
||||
addons.setConfig({
|
||||
theme: NavTheme,
|
||||
});
|
||||
@@ -1,14 +1,13 @@
|
||||
import "nav-frontend-core";
|
||||
import "@navikt/ds-css/baseline/index.css";
|
||||
import "@navikt/ds-css/index.css";
|
||||
|
||||
export const parameters = {
|
||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||
options: {
|
||||
// Makes sure `all` story is first
|
||||
storySort: (a, b) => {
|
||||
if (a[0].indexOf("all") !== -1) return -1;
|
||||
if (b[0].indexOf("all") !== -1) return 1;
|
||||
return 0;
|
||||
storySort: {
|
||||
method: "",
|
||||
order: [],
|
||||
locales: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Meta } from "@storybook/addon-docs/blocks";
|
||||
|
||||
<Meta title="ds-react/Kom i gang" />
|
||||
|
||||
# Ta i bruk `@navikt/ds-react` pakken
|
||||
|
||||
## Oppsett
|
||||
|
||||
```bash
|
||||
yarn add @navikt/ds-react @navikt/ds-css
|
||||
```
|
||||
|
||||
Siden stilene ikke importeres direkte i komponentene, så må man selv importere ds-css.
|
||||
Dette gjøres for å la komponetene brukes i Nextjs prosjekter.
|
||||
|
||||
```bash
|
||||
import "@navikt/ds-css"
|
||||
```
|
||||
|
||||
Dette vil også legge css-variabler på :root. For å få dette til å fungere med IE11, kan denne pakken tas i bruk: https://jhildenbiddle.github.io/css-vars-ponyfill/#/
|
||||
|
||||
## Testing
|
||||
|
||||
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
|
||||
|
||||
```bash
|
||||
"moduleNameMapper": {
|
||||
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
|
||||
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
|
||||
}
|
||||
```
|
||||
|
||||
Dette vil remappe komponentene (og ikonpakken) til å bruke CommonJs versjonen for testing
|
||||
@@ -0,0 +1,6 @@
|
||||
import { create } from "@storybook/theming";
|
||||
|
||||
export default create({
|
||||
base: "light",
|
||||
brandTitle: "NAV Designsystem",
|
||||
});
|
||||
@@ -1,11 +1,31 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = (baseConfig) => {
|
||||
baseConfig.config.module.rules.push({
|
||||
test: /\.less$/,
|
||||
loaders: ["style-loader", "css-loader", "less-loader"],
|
||||
include: path.resolve(__dirname, "../packages/"),
|
||||
});
|
||||
baseConfig.config.module.rules.push(
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ["style-loader", "css-loader"],
|
||||
include: [
|
||||
path.resolve(__dirname, "../node_modules/@navikt/ds-css/index.css"),
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
loaders: ["style-loader", "css-loader", "less-loader"],
|
||||
include: path.resolve(__dirname, "../packages/"),
|
||||
}
|
||||
);
|
||||
baseConfig.config.resolve.alias = {
|
||||
...baseConfig.config.resolve?.alias,
|
||||
"./normalize.css": path.resolve(
|
||||
__dirname,
|
||||
"../node_modules/normalize.css/normalize.css"
|
||||
),
|
||||
"./@navikt/ds-tokens": path.resolve(
|
||||
__dirname,
|
||||
"../node_modules/@navikt/ds-tokens/dist/tokens.css"
|
||||
),
|
||||
};
|
||||
|
||||
return baseConfig.config;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
.navds-accordion-anchor-menu {
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
.navds-accordion-anchor-menu__title {
|
||||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
.navds-accordion-menu__list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
font: inherit;
|
||||
text-align: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
color: var(--navds-color-text-link);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable .navds-accordion-menu__list,
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
font-weight: var(--navds-font-weight-regular);
|
||||
}
|
||||
|
||||
.navds-accordion-menu-item,
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
display: flex;
|
||||
padding: 0.75rem 1rem;
|
||||
line-height: 1.5rem; /* TODO: fix typography. */
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable__expand-icon {
|
||||
font-size: 1.5rem;
|
||||
color: var(--navds-color-text-link);
|
||||
flex-shrink: 0;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable--open
|
||||
> .navds-accordion-menu-collapsable__button
|
||||
> .navds-accordion-menu-collapsable__expand-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable .navds-accordion-menu-item,
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-item,
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 3rem;
|
||||
}
|
||||
|
||||
.navds-accordion-menu-item:focus,
|
||||
.navds-accordion-menu-collapsable__button:focus {
|
||||
outline: 3px solid var(--navds-text-focus);
|
||||
outline-offset: -3px;
|
||||
}
|
||||
|
||||
.navds-accordion-menu-item:hover,
|
||||
.navds-accordion-menu-collapsable__button:hover {
|
||||
background-color: var(--navds-color-gray-20);
|
||||
}
|
||||
|
||||
.navds-accordion-menu-item--active {
|
||||
box-shadow: inset 0.5rem 0 var(--navds-color-text-link);
|
||||
color: var(--navds-color-text);
|
||||
text-decoration: none;
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
}
|
||||
@@ -24,7 +24,6 @@
|
||||
.navds-accordion__chevron {
|
||||
width: 1.25em;
|
||||
height: 1.25em;
|
||||
transition: 300ms transform;
|
||||
transform: rotateZ(0deg);
|
||||
flex-shrink: 0;
|
||||
margin-left: 1rem;
|
||||
File renamed without changes.
@@ -0,0 +1,35 @@
|
||||
@import "@navikt/ds-tokens";
|
||||
@import "normalize.css";
|
||||
@import "Source-Sans-Pro-regular.css";
|
||||
@import "Source-Sans-Pro-italic.css";
|
||||
@import "Source-Sans-Pro-600.css";
|
||||
@import "print.css";
|
||||
@import "utility.css";
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--navds-font-family);
|
||||
line-height: 1.375;
|
||||
color: var(--navds-color-text-primary);
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--navds-color-text-link);
|
||||
}
|
||||
|
||||
/* https://web.dev/prefers-reduced-motion/ */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, ::before, ::after {
|
||||
animation-delay: -1ms !important;
|
||||
animation-duration: 1ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
background-attachment: initial !important;
|
||||
scroll-behavior: auto !important;
|
||||
transition-duration: 0s !important;
|
||||
transition-delay: 0s !important;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@import url(~normalize.css);
|
||||
@import url(~@navikt/ds-tokens/dist/tokens.css);
|
||||
@import url(Source-Sans-Pro-regular.css);
|
||||
@import url(Source-Sans-Pro-italic.css);
|
||||
@import url(Source-Sans-Pro-600.css);
|
||||
@import url(print.css);
|
||||
@import url(utility.css);
|
||||
|
||||
body {
|
||||
font-family: var(--navds-font-family);
|
||||
line-height: 1.375;
|
||||
color: var(--navds-color-text-primary);
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--navds-color-text-link);
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,3 +1,23 @@
|
||||
/**************************
|
||||
* .navds-grid *
|
||||
**************************/
|
||||
|
||||
.navds-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
grid-gap: var(--navds-grid-gutter-small);
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-grid {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************
|
||||
* .navds-grid__cell *
|
||||
**************************/
|
||||
|
||||
.navds-grid__cell--xs-1 {
|
||||
grid-column: span 1;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
.navds-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
grid-gap: var(--navds-grid-gutter-small);
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-grid {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
@import "./grid.css";
|
||||
@import "./cell.css";
|
||||
@@ -0,0 +1,15 @@
|
||||
@import "baseline/baseline.css";
|
||||
@import "accordion.css";
|
||||
@import "accordion-anchor-menu.css";
|
||||
@import "accordion-menu.css";
|
||||
@import "alert.css";
|
||||
@import "button.css";
|
||||
@import "content-container.css";
|
||||
@import "grid.css";
|
||||
@import "internal-header.css";
|
||||
@import "layouts.css";
|
||||
@import "link.css";
|
||||
@import "modal.css";
|
||||
@import "popover.css";
|
||||
@import "tag.css";
|
||||
@import "typography.css";
|
||||
@@ -0,0 +1,72 @@
|
||||
/**************************
|
||||
* .navds-header *
|
||||
**************************/
|
||||
|
||||
.navds-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--navds-color-darkgray);
|
||||
color: white;
|
||||
max-width: 100vw;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.navds-header__column {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* .navds-header__title *
|
||||
**************************/
|
||||
|
||||
.navds-header__title {
|
||||
padding: 0 1.5rem 0 1.5rem;
|
||||
border-right: 1px solid var(--navds-color-gray-40);
|
||||
display: flex;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
color: var(--navds-color-text-inverse);
|
||||
font-size: var(--navds-font-size-medium);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-medium);
|
||||
}
|
||||
|
||||
.navds-header__title > span > a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.navds-header__title > span > a:focus {
|
||||
box-shadow: var(--navds-shadow-focus-on-dark);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* .navds-header__user *
|
||||
**************************/
|
||||
|
||||
.navds-header__user {
|
||||
color: var(--navds-color-text-inverse);
|
||||
padding: 0 1.5rem 0 1.5rem;
|
||||
margin-left: auto;
|
||||
border-left: 1px solid var(--navds-color-gray-40);
|
||||
display: flex;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navds-header__name {
|
||||
margin-right: 1rem;
|
||||
font-size: var(--navds-font-size-small);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-small);
|
||||
}
|
||||
|
||||
.navds-header__ident {
|
||||
font-size: var(--navds-font-size-xs);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-xs);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
@import "./title.css";
|
||||
@import "./user.css";
|
||||
|
||||
.navds-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--navds-color-darkgray);
|
||||
color: white;
|
||||
max-width: 100vw;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.navds-header__column {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
.navds-header__title {
|
||||
padding: 0 1.5rem 0 1.5rem;
|
||||
border-right: 1px solid var(--navds-color-gray-40);
|
||||
display: flex;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
color: var(--navds-color-text-inverse);
|
||||
font-size: var(--navds-font-size-medium);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-medium);
|
||||
}
|
||||
|
||||
.navds-header__title > span > a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.navds-header__title > span > a:focus {
|
||||
box-shadow: var(--navds-shadow-focus-on-dark);
|
||||
outline: none;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
.navds-header__user {
|
||||
color: var(--navds-color-text-inverse);
|
||||
padding: 0 1.5rem 0 1.5rem;
|
||||
margin-left: auto;
|
||||
border-left: 1px solid var(--navds-color-gray-40);
|
||||
display: flex;
|
||||
align-self: stretch;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navds-header__name {
|
||||
margin-right: 1rem;
|
||||
font-size: var(--navds-font-size-small);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-small);
|
||||
}
|
||||
|
||||
.navds-header__ident {
|
||||
font-size: var(--navds-font-size-xs);
|
||||
font-weight: var(--navds-font-weight-bold);
|
||||
line-height: var(--navds-font-line-height-xs);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import "./layout.css";
|
||||
@@ -1,117 +0,0 @@
|
||||
.navds-layout__container {
|
||||
display: grid;
|
||||
grid-gap: var(--navds-grid-gutter-small);
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns,
|
||||
.navds-layout__container--2-columns {
|
||||
max-width: 60rem;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns {
|
||||
max-width: 79.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section--white > * {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.navds-layout__section--padding > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__section--sticky > * {
|
||||
top: var(--navds-grid-gutter-small);
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
.navds-layout__section--left,
|
||||
.navds-layout__section--main,
|
||||
.navds-layout__section--right {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--left > *,
|
||||
.navds-layout__section--padding.navds-layout__section--main > *,
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns > .navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 10;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--left,
|
||||
.navds-layout__container--2-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 2;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-column: span 4;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 6;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
/*****************
|
||||
* .navds-layout *
|
||||
*****************/
|
||||
|
||||
.navds-layout__container {
|
||||
display: grid;
|
||||
grid-gap: var(--navds-grid-gutter-small);
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns,
|
||||
.navds-layout__container--2-columns {
|
||||
max-width: 60rem;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns {
|
||||
max-width: 79.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section--white > * {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.navds-layout__section--padding > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__section--sticky > * {
|
||||
top: calc(var(--navds-grid-gutter-small) + var(--decorator-sticky-offset));
|
||||
position: sticky;
|
||||
}
|
||||
|
||||
.navds-layout__section > *:not(:last-child) {
|
||||
margin-bottom: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__section--left,
|
||||
.navds-layout__section--main,
|
||||
.navds-layout__section--right {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section > *:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--left > *,
|
||||
.navds-layout__section--padding.navds-layout__section--main > *,
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
.navds-layout__container {
|
||||
grid-gap: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__section--padding.navds-layout__section--right > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns > .navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 10;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--left,
|
||||
.navds-layout__container--2-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.navds-layout__container--2-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 2;
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-column: span 4;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navds-layout__section--padding.navds-layout__section--left > * {
|
||||
padding: var(--navds-layout-padding-small);
|
||||
}
|
||||
|
||||
.navds-layout__container--1-columns > .navds-layout__section--main {
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--left {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--main {
|
||||
grid-row: 1;
|
||||
grid-column: span 6;
|
||||
}
|
||||
|
||||
.navds-layout__container--3-columns > .navds-layout__section--right {
|
||||
grid-row: 1;
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__header *
|
||||
************************/
|
||||
|
||||
.navds-layout__header {
|
||||
background: var(--navds-layout-background-white);
|
||||
}
|
||||
|
||||
.navds-layout__header-content {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
.navds-layout__header-title {
|
||||
margin: 0.25rem 0.85rem;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__header-title {
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__body *
|
||||
************************/
|
||||
|
||||
.navds-layout__body {
|
||||
background: var(--navds-layout-background-gray);
|
||||
}
|
||||
|
||||
.navds-layout__body--white {
|
||||
background: var(--navds-layout-background-white);
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
.navds-layout__body--2-columns.navds-layout__body--padding {
|
||||
padding-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.navds-layout__body--3-columns.navds-layout__body--padding {
|
||||
padding-top: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
* .navds-layout__panel *
|
||||
************************/
|
||||
|
||||
.navds-layout__panel {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
padding: var(--navds-layout-padding-small);
|
||||
background: white;
|
||||
padding-top: 2.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel--icon-margin {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-small);
|
||||
}
|
||||
|
||||
.navds-layout__panel--highlight {
|
||||
box-shadow: rgb(102, 164, 220) 0 0 0 0.15rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-content {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-icon {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
top: -2rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel-icon svg,
|
||||
.navds-layout__panel-icon img {
|
||||
background: #c7dbed;
|
||||
border-radius: 2rem;
|
||||
padding: 1rem;
|
||||
height: 4rem;
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-title {
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy-icon {
|
||||
color: var(--navds-color-text-link);
|
||||
margin-right: 0.5rem;
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-popover-content {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__panel-copy-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
margin: 0 1rem 0 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 448px) {
|
||||
.navds-layout__panel {
|
||||
padding: var(--navds-layout-padding-medium-and-larger);
|
||||
}
|
||||
|
||||
.navds-layout__panel:not(:last-child) {
|
||||
margin-bottom: var(--navds-grid-gutter-medium-and-larger);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 448px) and (max-width: 959px) {
|
||||
.navds-layout__section .navds-accordion-anchor-menu__title {
|
||||
margin-left: 2.5rem;
|
||||
margin-right: 2.5rem;
|
||||
}
|
||||
.navds-layout__section .navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 2.5rem;
|
||||
padding-right: 2.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 3.5rem;
|
||||
padding-right: 3.5rem;
|
||||
}
|
||||
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-item,
|
||||
.navds-layout__section
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable
|
||||
.navds-accordion-menu-collapsable__button {
|
||||
padding-left: 4.5rem;
|
||||
padding-right: 4.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 648px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--2-columns .navds-layout__panel--icon-margin:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
/* prettier-ignore */
|
||||
.navds-layout__container--3-columns .navds-layout__panel--icon-margin:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.navds-layout__panel--icon-margin:not(:first-child) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "0.1.17",
|
||||
"version": "0.2.5",
|
||||
"private": false,
|
||||
"description": "Css for NAV Designsystem components",
|
||||
"author": "NAV Designsystem team",
|
||||
@@ -15,8 +15,16 @@
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@navikt/ds-tokens": "^0.1.0",
|
||||
"normalize.css": "^8.0.1"
|
||||
"main": "./dist/index.css",
|
||||
"scripts": {
|
||||
"build": "postcss --use postcss-import -o dist/index.css index.css",
|
||||
"watch-css": "postcss -w --use postcss-import -o dist/index.css index.css"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^0.1.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.2.7",
|
||||
"postcss-cli": "^8.3.1",
|
||||
"postcss-import": "^14.0.0"
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,6 @@
|
||||
box-shadow: 0 0.05rem 0.25rem 0.125rem rgba(0, 0, 0, 0.08);
|
||||
border: var(--navds-border-default);
|
||||
border-radius: 2px;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.navds-popover--small {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.navds-popover--hidden {
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"main": "index.js",
|
||||
"typings": "../esm/index.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// https://levelup.gitconnected.com/learn-svg-to-react-using-figma-api-be0a5f9c0ca
|
||||
// used for reference/implementation
|
||||
|
||||
const api = require("axios");
|
||||
import { create, get } from "axios";
|
||||
|
||||
// Requires user to add a personalized figma token in .env
|
||||
const headers = {
|
||||
@@ -11,7 +11,7 @@ const headers = {
|
||||
* Api connection for icon components
|
||||
* https://www.figma.com/file/UmEVH3pZ71uJPsSz9ilP3Y/NAV-ikoner-2.1-Figma-i-test?node-id=0%3A1
|
||||
*/
|
||||
const instanceFiles = api.create({
|
||||
const instanceFiles = create({
|
||||
baseURL: `https://api.figma.com/v1/files/${process.env.FILE_KEY}/components`,
|
||||
headers,
|
||||
});
|
||||
@@ -19,7 +19,7 @@ const instanceFiles = api.create({
|
||||
/**
|
||||
* api endpoint for images
|
||||
*/
|
||||
const instanceImages = api.create({
|
||||
const instanceImages = create({
|
||||
baseURL: `https://api.figma.com/v1/images/${process.env.FILE_KEY}`,
|
||||
headers,
|
||||
});
|
||||
@@ -45,9 +45,9 @@ const getSvgImageUrls = async (nodeIds) => {
|
||||
/**
|
||||
* Gets raw svg data from url
|
||||
*/
|
||||
const getIconContent = async (url) => api.get(url);
|
||||
const getIconContent = async (url) => get(url);
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
getNodeChildren,
|
||||
getSvgImageUrls,
|
||||
getIconContent,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const api = require("./api");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const pLimit = require("p-limit");
|
||||
const rimraf = require("rimraf");
|
||||
const startCase = require("lodash.startcase");
|
||||
import { getNodeChildren, getSvgImageUrls, getIconContent } from "./api";
|
||||
import { existsSync, unlinkSync, writeFileSync, mkdirSync } from "fs";
|
||||
import { resolve } from "path";
|
||||
import pLimit from "p-limit";
|
||||
import rimraf from "rimraf";
|
||||
import startCase from "lodash.startcase";
|
||||
|
||||
const generateMetadata = (iconNodesArr) => {
|
||||
return iconNodesArr
|
||||
@@ -32,14 +32,14 @@ const main = async () => {
|
||||
// Limiting to ~20 concurrent downloads seems to lead to fewer erros
|
||||
const limit = pLimit(20);
|
||||
|
||||
const iconNodesArr = await api.getNodeChildren().catch((e) => {
|
||||
const iconNodesArr = await getNodeChildren().catch((e) => {
|
||||
throw e;
|
||||
});
|
||||
|
||||
if (fs.existsSync(metadataFileName)) {
|
||||
fs.unlinkSync(metadataFileName);
|
||||
if (existsSync(metadataFileName)) {
|
||||
unlinkSync(metadataFileName);
|
||||
}
|
||||
fs.writeFileSync(
|
||||
writeFileSync(
|
||||
metadataFileName,
|
||||
JSON.stringify(generateMetadata(iconNodesArr), null, 4),
|
||||
{
|
||||
@@ -47,25 +47,24 @@ const main = async () => {
|
||||
}
|
||||
);
|
||||
|
||||
const iconUrls = await api.getSvgImageUrls(
|
||||
const iconUrls = await getSvgImageUrls(
|
||||
iconNodesArr.map((node) => node.node_id).join(",")
|
||||
);
|
||||
|
||||
if (fs.existsSync(iconFolder)) {
|
||||
if (existsSync(iconFolder)) {
|
||||
rimraf.sync(iconFolder);
|
||||
}
|
||||
fs.mkdirSync(iconFolder);
|
||||
mkdirSync(iconFolder);
|
||||
|
||||
console.log("Total icons: " + iconNodesArr.length);
|
||||
|
||||
await Promise.all(
|
||||
iconUrls.map((url, x) =>
|
||||
limit(() =>
|
||||
api
|
||||
.getIconContent(url)
|
||||
getIconContent(url)
|
||||
.then(({ data }) => {
|
||||
fs.writeFileSync(
|
||||
path.resolve(
|
||||
writeFileSync(
|
||||
resolve(
|
||||
iconFolder,
|
||||
`${startCase(iconNodesArr[x].name).replace(/\s/g, "")}.svg`
|
||||
),
|
||||
@@ -86,8 +85,8 @@ const main = async () => {
|
||||
);
|
||||
|
||||
if (misses.length > 0) {
|
||||
fs.writeFileSync(
|
||||
path.resolve("./", `misses.txt`),
|
||||
writeFileSync(
|
||||
resolve("./", `misses.txt`),
|
||||
JSON.stringify(misses, null, 4),
|
||||
{
|
||||
encoding: "utf8",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const fs = require("fs");
|
||||
const sharp = require("sharp");
|
||||
const rimraf = require("rimraf");
|
||||
const pLimit = require("p-limit");
|
||||
import { existsSync, mkdirSync, readdirSync } from "fs";
|
||||
import sharp from "sharp";
|
||||
import rimraf from "rimraf";
|
||||
import pLimit from "p-limit";
|
||||
|
||||
const convertToPng = async () => {
|
||||
const inputDir = "./svg/";
|
||||
@@ -11,14 +11,14 @@ const convertToPng = async () => {
|
||||
|
||||
const limit = pLimit(20);
|
||||
|
||||
if (fs.existsSync(outDir)) {
|
||||
if (existsSync(outDir)) {
|
||||
rimraf.sync(outDir);
|
||||
}
|
||||
fs.mkdirSync(outDir);
|
||||
sizes.forEach((size) => fs.mkdirSync(outDir + size.toString()));
|
||||
mkdirSync(outDir);
|
||||
sizes.forEach((size) => mkdirSync(outDir + size.toString()));
|
||||
|
||||
await Promise.all(
|
||||
fs.readdirSync(inputDir).map((file) => {
|
||||
readdirSync(inputDir).map((file) => {
|
||||
return limit(() =>
|
||||
sizes.forEach((size) => {
|
||||
const density = (100 * size) / 16;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const zipdir = require("zip-dir");
|
||||
import zipdir from "zip-dir";
|
||||
|
||||
const zipDir = async (dir, name) => {
|
||||
await zipdir(dir, { saveTo: name }, function (err, buffer) {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
{
|
||||
"name": "@navikt/ds-icons",
|
||||
"version": "0.1.7",
|
||||
"version": "0.2.1",
|
||||
"private": false,
|
||||
"description": "NAVs egne ikoner i SVG og React format",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler/tree/master/%40navikt/ds-icons"
|
||||
},
|
||||
"keywords": [
|
||||
"NAV",
|
||||
"designsystem",
|
||||
@@ -10,29 +14,31 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"author": "NAV",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"main": "esm/index.js",
|
||||
"module": "esm/index.js",
|
||||
"typings": "esm/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"files": [
|
||||
"/lib",
|
||||
"/cjs",
|
||||
"/esm",
|
||||
"/src",
|
||||
"/svg"
|
||||
],
|
||||
"scripts": {
|
||||
"cjs-package": "copyfiles -f config/package.json cjs",
|
||||
"dl-icons": "FILE_KEY=UmEVH3pZ71uJPsSz9ilP3Y node -r dotenv/config figma-api/index.js dotenv_config_path=figma-api/.env",
|
||||
"create-icons": "svgr --silent --typescript --ref --icon --title-prop --replace-attr-values \"#3E3832=currentColor\" -d src svg",
|
||||
"convert-icons": "node figma-api/pngConverter.js",
|
||||
"clean": "rm -rf src && rm -rf lib && rm -rf png && rm -rf NAV-ikonpakke-png.zip && rm -rf NAV-ikonpakke-svg.zip",
|
||||
"build": "npm run clean && npm run create-icons && tsc && npm run convert-icons && node figma-api/zipIcons.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler/tree/master/%40navikt/ds-icons"
|
||||
"clean": "rm -rf src && rm -rf esm && rm -rf cjs && rm -rf png && rm -rf NAV-ikonpakke-png.zip && rm -rf NAV-ikonpakke-svg.zip",
|
||||
"build": "npm run clean && npm run create-icons && tsc && tsc -p tsconfig-esm.json && yarn cjs-package && npm run convert-icons && node figma-api/zipIcons.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/cli": "^5.4.0",
|
||||
"copyfiles": "^2.4.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"lodash.kebabcase": "^4.1.1",
|
||||
"lodash.startcase": "4.4.0",
|
||||
@@ -40,6 +46,5 @@
|
||||
"rimraf": "3.0.2",
|
||||
"sharp": "0.27.1",
|
||||
"zip-dir": "^2.0.0"
|
||||
},
|
||||
"sideEffects": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Meta } from "@storybook/addon-docs/blocks";
|
||||
|
||||
<Meta title="ds-icons/Kom i gang" />
|
||||
|
||||
# Ta i bruk ikonpakken `@navikt/ds-icons`
|
||||
|
||||
Alle ikoner kan bli funnet her https://design.nav.no/resources/icons
|
||||
|
||||
## Oppsett
|
||||
|
||||
```bash
|
||||
yarn add @navikt/ds-icons
|
||||
```
|
||||
|
||||
```bash
|
||||
Import { Expand } from `@navikt/ds-icons`;
|
||||
|
||||
<Expand
|
||||
aria-label="Åpne meny"
|
||||
role="img"
|
||||
focusable="false"
|
||||
/>
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
For å støtte testing med eks Jest som ikke tillater ESM moduler, så kan denne configen legges til
|
||||
|
||||
```bash
|
||||
"moduleNameMapper": {
|
||||
"@navikt/ds-react(.*)": "@navikt/ds-react/cjs$1",
|
||||
"@navikt/ds-icons(.*)": "@navikt/ds-icons/cjs$1"
|
||||
}
|
||||
```
|
||||
|
||||
Dette vil remappe Ikonpakken (og komponentpakken) til å bruke CommonJs versjonen for testing
|
||||
@@ -1,35 +1,65 @@
|
||||
import React from "react";
|
||||
// also exported from '@storybook/react' if you can deal with breaking changes in 6.1
|
||||
// import { Story, Meta } from '@storybook/react/types-6-0';
|
||||
import { storiesOf } from "@storybook/react";
|
||||
|
||||
import * as Icons from "../src";
|
||||
export default {
|
||||
title: "ds-icons/Ikoner",
|
||||
argTypes: {
|
||||
Icon: {
|
||||
defaultValue: "System",
|
||||
control: {
|
||||
type: "select",
|
||||
options: Object.entries(Icons).map(([Name, _]) => Name),
|
||||
},
|
||||
},
|
||||
color: { control: "color" },
|
||||
},
|
||||
};
|
||||
|
||||
const iconsStories = storiesOf("@navikt/icons", module);
|
||||
if (process.env.STORYBOOK_CHROMATIC === "true") {
|
||||
const iconsStories = storiesOf("ds-icons/Ikoner", module);
|
||||
|
||||
Object.entries(Icons).forEach(([name, Icon]) => {
|
||||
iconsStories.add(name, () => (
|
||||
<div>
|
||||
<Icon title="hello, world" />
|
||||
<Icon style={{ height: "2em", width: "2em" }} />
|
||||
<Icon style={{ height: "4em", width: "4em" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", color: "white" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", color: "crimson" }} />
|
||||
<br />
|
||||
<Icon style={{ height: "4em", width: "4em", backgroundColor: "#aaa" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", backgroundColor: "#777" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", backgroundColor: "#333" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", backgroundColor: "#000" }} />
|
||||
<br />
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(45deg)" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(90deg)" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(180deg)" }}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
});
|
||||
Object.entries(Icons).forEach(([name, Icon]) => {
|
||||
iconsStories.add(name, () => (
|
||||
<div>
|
||||
<Icon title="hello, world" />
|
||||
<Icon style={{ height: "2em", width: "2em" }} />
|
||||
<Icon style={{ height: "4em", width: "4em" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", color: "white" }} />
|
||||
<Icon style={{ height: "4em", width: "4em", color: "crimson" }} />
|
||||
<br />
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", backgroundColor: "#aaa" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", backgroundColor: "#777" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", backgroundColor: "#333" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", backgroundColor: "#000" }}
|
||||
/>
|
||||
<br />
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(45deg)" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(90deg)" }}
|
||||
/>
|
||||
<Icon
|
||||
style={{ height: "4em", width: "4em", transform: "rotate(180deg)" }}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
const Template = ({ Icon, color, size, ...args }) => {
|
||||
const Iconname = Icons[Icon];
|
||||
return <Iconname style={{ fontSize: size, color }} {...args} />;
|
||||
};
|
||||
export const Ikon = Template.bind({});
|
||||
Ikon.args = {
|
||||
size: "24px",
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../utilities/build/tsconfig-pakker.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"esModuleInterop": true,
|
||||
"module": "ES2020",
|
||||
"target": "ES2015",
|
||||
"outDir": "./esm",
|
||||
"sourceMap": true,
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"extends": "../../utilities/build/tsconfig-pakker.json",
|
||||
"compilerOptions": {
|
||||
"module": "ES6",
|
||||
"outDir": "./lib",
|
||||
"module": "commonjs",
|
||||
"outDir": "./cjs",
|
||||
"target": "es2015",
|
||||
"rootDir": "./src",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true
|
||||
"sourceMap": false,
|
||||
"declaration": false
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import { AccordionMenu as BaseAccordionMenu } from "../accordion-menu";
|
||||
import { Heading } from "../index";
|
||||
import { ActiveAnchorProvider } from "./ActiveAnchorStore";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface AccordionAnchorMenuProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
title?: string;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionAnchorMenu = forwardRef<
|
||||
HTMLDivElement,
|
||||
AccordionAnchorMenuProps
|
||||
>(({ children, title, className, ...rest }, ref) => (
|
||||
<div
|
||||
className={cl("navds-accordion-anchor-menu", className)}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
{title && (
|
||||
<Heading
|
||||
level={2}
|
||||
size="medium"
|
||||
className="navds-accordion-anchor-menu__title"
|
||||
>
|
||||
{title}
|
||||
</Heading>
|
||||
)}
|
||||
<ActiveAnchorProvider>
|
||||
<BaseAccordionMenu aria-label={title || "Meny"}>
|
||||
{children}
|
||||
</BaseAccordionMenu>
|
||||
</ActiveAnchorProvider>
|
||||
</div>
|
||||
));
|
||||
|
||||
export default AccordionAnchorMenu;
|
||||
@@ -0,0 +1 @@
|
||||
export { AccordionMenuCollapsable as AccordionAnchorMenuCollapsable } from "../accordion-menu";
|
||||
@@ -0,0 +1,39 @@
|
||||
import React, { forwardRef, useEffect } from "react";
|
||||
import { AccordionMenuItem, AccordionMenuItemType } from "../accordion-menu";
|
||||
import { useStore } from "./ActiveAnchorStore";
|
||||
|
||||
const AccordionAnchorMenuItem: AccordionMenuItemType = forwardRef(
|
||||
(props, ref) => {
|
||||
const isAnchorActive = useIsAnchorActive(
|
||||
props.href && props.href.split("#")[1]
|
||||
);
|
||||
|
||||
return (
|
||||
<AccordionMenuItem
|
||||
{...props}
|
||||
ref={ref}
|
||||
active={props.active || isAnchorActive}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const useIsAnchorActive = (anchor: string | undefined) => {
|
||||
const { activeAnchor, registerAnchor, unregisterAnchor } = useStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (anchor) {
|
||||
const target = document.getElementById(anchor);
|
||||
if (target) {
|
||||
registerAnchor(anchor);
|
||||
return () => {
|
||||
unregisterAnchor(anchor);
|
||||
};
|
||||
}
|
||||
}
|
||||
}, [anchor, registerAnchor, unregisterAnchor]);
|
||||
|
||||
return (anchor && activeAnchor === anchor) || false;
|
||||
};
|
||||
|
||||
export default AccordionAnchorMenuItem;
|
||||
@@ -0,0 +1,69 @@
|
||||
import React, {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
} from "react";
|
||||
|
||||
export interface ActiveAnchorStore {
|
||||
activeAnchor?: string;
|
||||
registerAnchor: (anchor: string) => void;
|
||||
unregisterAnchor: (anchor: string) => void;
|
||||
}
|
||||
|
||||
export const ActiveAnchorContext = createContext({} as ActiveAnchorStore);
|
||||
export const ActiveAnchorProvider = ({ children }) => {
|
||||
const [anchors, setAnchors] = useState<string[]>([]);
|
||||
const [activeAnchor, setActiveAnchor] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
const scrollListener = () => {
|
||||
const offset = 100;
|
||||
const lastPassedAnchor = anchors
|
||||
.map((anchor) => document.getElementById(anchor))
|
||||
.map((element: HTMLElement) => ({
|
||||
id: element.id,
|
||||
top: element.getBoundingClientRect().top - offset,
|
||||
scrolledToBottom:
|
||||
window.innerHeight + window.pageYOffset >=
|
||||
document.body.offsetHeight,
|
||||
}))
|
||||
.filter((element) => element.scrolledToBottom || element.top <= 0)
|
||||
.sort((a, b) => (a.top < b.top ? -1 : 1))
|
||||
.map((anchor) => anchor.id)
|
||||
.pop();
|
||||
|
||||
// Set active anchor and related url hash
|
||||
if (lastPassedAnchor && activeAnchor !== lastPassedAnchor) {
|
||||
const { href, hash } = window.location;
|
||||
const urlWithoutHash = href.replace(hash, "");
|
||||
const urlWithAnchor = `${urlWithoutHash}#${lastPassedAnchor}`;
|
||||
const title = document.title;
|
||||
window.history.pushState(lastPassedAnchor, title, urlWithAnchor);
|
||||
setActiveAnchor(lastPassedAnchor);
|
||||
}
|
||||
};
|
||||
window.addEventListener("scroll", scrollListener);
|
||||
return () => {
|
||||
window.removeEventListener("scroll", scrollListener);
|
||||
};
|
||||
}, [anchors, activeAnchor]);
|
||||
|
||||
return (
|
||||
<ActiveAnchorContext.Provider
|
||||
value={{
|
||||
activeAnchor,
|
||||
registerAnchor: useCallback((anchor) => {
|
||||
setAnchors((anchors) => [...anchors, anchor]);
|
||||
}, []),
|
||||
unregisterAnchor: useCallback((anchor) => {
|
||||
setAnchors((anchors) => anchors.filter((a) => a !== anchor));
|
||||
}, []),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ActiveAnchorContext.Provider>
|
||||
);
|
||||
};
|
||||
export const useStore = () => useContext(ActiveAnchorContext);
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default as AccordionAnchorMenu } from "./AccordionAnchorMenu";
|
||||
export { AccordionAnchorMenuCollapsable } from "./AccordionAnchorMenuCollapsable";
|
||||
export { default as AccordionAnchorMenuItem } from "./AccordionAnchorMenuItem";
|
||||
@@ -0,0 +1,141 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
AccordionAnchorMenu as Menu,
|
||||
AccordionAnchorMenuCollapsable as Collapsable,
|
||||
AccordionAnchorMenuItem as Item,
|
||||
} from "../index";
|
||||
import { useEffect } from "react";
|
||||
import { ProductPageLayout } from "../../index";
|
||||
import { Right } from "../../layouts/stories/components/sections/Right";
|
||||
import { LightBulb, Telephone } from "@navikt/ds-icons";
|
||||
import { MainOne } from "../../layouts/stories/components/sections/Main";
|
||||
import { MainTwo } from "../../layouts/stories/components/sections/Main";
|
||||
import { MainThree } from "../../layouts/stories/components/sections/Main";
|
||||
import { Link, HashRouter as Router } from "react-router-dom";
|
||||
|
||||
export default {
|
||||
title: "ds-react/accordion-anchor-menu",
|
||||
component: { Menu },
|
||||
decorators: [
|
||||
(Story) => {
|
||||
useEffect(() => {
|
||||
document.getElementById("decorator-header").style.display = "block";
|
||||
document.getElementById("decorator-footer").style.display = "block";
|
||||
return () => {
|
||||
document.getElementById("decorator-header").style.display = "none";
|
||||
document.getElementById("decorator-footer").style.display = "none";
|
||||
};
|
||||
}, []);
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
};
|
||||
|
||||
export const All = () => (
|
||||
<ProductPageLayout title={"Nunc et lorem"}>
|
||||
<ProductPageLayout.Section left sticky withPadding={false}>
|
||||
<Menu title={"Minima"} smoothScrollBehavior>
|
||||
<Item href={"#leo-quis"}>Leo quis</Item>
|
||||
<Collapsable title={"Proin accumsan"}>
|
||||
<Item href={"#nulla-pariatur"}>Nulla pariatur</Item>
|
||||
<Item href={"#luctus-justo"}>Luctus justo</Item>
|
||||
</Collapsable>
|
||||
<Item href={"#maecenas-in-pretium"}>Maecenas in pretium</Item>
|
||||
</Menu>
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section whiteBackground={false} withPadding={false}>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Proin accumsan"}
|
||||
anchor={"proin-accumsan"}
|
||||
>
|
||||
<MainTwo title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section right sticky>
|
||||
<Right />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
|
||||
export const ReactRouter = () => (
|
||||
<ProductPageLayout title={"Nunc et lorem"}>
|
||||
<ProductPageLayout.Section left sticky withPadding={false}>
|
||||
<Menu>
|
||||
<Item component={Link} to="/link1">
|
||||
Leo quis
|
||||
</Item>
|
||||
<Collapsable title={"Proin accumsan"}>
|
||||
<Item component={Link} to="/link2">
|
||||
Nulla pariatur
|
||||
</Item>
|
||||
<Item component={Link} to="/link3">
|
||||
Luctus justo
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Collapsable title={"Sint cupidatat"}>
|
||||
<Item component={Link} to="/link4">
|
||||
Nulla pariatur
|
||||
</Item>
|
||||
<Item component={Link} to="/link5">
|
||||
Luctus justo
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Item component={Link} to="/link6">
|
||||
Maecenas in pretium
|
||||
</Item>
|
||||
</Menu>
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section whiteBackground={false} withPadding={false}>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Proin accumsan"}
|
||||
anchor={"proin-accumsan"}
|
||||
>
|
||||
<MainTwo title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section right sticky>
|
||||
<Right />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
|
||||
ReactRouter.decorators = [
|
||||
(Story) => (
|
||||
<Router>
|
||||
<Story />
|
||||
</Router>
|
||||
),
|
||||
];
|
||||
@@ -0,0 +1,25 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import MenuItems from "./MenuItems";
|
||||
|
||||
export interface AccordionMenuProps extends HTMLAttributes<HTMLElement> {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionMenu = forwardRef<HTMLElement, AccordionMenuProps>(
|
||||
({ children, className, ...rest }, ref) => {
|
||||
return (
|
||||
<nav
|
||||
role="navigation"
|
||||
ref={ref}
|
||||
className={cl("navds-accordion-menu", className)}
|
||||
{...rest}
|
||||
>
|
||||
<MenuItems>{children}</MenuItems>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default AccordionMenu;
|
||||
@@ -0,0 +1,44 @@
|
||||
import React, { forwardRef, HTMLAttributes, useState } from "react";
|
||||
import cl from "classnames";
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import MenuItems from "./MenuItems";
|
||||
|
||||
export interface AccordionMenuCollapsableProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
title: string;
|
||||
defaultOpen?: boolean;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AccordionMenuCollapsable = forwardRef<
|
||||
HTMLDivElement,
|
||||
AccordionMenuCollapsableProps
|
||||
>(({ children, defaultOpen = false, title, className, ...rest }, ref) => {
|
||||
const [isOpen, setIsOpen] = useState(defaultOpen);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cl("navds-accordion-menu-collapsable", className, {
|
||||
"navds-accordion-menu-collapsable--open": isOpen,
|
||||
})}
|
||||
{...rest}
|
||||
>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="navds-accordion-menu-collapsable__button"
|
||||
>
|
||||
{title}
|
||||
<Expand
|
||||
role="img"
|
||||
aria-label={isOpen ? "Pil peker opp" : "Pil peker ned"}
|
||||
className="navds-accordion-menu-collapsable__expand-icon"
|
||||
/>
|
||||
</button>
|
||||
{isOpen && <MenuItems>{children}</MenuItems>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default AccordionMenuCollapsable;
|
||||
@@ -0,0 +1,40 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "../util";
|
||||
import cl from "classnames";
|
||||
|
||||
export type AccordionMenuItemType = OverridableComponent<AccordionMenuItemProps>;
|
||||
|
||||
export interface AccordionMenuItemProps {
|
||||
props: {
|
||||
children: React.ReactNode;
|
||||
active?: boolean;
|
||||
} & React.HTMLAttributes<HTMLAnchorElement>;
|
||||
defaultComponent: "a";
|
||||
}
|
||||
|
||||
const AccordionMenuItem: AccordionMenuItemType = forwardRef(
|
||||
(
|
||||
{
|
||||
children,
|
||||
component: Component = "a",
|
||||
active = false,
|
||||
className,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
ref={ref}
|
||||
className={cl("navds-accordion-menu-item", className, {
|
||||
"navds-accordion-menu-item--active": active,
|
||||
})}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default AccordionMenuItem;
|
||||
@@ -0,0 +1,16 @@
|
||||
import React from "react";
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
const MenuItems = ({ children }) => (
|
||||
<ul className="navds-accordion-menu__list">
|
||||
{React.Children.toArray(children).map((child, i) => (
|
||||
<li key={i} className="navds-accordion-menu__list-item">
|
||||
{child}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
|
||||
export default MenuItems;
|
||||
@@ -0,0 +1,6 @@
|
||||
export { default as AccordionMenu } from "./AccordionMenu";
|
||||
export { default as AccordionMenuCollapsable } from "./AccordionMenuCollapsable";
|
||||
export {
|
||||
default as AccordionMenuItem,
|
||||
AccordionMenuItemType,
|
||||
} from "./AccordionMenuItem";
|
||||
@@ -0,0 +1,160 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
AccordionMenu,
|
||||
AccordionMenuItem as Item,
|
||||
AccordionMenuCollapsable as Collapsable,
|
||||
} from "../index";
|
||||
import { NavLink, HashRouter as Router } from "react-router-dom";
|
||||
|
||||
export default {
|
||||
title: "ds-react/accordion-menu",
|
||||
component: { AccordionMenu },
|
||||
parameters: {
|
||||
backgrounds: {
|
||||
default: "light",
|
||||
values: [
|
||||
{
|
||||
name: "light",
|
||||
value: "#F1F1F1",
|
||||
},
|
||||
{
|
||||
name: "white",
|
||||
value: "#fff",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const All = () => (
|
||||
<div
|
||||
style={{
|
||||
background: "white",
|
||||
maxWidth: 288,
|
||||
}}
|
||||
>
|
||||
<AccordionMenu>
|
||||
<Item href="#leo">Leo</Item>
|
||||
<Collapsable title="Proin">
|
||||
<Item href="#nulla" active>
|
||||
Nulla
|
||||
</Item>
|
||||
<Item href="#luctus">Luctus</Item>
|
||||
</Collapsable>
|
||||
<Collapsable title="Accumsan">
|
||||
<Item href="#justo" ariaCurrent="page">
|
||||
Justo
|
||||
</Item>
|
||||
<Item href="#pariatur" active ariaCurrent="page">
|
||||
Pariatur
|
||||
</Item>
|
||||
<Collapsable title="Proin">
|
||||
<Item href="#nulla" active>
|
||||
Nulla
|
||||
</Item>
|
||||
<Item href="#luctus">Luctus</Item>
|
||||
</Collapsable>
|
||||
</Collapsable>
|
||||
<Item href="#justo" active>
|
||||
Justo
|
||||
</Item>
|
||||
<Item href="#pariatur">Pariatur</Item>
|
||||
</AccordionMenu>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const ReactRouter = () => (
|
||||
<AccordionMenu>
|
||||
<Collapsable title="Nivå 1 – 3 rems høy">
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/1"
|
||||
>
|
||||
Nivå 2 innrykk 2 rems
|
||||
</Item>
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/2"
|
||||
>
|
||||
Subtitle 3
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Collapsable title="Skjema og søknad">
|
||||
<Collapsable title="Satser">
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/3"
|
||||
>
|
||||
Nivå 3 – 3 rems innrykk Har du rett til dagpenger når du mottar annen
|
||||
økonomisk støtte fra NAV?
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/4"
|
||||
>
|
||||
Subtitle 2
|
||||
</Item>
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/5"
|
||||
>
|
||||
Subtitle 3
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Collapsable title="Sakbehandlingstider">
|
||||
<Collapsable title="Subtitle 4 Lang tittel på andre nivå lorem ipsum">
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/6"
|
||||
>
|
||||
Subtitle 5
|
||||
</Item>
|
||||
</Collapsable>
|
||||
</Collapsable>
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/7"
|
||||
>
|
||||
Internasjonalt
|
||||
</Item>
|
||||
<Collapsable title="Meld fra om endringer lang tittel på første nivå">
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/8"
|
||||
>
|
||||
Subtitle 6
|
||||
</Item>
|
||||
</Collapsable>
|
||||
<Item
|
||||
component={NavLink}
|
||||
activeClassName="navds-accordion-menu-item--active"
|
||||
to="/9"
|
||||
>
|
||||
Nivå 1
|
||||
</Item>
|
||||
</AccordionMenu>
|
||||
);
|
||||
|
||||
ReactRouter.decorators = [
|
||||
(Story) => (
|
||||
<Router>
|
||||
<div
|
||||
style={{
|
||||
background: "white",
|
||||
maxWidth: 288,
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</div>
|
||||
</Router>
|
||||
),
|
||||
];
|
||||
@@ -1,17 +1,39 @@
|
||||
import React, { forwardRef, useEffect, useRef, useState } from "react";
|
||||
import cl from "classnames";
|
||||
import { UnmountClosed, Collapse } from "react-collapse";
|
||||
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import "@navikt/ds-css/accordion/index.css";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
export interface AccordionProps
|
||||
extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Content on interactive surface of component
|
||||
*/
|
||||
heading: React.ReactNode;
|
||||
/**
|
||||
* Opens component if 'true', closes if 'false'
|
||||
* Using this props removes automatic control of open-state
|
||||
* @default false
|
||||
*/
|
||||
open?: boolean;
|
||||
/**
|
||||
* Callback for when user interacts with component
|
||||
*
|
||||
* @param {object} event
|
||||
*/
|
||||
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||
/**
|
||||
* Removes content-element from dom when closed
|
||||
* @default false
|
||||
*/
|
||||
renderContentWhenClosed?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState } from "react";
|
||||
import { Accordion } from "../index";
|
||||
|
||||
export default {
|
||||
title: "@navikt/accordion",
|
||||
title: "ds-react/accordion",
|
||||
component: Accordion,
|
||||
};
|
||||
|
||||
|
||||
@@ -6,11 +6,24 @@ import {
|
||||
InformationFilled,
|
||||
SuccessFilled,
|
||||
} from "@navikt/ds-icons";
|
||||
import "@navikt/ds-css/alert/index.css";
|
||||
|
||||
export interface AlertProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Decides what design the alert will have
|
||||
*/
|
||||
variant: "error" | "warning" | "info" | "success";
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Reduces padding on component
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Alert } from "../index";
|
||||
|
||||
export default {
|
||||
title: "@navikt/alert",
|
||||
title: "ds-react/alert",
|
||||
component: Alert,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/button/index.css";
|
||||
|
||||
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Decides component design and interactions
|
||||
* @default "primary"
|
||||
*/
|
||||
variant?: "primary" | "secondary" | "action" | "danger";
|
||||
/**
|
||||
* Reduces internal padding for component
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
/**
|
||||
* Prevent the user from interacting with the button: it cannot be pressed or focused.
|
||||
* @default false
|
||||
*/
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Button } from "../index";
|
||||
|
||||
export default {
|
||||
title: "@navikt/button",
|
||||
title: "ds-react/button",
|
||||
component: Button,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"type": "commonjs",
|
||||
"main": "index.js",
|
||||
"typings": "../esm/index.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/content-container/index.css";
|
||||
|
||||
export type ContentContainerProps = HTMLAttributes<HTMLDivElement>;
|
||||
export interface ContentContainerProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
classNames?: string;
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const ContentContainer = forwardRef<HTMLDivElement, ContentContainerProps>(
|
||||
({ children, className, ...rest }, ref) => (
|
||||
<div
|
||||
|
||||
@@ -5,7 +5,7 @@ import "./style.css";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default {
|
||||
title: "@navikt/content-container",
|
||||
title: "ds-react/content-container",
|
||||
component: ContentContainer,
|
||||
decorators: [
|
||||
(Story) => {
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/grid/index.css";
|
||||
|
||||
type Column = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
||||
export interface CellProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* Cell columns on width < 448px
|
||||
*/
|
||||
xs: Column;
|
||||
/**
|
||||
* Cell columns on min-width: 448
|
||||
*/
|
||||
sm?: Column;
|
||||
/**
|
||||
* Cell columns on min-width: 648
|
||||
*/
|
||||
md?: Column;
|
||||
/**
|
||||
* Cell columns on min-width: 960px
|
||||
*/
|
||||
lg?: Column;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/grid/index.css";
|
||||
|
||||
export type GridProps = HTMLAttributes<HTMLDivElement>;
|
||||
export interface GridProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
const Grid = forwardRef<HTMLDivElement, GridProps>(
|
||||
({ children, className, ...rest }, ref) => (
|
||||
<div ref={ref} className={cl("navds-grid", className)} {...rest}>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ContentContainer } from "../../index";
|
||||
import "./styles.css";
|
||||
|
||||
export default {
|
||||
title: "@navikt/grid",
|
||||
title: "ds-react/grid",
|
||||
component: { Grid, Cell },
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
export {
|
||||
AccordionAnchorMenu,
|
||||
AccordionAnchorMenuCollapsable,
|
||||
AccordionAnchorMenuItem,
|
||||
} from "./accordion-anchor-menu";
|
||||
export {
|
||||
AccordionMenu,
|
||||
AccordionMenuCollapsable,
|
||||
AccordionMenuItem,
|
||||
} from "./accordion-menu";
|
||||
export { Accordion, AccordionProps } from "./accordion/index";
|
||||
export { Alert, AlertProps } from "./alert/index";
|
||||
export { Button, ButtonProps } from "./button/index";
|
||||
@@ -14,7 +24,11 @@ export {
|
||||
InternalHeaderUser,
|
||||
InternalHeaderUserProps,
|
||||
} from "./internal-header/index";
|
||||
export { Layout, LayoutProps, SectionProps } from "./layout/index";
|
||||
export {
|
||||
ProductPageLayout,
|
||||
ProductPageLayoutProps,
|
||||
ProductPageLayoutSectionProps,
|
||||
} from "./layouts/index";
|
||||
export { Link, LinkProps } from "./link/index";
|
||||
export { Modal, ModalProps } from "./modal/index";
|
||||
export { Popover, PopoverProps } from "./popover/index";
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/internal-header/index.css";
|
||||
import "@navikt/ds-css/typography/index.css";
|
||||
|
||||
export interface InternalHeaderProps extends HTMLAttributes<HTMLElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const InternalHeader = forwardRef<HTMLElement, InternalHeaderProps>(
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import React, { forwardRef, HTMLAttributes, createElement } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/internal-header/index.css";
|
||||
import "@navikt/ds-css/typography/index.css";
|
||||
|
||||
export interface InternalHeaderTitleProps extends HTMLAttributes<HTMLElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Tag this component will use. Usefull for defining a button/link
|
||||
* @default "h1"
|
||||
*/
|
||||
element?: keyof React.ReactHTML;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/internal-header/index.css";
|
||||
import "@navikt/ds-css/typography/index.css";
|
||||
|
||||
export interface InternalHeaderUserProps
|
||||
extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* user name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* user ident
|
||||
*/
|
||||
ident: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "../index";
|
||||
|
||||
export default {
|
||||
title: "@navikt/internal-header",
|
||||
title: "ds-react/internal-header",
|
||||
component: InternalHeader,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import "@navikt/ds-css/layout/index.css";
|
||||
import cl from "classnames";
|
||||
import React, {
|
||||
Children,
|
||||
forwardRef,
|
||||
ForwardRefExoticComponent,
|
||||
HTMLAttributes,
|
||||
} from "react";
|
||||
import { default as Section, SectionProps } from "./Section";
|
||||
|
||||
export interface LayoutWithSubComponents
|
||||
extends ForwardRefExoticComponent<LayoutProps> {
|
||||
Section: ForwardRefExoticComponent<SectionProps>;
|
||||
}
|
||||
|
||||
export interface LayoutProps extends HTMLAttributes<HTMLElement> {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Layout = forwardRef<HTMLDivElement, LayoutProps>(
|
||||
({ children, className, ...rest }, ref) => {
|
||||
const columns = Children.count(children);
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-layout__container",
|
||||
`navds-layout__container--${columns}-columns`,
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
) as LayoutWithSubComponents;
|
||||
|
||||
Layout.Section = Section;
|
||||
export default Layout;
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as Layout } from "./Layout";
|
||||
export * from "./Layout";
|
||||
export * from "./Section";
|
||||
@@ -1,94 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { ContentContainer } from "../../index";
|
||||
import { Layout } from "../index";
|
||||
import { Left } from "./components/sections/Left";
|
||||
import { Main } from "./components/sections/Main";
|
||||
import { Right } from "./components/sections/Right";
|
||||
import "./components/styles.css";
|
||||
|
||||
export default {
|
||||
title: "@navikt/layout/Article",
|
||||
component: { Layout },
|
||||
decorators: [
|
||||
(Story) => {
|
||||
useEffect(() => {
|
||||
document.getElementById("decorator-header").style.display = "block";
|
||||
document.getElementById("decorator-footer").style.display = "block";
|
||||
return () => {
|
||||
document.getElementById("decorator-header").style.display = "none";
|
||||
document.getElementById("decorator-footer").style.display = "none";
|
||||
};
|
||||
}, []);
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
backgrounds: {
|
||||
default: "NAV gray",
|
||||
values: [
|
||||
{
|
||||
name: "NAV gray",
|
||||
value: "#f1f1f1",
|
||||
},
|
||||
{
|
||||
name: "white",
|
||||
value: "#ffffff",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ThreeColumns = () => (
|
||||
<ContentContainer>
|
||||
<Layout>
|
||||
<Layout.Section left sticky>
|
||||
<Left />
|
||||
</Layout.Section>
|
||||
<Layout.Section>
|
||||
<Main />
|
||||
</Layout.Section>
|
||||
<Layout.Section right sticky>
|
||||
<Right />
|
||||
</Layout.Section>
|
||||
</Layout>
|
||||
</ContentContainer>
|
||||
);
|
||||
|
||||
export const TwoColumnsLeft = () => (
|
||||
<ContentContainer>
|
||||
<Layout>
|
||||
<Layout.Section left sticky>
|
||||
<Left />
|
||||
</Layout.Section>
|
||||
<Layout.Section>
|
||||
<Main />
|
||||
</Layout.Section>
|
||||
</Layout>
|
||||
</ContentContainer>
|
||||
);
|
||||
|
||||
export const TwoColumnsRight = () => (
|
||||
<ContentContainer>
|
||||
<Layout>
|
||||
<Layout.Section>
|
||||
<Main />
|
||||
</Layout.Section>
|
||||
<Layout.Section right sticky>
|
||||
<Right />
|
||||
</Layout.Section>
|
||||
</Layout>
|
||||
</ContentContainer>
|
||||
);
|
||||
|
||||
export const OneColumn = () => (
|
||||
<ContentContainer>
|
||||
<Layout>
|
||||
<Layout.Section>
|
||||
<Main />
|
||||
</Layout.Section>
|
||||
</Layout>
|
||||
</ContentContainer>
|
||||
);
|
||||
@@ -1,108 +0,0 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
Cell,
|
||||
Grid,
|
||||
Heading,
|
||||
Link,
|
||||
Paragraph,
|
||||
Alert,
|
||||
} from "../../../../index";
|
||||
|
||||
export const Main = () => (
|
||||
<div>
|
||||
<Heading className={"navds-story-section"} level={1} size={"xl"}>
|
||||
Quis autem
|
||||
</Heading>
|
||||
<Paragraph className={"section"}>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
|
||||
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo
|
||||
inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut
|
||||
fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem
|
||||
sequi nesciunt.
|
||||
</Paragraph>
|
||||
<Grid className={"section"}>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Ea voluptate</Link>
|
||||
</Cell>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Quis autem</Link>
|
||||
</Cell>
|
||||
</Grid>
|
||||
<Paragraph className={"section"}>
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
|
||||
consectetur, adipisci velit, sed quia non numquam eius modi tempora
|
||||
incidunt ut labore et dolore magnam aliquam quaerat voluptatem.{" "}
|
||||
</Paragraph>
|
||||
<Alert variant="info" className={"section"}>
|
||||
Suspendisse potenti. Interdum et malesuada fames ac ante ipsum primis in
|
||||
faucibus.
|
||||
</Alert>
|
||||
<Paragraph className={"section"}>
|
||||
Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis
|
||||
suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem
|
||||
vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil
|
||||
molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla
|
||||
pariatur?
|
||||
</Paragraph>
|
||||
<Heading className={"section"} level={2} size={"xl"}>
|
||||
Nulla pariatur?
|
||||
</Heading>
|
||||
<Paragraph className={"section"}>
|
||||
Etiam viverra neque sit amet libero dapibus tincidunt. Pellentesque quis
|
||||
imperdiet erat. Morbi sodales bibendum volutpat. Sed malesuada risus
|
||||
lorem, in elementum purus commodo eget. Mauris maximus congue efficitur.
|
||||
Cras vestibulum id metus sed pellentesque.
|
||||
</Paragraph>
|
||||
|
||||
<table className={"section tabell tabell--stripet"}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Fornavn</th>
|
||||
<th>Etternavn</th>
|
||||
<th>Rolle</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Jean-Luc</td>
|
||||
<td>Picard</td>
|
||||
<td>Kaptein</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>William</td>
|
||||
<td>Riker</td>
|
||||
<td>Kommandør</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Geordi</td>
|
||||
<td>La Forge</td>
|
||||
<td>Sjefsingeniør</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Paragraph className={"section"}>
|
||||
Curabitur a purus pretium, condimentum magna ac, pellentesque diam. Nulla
|
||||
facilisi. Nullam consequat, dui sed bibendum faucibus, metus mauris
|
||||
commodo tortor, eget mollis nunc augue eu elit. Ut nec fringilla odio, eu
|
||||
scelerisque tellus.
|
||||
</Paragraph>
|
||||
<Paragraph className={"section"}>
|
||||
Proin nec luctus justo. Pellentesque et dapibus libero. Phasellus non elit
|
||||
eget justo mattis venenatis. In hac habitasse platea dictumst. Proin nunc
|
||||
ipsum, ornare eu pretium in, aliquet non velit. Nullam efficitur tincidunt
|
||||
leo, vel tempus nibh consectetur sed. Etiam porttitor finibus erat varius
|
||||
rhoncus. Sed ac augue imperdiet, porta tellus vitae, aliquam est.
|
||||
</Paragraph>
|
||||
<Paragraph className={"section"}>
|
||||
Nunc eget consectetur felis, id scelerisque sapien. Ut id feugiat nulla,
|
||||
ut cursus sem. In viverra felis vitae aliquet finibus.
|
||||
</Paragraph>
|
||||
<Button>Søk ...</Button>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default as ProductPageLayout } from "./product-page/Layout";
|
||||
export { LayoutProps as ProductPageLayoutProps } from "./product-page/Layout";
|
||||
export { SectionProps as ProductPageLayoutSectionProps } from "./product-page/Section";
|
||||
@@ -0,0 +1,69 @@
|
||||
import React, { useEffect, Children, forwardRef } from "react";
|
||||
import { ForwardRefExoticComponent, HTMLAttributes } from "react";
|
||||
import { default as Section, SectionProps } from "./Section";
|
||||
import { default as Panel, PanelProps } from "./Panel";
|
||||
import { ContentContainer, Heading, OverridableComponent } from "../../";
|
||||
import cl from "classnames";
|
||||
|
||||
export interface LayoutWithSubComponents
|
||||
extends ForwardRefExoticComponent<LayoutProps> {
|
||||
Section: ForwardRefExoticComponent<SectionProps>;
|
||||
Panel: OverridableComponent<PanelProps>;
|
||||
}
|
||||
|
||||
export interface LayoutProps extends HTMLAttributes<HTMLElement> {
|
||||
title: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const Layout = forwardRef<HTMLDivElement, LayoutProps>(
|
||||
({ children, title, className, ...rest }, ref) => {
|
||||
const columns = Children.toArray(children).length;
|
||||
const classNames = cl(
|
||||
"navds-layout__container",
|
||||
`navds-layout__container--${columns}-columns`,
|
||||
className
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const layoutBody = document.getElementById("navds-layout-body");
|
||||
layoutBody?.classList.add(`navds-layout__body--${columns}-columns`);
|
||||
document.body.classList.add("navds-layout__body--white");
|
||||
return () => {
|
||||
layoutBody?.classList.remove(`navds-layout__body--${columns}-columns`);
|
||||
document.body.classList.remove("navds-layout__body--white");
|
||||
};
|
||||
}, [columns]);
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<div id={"navds-layout-header"} className={"navds-layout__header"}>
|
||||
<ContentContainer>
|
||||
<div className={classNames} {...rest}>
|
||||
<div className={cl("navds-layout__header-content")}>
|
||||
<Heading
|
||||
size={"xxl"}
|
||||
className={cl("navds-layout__header-title")}
|
||||
level={1}
|
||||
>
|
||||
{title}
|
||||
</Heading>
|
||||
</div>
|
||||
</div>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
<div id={"navds-layout-body"} className={"navds-layout__body"}>
|
||||
<ContentContainer>
|
||||
<div className={classNames} {...rest}>
|
||||
{children}
|
||||
</div>
|
||||
</ContentContainer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
) as LayoutWithSubComponents;
|
||||
|
||||
Layout.Section = Section;
|
||||
Layout.Panel = Panel;
|
||||
export default Layout;
|
||||
@@ -0,0 +1,101 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { forwardRef, ReactNode } from "react";
|
||||
import cl from "classnames";
|
||||
import { Button, Heading, Popover } from "../../";
|
||||
import { Attachment } from "@navikt/ds-icons";
|
||||
import { OverridableComponent } from "../../util";
|
||||
|
||||
export interface PanelProps {
|
||||
props: {
|
||||
title: string;
|
||||
icon?: ReactNode;
|
||||
highlight?: boolean;
|
||||
anchor?: string;
|
||||
whiteBackground?: boolean;
|
||||
withPadding?: boolean;
|
||||
} & React.HTMLAttributes<HTMLDivElement>;
|
||||
defaultComponent: "div";
|
||||
}
|
||||
|
||||
const Panel: OverridableComponent<PanelProps> = forwardRef(
|
||||
(
|
||||
{
|
||||
title,
|
||||
highlight,
|
||||
icon,
|
||||
anchor,
|
||||
component: Component = "div",
|
||||
className,
|
||||
children,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
|
||||
const [copied, setIsCopied] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const header = document.getElementById("navds-layout-body");
|
||||
header?.classList.add("navds-layout__body--padding");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Component
|
||||
ref={ref}
|
||||
id={anchor}
|
||||
className={cl(
|
||||
"navds-layout__panel",
|
||||
icon && "navds-layout__panel--icon-margin",
|
||||
highlight && "navds-layout__panel--highlight",
|
||||
className
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{icon && <div className={"navds-layout__panel-icon"}>{icon}</div>}
|
||||
<Heading size={"xl"} className={"navds-layout__panel-title"} level={2}>
|
||||
{title}
|
||||
</Heading>
|
||||
{anchor && (
|
||||
<div className={"navds-layout__panel-copy"}>
|
||||
<Button
|
||||
ref={(el) => setAnchorEl(el)}
|
||||
variant={"secondary"}
|
||||
className={"navds-layout__panel-copy-button"}
|
||||
onClick={() => {
|
||||
setIsCopied(true);
|
||||
const { href, hash } = window.location;
|
||||
const urlWithoutHash = href.replace(hash, "");
|
||||
copyToClipboard(`${urlWithoutHash}#${anchor}`);
|
||||
setTimeout(() => {
|
||||
setIsCopied(false);
|
||||
}, 1000);
|
||||
}}
|
||||
>
|
||||
<Attachment className={"navds-layout__panel-copy-icon"} />
|
||||
<span>Kopier lenke</span>
|
||||
</Button>
|
||||
<Popover anchorEl={anchorEl} open={copied} onClose={() => {}}>
|
||||
<div className="navds-layout__panel-popover-content">Kopiert</div>
|
||||
</Popover>
|
||||
</div>
|
||||
)}
|
||||
<div className={"navds-layout__panel-content"}>{children}</div>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const copyToClipboard = (text: string) => {
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
textArea.style.top = "0";
|
||||
textArea.style.left = "0";
|
||||
textArea.style.position = "fixed";
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(textArea);
|
||||
};
|
||||
|
||||
export default Panel;
|
||||
File renamed without changes.
+4
-4
@@ -4,16 +4,16 @@ import { Button, Link } from "../../../../index";
|
||||
export const Left = () => (
|
||||
<ul className={"navds-story-menu"}>
|
||||
<li>
|
||||
<Link href={"#"}>Iusto odio dignissimos</Link>
|
||||
<Link href={"#leo-quis"}>Leo quis</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#"}>Nam libero tempore</Link>
|
||||
<Link href={"#proin-accumsan"}>Proin accumsan</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#"}>Reiciendis voluptatibus</Link>
|
||||
<Link href={"#nulla-pariatur"}>Nulla pariatur?</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={"#"}>Earum rerum</Link>
|
||||
<Link href={"#maecenas-in-pretium"}>Maecenas in pretium</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Button>Søk ...</Button>
|
||||
@@ -0,0 +1,145 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
Cell,
|
||||
Grid,
|
||||
Heading,
|
||||
Link,
|
||||
Paragraph,
|
||||
} from "../../../../index";
|
||||
import Snakkeboble from "nav-frontend-snakkeboble";
|
||||
|
||||
export const Main = ({ title = true }) => (
|
||||
<>
|
||||
<MainOne title={title} />
|
||||
<MainTwo title={title} />
|
||||
<MainThree title={title} />
|
||||
</>
|
||||
);
|
||||
|
||||
export const MainOne = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Heading level={1} size={"xl"} id={"leo-quis"}>
|
||||
Leo quis
|
||||
</Heading>
|
||||
)}
|
||||
<Paragraph>
|
||||
Sed ullamcorper quam eget lorem volutpat, quis cursus risus fermentum.
|
||||
Quisque varius ornare nulla, ut condimentum sapien dapibus non. Nullam
|
||||
eget interdum nibh
|
||||
</Paragraph>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MainTwo = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Heading level={1} size={"xl"} id={"proin-accumsan"}>
|
||||
Proin accumsan
|
||||
</Heading>
|
||||
)}
|
||||
<Paragraph className={"section"}>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
|
||||
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo
|
||||
inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
</Paragraph>
|
||||
<Grid className={"section"}>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Ea voluptate</Link>
|
||||
</Cell>
|
||||
<Cell xs={6}>
|
||||
<Link href={"#"}>Quis autem</Link>
|
||||
</Cell>
|
||||
</Grid>
|
||||
<Paragraph className={"section"}>
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet,
|
||||
consectetur, adipisci velit, sed quia non numquam eius modi tempora.
|
||||
</Paragraph>
|
||||
<Heading level={2} size={"large"} id={"nulla-pariatur"}>
|
||||
Nulla pariatur?
|
||||
</Heading>
|
||||
<Paragraph className={"section"}>
|
||||
Etiam viverra neque sit amet libero dapibus tincidunt. Pellentesque quis
|
||||
imperdiet erat. Morbi sodales bibendum volutpat.
|
||||
</Paragraph>
|
||||
<table className={"section tabell tabell--stripet"}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Fornavn</th>
|
||||
<th>Etternavn</th>
|
||||
<th>Rolle</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Jean-Luc</td>
|
||||
<td>Picard</td>
|
||||
<td>Kaptein</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>William</td>
|
||||
<td>Riker</td>
|
||||
<td>Kommandør</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Geordi</td>
|
||||
<td>La Forge</td>
|
||||
<td>Sjefsingeniør</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Paragraph className={"section"}>
|
||||
Curabitur a purus pretium, condimentum magna ac, pellentesque diam. Nulla
|
||||
facilisi. Nullam consequat, dui sed bibendum faucibus, metus mauris
|
||||
commodo tortor.
|
||||
</Paragraph>
|
||||
<Heading level={2} size={"large"} id={"luctus-justo"}>
|
||||
Luctus justo
|
||||
</Heading>
|
||||
<Paragraph className={"section"}>
|
||||
Nunc eget consectetur felis, id scelerisque sapien. Ut id feugiat nulla,
|
||||
ut cursus sem. In viverra felis vitae aliquet finibus.
|
||||
</Paragraph>
|
||||
<Button>Søk ...</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const MainThree = ({ title = true }) => (
|
||||
<div>
|
||||
{title && (
|
||||
<Heading level={1} size={"xl"} id={"maecenas-in-pretium"}>
|
||||
Maecenas in pretium
|
||||
</Heading>
|
||||
)}
|
||||
<Paragraph>
|
||||
Sed ullamcorper quam eget lorem volutpat, quis cursus risus fermentum.
|
||||
Quisque varius ornare nulla, ut condimentum sapien dapibus non. Nullam
|
||||
eget interdum nibh
|
||||
</Paragraph>
|
||||
<Snakkeboble>Integer aliquam feugiat purus et imperdie</Snakkeboble>
|
||||
<Paragraph>
|
||||
Cras tempor eros sed dapibus egestas. Curabitur bibendum quam quis lectus
|
||||
pretium lacinia. Nunc consequat ac augue quis laoreet. Donec porta, erat
|
||||
vitae blandit egestas, arcu metus pharetra nulla, et laoreet risus purus
|
||||
convallis turpis.
|
||||
</Paragraph>
|
||||
<Snakkeboble pilHoyre={true}>
|
||||
Integer aliquam feugiat purus et imperdie
|
||||
</Snakkeboble>
|
||||
<Paragraph>
|
||||
Suspendisse potenti. Praesent at elit interdum, porttitor sem eget,
|
||||
blandit dolor. Nunc eget consectetur felis, id scelerisque sapien. Ut id
|
||||
feugiat nulla, ut cursus sem. In viverra felis vitae aliquet finibus.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Vivamus id mi lectus. Duis ac augue magna. Aliquam ut euismod dui. Duis
|
||||
consectetur, magna a malesuada tempus, elit urna fermentum arcu, at
|
||||
porttitor magna sapien id enim.
|
||||
</Paragraph>
|
||||
</div>
|
||||
);
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,102 @@
|
||||
import * as React from "react";
|
||||
import { useEffect } from "react";
|
||||
import { ProductPageLayout } from "../../index";
|
||||
import { Left } from "./components/sections/Left";
|
||||
import { Main, MainOne, MainTwo, MainThree } from "./components/sections/Main";
|
||||
import { Right } from "./components/sections/Right";
|
||||
import { LightBulb, Telephone } from "@navikt/ds-icons";
|
||||
import "./components/styles.css";
|
||||
|
||||
export default {
|
||||
title: "ds-react/layouts/ProductPage",
|
||||
component: ProductPageLayout,
|
||||
decorators: [
|
||||
(Story) => {
|
||||
useEffect(() => {
|
||||
document.getElementById("decorator-header").style.display = "block";
|
||||
document.getElementById("decorator-footer").style.display = "block";
|
||||
return () => {
|
||||
document.getElementById("decorator-header").style.display = "none";
|
||||
document.getElementById("decorator-footer").style.display = "none";
|
||||
};
|
||||
}, []);
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
};
|
||||
|
||||
const title = "Nunc et lorem";
|
||||
export const ThreeColumns = () => (
|
||||
<ProductPageLayout title={title}>
|
||||
<ProductPageLayout.Section left sticky>
|
||||
<Left />
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section whiteBackground={false} withPadding={false}>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Proin accumsan"}
|
||||
anchor={"proin-accumsan"}
|
||||
>
|
||||
<MainTwo title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Maecenas in pretium"}
|
||||
anchor={"maecenas-in-pretium"}
|
||||
icon={<Telephone />}
|
||||
>
|
||||
<MainThree title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section right sticky>
|
||||
<Right />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
|
||||
export const TwoColumnsLeft = () => (
|
||||
<ProductPageLayout title={title}>
|
||||
<ProductPageLayout.Section left sticky>
|
||||
<Left />
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section>
|
||||
<ProductPageLayout.Panel
|
||||
title={"Leo quis"}
|
||||
anchor={"leo-quis"}
|
||||
highlight={true}
|
||||
icon={<LightBulb />}
|
||||
>
|
||||
<MainOne title={false} />
|
||||
</ProductPageLayout.Panel>
|
||||
<Main />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
|
||||
export const TwoColumnsRight = () => (
|
||||
<ProductPageLayout title={title}>
|
||||
<ProductPageLayout.Section>
|
||||
<Main />
|
||||
</ProductPageLayout.Section>
|
||||
<ProductPageLayout.Section right sticky>
|
||||
<Right />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
|
||||
export const OneColumn = () => (
|
||||
<ProductPageLayout title={title}>
|
||||
<ProductPageLayout.Section>
|
||||
<Main />
|
||||
</ProductPageLayout.Section>
|
||||
</ProductPageLayout>
|
||||
);
|
||||
@@ -1,9 +1,16 @@
|
||||
import React, { forwardRef } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/link/index.css";
|
||||
|
||||
export interface LinkProps
|
||||
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Link anchor should direct to
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Link } from "../index";
|
||||
import { Add } from "@navikt/ds-icons";
|
||||
export default {
|
||||
title: "@navikt/link",
|
||||
title: "ds-react/link",
|
||||
component: Link,
|
||||
};
|
||||
|
||||
|
||||
@@ -3,12 +3,8 @@ import cl from "classnames";
|
||||
import ReactModal from "react-modal";
|
||||
import mergeRefs from "react-merge-refs";
|
||||
import { Close } from "@navikt/ds-icons";
|
||||
import "@navikt/ds-css/modal/index.css";
|
||||
import { Button } from "../index";
|
||||
|
||||
// TODO: Has to be documented well that the user has to import react-modal and call
|
||||
// ReactModal.setAppElement("#root")
|
||||
|
||||
export interface ModalProps {
|
||||
/**
|
||||
* Content of modal
|
||||
@@ -28,7 +24,7 @@ export interface ModalProps {
|
||||
*/
|
||||
shouldCloseOnOverlayClick?: boolean;
|
||||
/**
|
||||
* User defined classname for wrapper element
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
@@ -37,7 +33,14 @@ export interface ModalProps {
|
||||
contentClassName?: string;
|
||||
}
|
||||
|
||||
const Modal = forwardRef<ReactModal, ModalProps>(
|
||||
type ModalLifecycle = {
|
||||
setAppElement?: (element: any) => void;
|
||||
};
|
||||
|
||||
const Modal: ModalLifecycle &
|
||||
React.ForwardRefExoticComponent<
|
||||
ModalProps & React.RefAttributes<ReactModal>
|
||||
> = forwardRef<ReactModal, ModalProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
@@ -90,8 +93,6 @@ const Modal = forwardRef<ReactModal, ModalProps>(
|
||||
}
|
||||
);
|
||||
|
||||
export const setAppElement = (element) => {
|
||||
ReactModal.setAppElement(element);
|
||||
};
|
||||
Modal.setAppElement = (element) => ReactModal.setAppElement(element);
|
||||
|
||||
export default Modal;
|
||||
@@ -1,13 +1,12 @@
|
||||
import React, { useState } from "react";
|
||||
import { Modal } from "../index";
|
||||
import ReactModal from "react-modal";
|
||||
|
||||
export default {
|
||||
title: "@navikt/modal",
|
||||
title: "ds-react/modal",
|
||||
component: Modal,
|
||||
};
|
||||
|
||||
ReactModal.setAppElement("#root");
|
||||
Modal.setAppElement("#root");
|
||||
|
||||
export const All = () => {
|
||||
const [open, setOpen] = useState(true);
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "0.1.2",
|
||||
"version": "0.2.7",
|
||||
"private": false,
|
||||
"description": "NAV designsystem react components",
|
||||
"author": "NAV Designsystem team",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"react",
|
||||
"typescript",
|
||||
"javascript"
|
||||
],
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler/tree/master/%40navikt/ds-react"
|
||||
},
|
||||
"main": "esm/index.js",
|
||||
"module": "esm/index.js",
|
||||
"typings": "esm/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"/lib"
|
||||
"/cjs",
|
||||
"/esm"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/navikt/nav-frontend-moduler.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"cjs-package": "copyfiles -f config/package.json cjs",
|
||||
"clean": "rm -rf cjs esm",
|
||||
"build": "yarn run clean && tsc && tsc -p tsconfig-esm.json && yarn cjs-package",
|
||||
"watch": "tsc --watch -p tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@navikt/ds-css": "^0.1.17",
|
||||
"@navikt/ds-icons": "^0.1.7",
|
||||
"@navikt/ds-icons": "^0.2.1",
|
||||
"@popperjs/core": "^2.5.4",
|
||||
"classnames": "^2.2.6",
|
||||
"react-collapse": "^5.1.0",
|
||||
@@ -38,6 +43,7 @@
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copyfiles": "^2.4.1",
|
||||
"react-router-dom": "^5.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { usePopper } from "react-popper";
|
||||
import { Placement } from "@popperjs/core";
|
||||
import mergeRefs from "react-merge-refs";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/popover/index.css";
|
||||
|
||||
export interface PopoverProps extends HTMLAttributes<HTMLDivElement> {
|
||||
/**
|
||||
@@ -28,12 +27,15 @@ export interface PopoverProps extends HTMLAttributes<HTMLDivElement> {
|
||||
* Content rendered inside popover
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Orientation for popover
|
||||
* @default 'auto'
|
||||
* @default "right"
|
||||
*/
|
||||
placement?: Placement;
|
||||
size?: "medium" | "small";
|
||||
}
|
||||
|
||||
const useEventLister = (event: string, callback) =>
|
||||
@@ -53,7 +55,6 @@ const Popover = forwardRef<HTMLDivElement, PopoverProps>(
|
||||
children,
|
||||
placement = "right",
|
||||
className,
|
||||
size = "medium",
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
@@ -67,9 +68,16 @@ const Popover = forwardRef<HTMLDivElement, PopoverProps>(
|
||||
useEventLister(
|
||||
"click",
|
||||
useCallback(
|
||||
(e: MouseEvent) =>
|
||||
!popoverRef.current?.contains(e.target as Node) && close(),
|
||||
[close]
|
||||
(e: MouseEvent) => {
|
||||
if (
|
||||
![anchorEl, popoverRef.current].some((element) =>
|
||||
element?.contains(e.target as Node)
|
||||
)
|
||||
) {
|
||||
close();
|
||||
}
|
||||
},
|
||||
[anchorEl, close]
|
||||
)
|
||||
);
|
||||
|
||||
@@ -124,8 +132,8 @@ const Popover = forwardRef<HTMLDivElement, PopoverProps>(
|
||||
return (
|
||||
<div
|
||||
ref={mergedRef}
|
||||
className={cl("navds-popover", `navds-popover--${size}`, className, {
|
||||
"popover--hidden": !open || !anchorEl,
|
||||
className={cl("navds-popover", className, {
|
||||
"navds-popover--hidden": !open || !anchorEl,
|
||||
})}
|
||||
aria-live="polite"
|
||||
aria-hidden={!open || !anchorEl}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Popover } from "../index";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
import { placements } from "@popperjs/core";
|
||||
export default {
|
||||
title: "@navikt/popover",
|
||||
title: "ds-react/popover",
|
||||
component: Popover,
|
||||
parameters: {
|
||||
chromatic: { disable: true },
|
||||
@@ -27,7 +27,7 @@ const Template = (props) => {
|
||||
{props.placement}
|
||||
</div>
|
||||
<Popover {...props} anchorEl={anchorEl} onClose={() => {}} open>
|
||||
Contents
|
||||
<div style={{ margin: "1rem" }}>Contents</div>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
@@ -56,27 +56,3 @@ export const All = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Small = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
margin: "4rem 8rem 4rem 8rem",
|
||||
}}
|
||||
>
|
||||
{placements.map((placement) => (
|
||||
<div
|
||||
style={{
|
||||
width: "20%",
|
||||
height: "100px",
|
||||
margin: "4rem",
|
||||
}}
|
||||
>
|
||||
<Template placement={placement} size="small" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,9 +1,15 @@
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import cl from "classnames";
|
||||
import "@navikt/ds-css/tag/index.css";
|
||||
|
||||
export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
/**
|
||||
* Component content
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Changes background-color and border-color
|
||||
*/
|
||||
@@ -11,11 +17,12 @@ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
}
|
||||
|
||||
const Tag = forwardRef<HTMLSpanElement, TagProps>(
|
||||
({ children, className, variant }, ref) => {
|
||||
({ children, className, variant, ...rest }, ref) => {
|
||||
return (
|
||||
<span
|
||||
ref={ref}
|
||||
className={cl("navds-tag", className, `navds-tag--${variant}`)}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Tag } from "../index";
|
||||
import { Meta } from "@storybook/react/types-6-0";
|
||||
export default {
|
||||
title: "@navikt/tag",
|
||||
title: "ds-react/tag",
|
||||
component: Tag,
|
||||
} as Meta;
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../utilities/build/tsconfig-pakker.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./esm",
|
||||
"rootDir": "./",
|
||||
"esModuleInterop": true,
|
||||
"module": "ES2020",
|
||||
"target": "ES2015",
|
||||
"sourceMap": true,
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["./*"]
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"extends": "../../utilities/build/tsconfig-pakker.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib",
|
||||
"outDir": "./cjs",
|
||||
"rootDir": "./",
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true
|
||||
"module": "commonjs",
|
||||
"target": "es2015",
|
||||
"sourceMap": false,
|
||||
"declaration": false
|
||||
},
|
||||
"include": ["./*"]
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import "@navikt/ds-css/typography/index.css";
|
||||
|
||||
export { default as Heading } from "./Heading";
|
||||
export * from "./Heading";
|
||||
export { default as Text } from "./Text";
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Heading, Text, Paragraph, Lead } from "../index";
|
||||
|
||||
export default {
|
||||
title: "@navikt/typography",
|
||||
title: "ds-react/typography",
|
||||
component: Heading,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"private": false,
|
||||
"description": "Auto-generated design-tokens for NAV design-systems framework",
|
||||
"author": "NAV Designsystem team",
|
||||
|
||||
@@ -25,8 +25,12 @@ module.exports = {
|
||||
white: { value: white },
|
||||
darkgray: { value: darkgray },
|
||||
gray: {
|
||||
40: { value: "#b7b1a9" },
|
||||
60: { value: "#78706a" },
|
||||
90: { value: "#262626" },
|
||||
80: { value: "#4F4F4F" },
|
||||
60: { value: "#6A6A6A" },
|
||||
40: { value: "#A0A0A0" },
|
||||
20: { value: "#C9C9C9" },
|
||||
10: { value: "#F1F1F1" },
|
||||
},
|
||||
...Object.entries(baseColors).reduce(
|
||||
(colors, [name, color]) => ({
|
||||
@@ -170,6 +174,10 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
background: {
|
||||
white: { value: "#FFFFFF" },
|
||||
gray: { value: "#F1F1F1" },
|
||||
},
|
||||
padding: {
|
||||
small: { value: "1rem" },
|
||||
mediumAndLarger: { value: "2.5rem" },
|
||||
|
||||
Loaded 100 of 219 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user