@developer-overheid-nl/don-register-components 1.3.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +170 -118
- package/LICENSE.md +291 -291
- package/README.md +20 -20
- package/package.json +10 -8
- package/src/Introduction.mdx +31 -0
- package/src/alert/Alert.stories.tsx +57 -0
- package/src/alert/Alert.tsx +19 -19
- package/src/alert/styles.module.css +3 -3
- package/src/alignBox/AlignBox.stories.tsx +84 -0
- package/src/alignBox/AlignBox.tsx +114 -114
- package/src/alignBox/styles.module.css +110 -110
- package/src/amountLabel/AmountLabel.stories.tsx +28 -0
- package/src/amountLabel/AmountLabel.tsx +21 -16
- package/src/amountLabel/styles.module.css +11 -11
- package/src/analytics/PiwikPro.tsx +94 -94
- package/src/analytics/index.ts +1 -1
- package/src/article/Article.stories.tsx +53 -0
- package/src/article/Article.tsx +10 -10
- package/src/badgeList/BadgeList.tsx +34 -34
- package/src/badgeList/styles.module.css +37 -37
- package/src/block/Block.stories.tsx +58 -0
- package/src/block/Block.tsx +35 -35
- package/src/block/styles.module.css +29 -29
- package/src/button/Button.stories.tsx +56 -0
- package/src/button/Button.tsx +3 -3
- package/src/button/ButtonAction.stories.tsx +62 -0
- package/src/button/ButtonAction.tsx +51 -0
- package/src/cardAsLink/CardAsLink.stories.tsx +81 -0
- package/src/cardAsLink/CardAsLink.tsx +21 -21
- package/src/cardAsLink/styles.module.css +23 -23
- package/src/cardsList/CardsList.tsx +56 -54
- package/src/cardsList/styles.module.css +18 -19
- package/src/client.ts +7 -7
- package/src/container/Container.stories.tsx +21 -0
- package/src/container/Container.tsx +10 -10
- package/src/container/styles.module.css +28 -28
- package/src/copyButton/CopyButton.stories.tsx +41 -0
- package/src/copyButton/CopyButton.tsx +45 -39
- package/src/copyButton/styles.module.css +13 -13
- package/src/dataBadgeLink/DataBadgeLink.stories.tsx +137 -0
- package/src/dataBadgeLink/DataBadgeLink.tsx +59 -53
- package/src/dataBadgeLink/styles.module.css +89 -89
- package/src/dataSummary/DataSummary.tsx +22 -22
- package/src/dataSummary/DataSummaryItem.tsx +21 -21
- package/src/dataSummary/styles.module.css +75 -75
- package/src/facetFilters/FacetFilters.stories.tsx +93 -0
- package/src/facetFilters/FacetFilters.tsx +424 -367
- package/src/facetFilters/styles.module.css +3 -3
- package/src/fieldset/FieldSet.stories.tsx +45 -0
- package/src/fieldset/FieldSet.tsx +3 -3
- package/src/filters/Filters.stories.tsx +45 -0
- package/src/filters/Filters.tsx +116 -116
- package/src/filters/styles.module.css +26 -26
- package/src/footer/Footer.stories.tsx +127 -0
- package/src/footer/Footer.tsx +81 -76
- package/src/footer/styles.module.css +103 -103
- package/src/formFieldCheckboxGroup/FormFieldCheckboxGroup.stories.tsx +48 -0
- package/src/formFieldCheckboxGroup/FormFieldCheckboxGroup.tsx +16 -16
- package/src/formFieldCheckboxGroup/styles.module.css +5 -5
- package/src/formFieldCheckboxOption/FormFieldCheckboxOption.stories.tsx +61 -0
- package/src/formFieldCheckboxOption/FormFieldCheckboxOption.tsx +26 -26
- package/src/formFieldCheckboxOption/styles.module.css +22 -22
- package/src/formFieldLabel/FormFieldLabel.stories.tsx +21 -0
- package/src/formFieldLabel/FormFieldLabel.tsx +23 -23
- package/src/formFieldRadioGroup/FormFieldRadioGroup.stories.tsx +57 -0
- package/src/formFieldRadioGroup/FormFieldRadioGroup.tsx +13 -13
- package/src/formFieldRadioGroup/styles.module.css +5 -5
- package/src/formFieldRadioOption/FormFieldRadioOption.stories.tsx +48 -0
- package/src/formFieldRadioOption/FormFieldRadioOption.tsx +75 -75
- package/src/formFieldRadioOption/styles.module.css +49 -49
- package/src/formFieldSwitch/FormFieldSwitch.stories.tsx +61 -0
- package/src/formFieldSwitch/FormFieldSwitch.tsx +82 -79
- package/src/formFieldSwitch/styles.module.css +32 -32
- package/src/formFieldTextInput/FormFieldTextInput.stories.tsx +45 -0
- package/src/formFieldTextInput/FormFieldTextInput.tsx +3 -3
- package/src/grid/Grid.stories.tsx +37 -0
- package/src/grid/Grid.tsx +48 -0
- package/src/grid/styles.module.css +24 -0
- package/src/header/Header.stories.tsx +54 -0
- package/src/header/Header.tsx +137 -137
- package/src/header/styles.module.css +71 -71
- package/src/heading/Heading.stories.tsx +60 -0
- package/src/heading/Heading.tsx +15 -15
- package/src/headingGroup/HeadingGroup.stories.tsx +57 -0
- package/src/headingGroup/HeadingGroup.tsx +48 -48
- package/src/headingGroup/styles.module.css +3 -3
- package/src/i18n.ts +24 -25
- package/src/iconBadge/IconBadge.stories.tsx +46 -0
- package/src/iconBadge/IconBadge.tsx +35 -35
- package/src/iconBadge/getAppearance.ts +53 -53
- package/src/iconBadge/styles.module.css +19 -19
- package/src/iconsSprite/Icon.stories.tsx +73 -0
- package/src/iconsSprite/Icon.tsx +17 -17
- package/src/iconsSprite/IconsSprite.tsx +5 -5
- package/src/index.ts +117 -107
- package/src/infoButton/InfoButton.stories.tsx +52 -0
- package/src/infoButton/InfoButton.tsx +45 -45
- package/src/infoButton/styles.module.css +43 -43
- package/src/link/Link.stories.tsx +49 -0
- package/src/link/Link.tsx +10 -10
- package/src/markdown/Markdown.stories.tsx +48 -0
- package/src/markdown/Markdown.tsx +42 -42
- package/src/overlay/Overlay.stories.tsx +38 -0
- package/src/overlay/Overlay.tsx +18 -18
- package/src/overlay/styles.module.css +15 -15
- package/src/pagination/Pagination.stories.tsx +91 -0
- package/src/pagination/Pagination.tsx +267 -267
- package/src/pagination/styles.module.css +28 -28
- package/src/paragraph/Paragraph.stories.tsx +45 -0
- package/src/paragraph/Paragraph.tsx +24 -24
- package/src/paragraph/styles.module.css +6 -6
- package/src/pillBadge/PillBadge.examples.tsx +107 -107
- package/src/pillBadge/PillBadge.stories.tsx +257 -0
- package/src/pillBadge/PillBadge.tsx +60 -51
- package/src/pillBadge/styles.module.css +214 -214
- package/src/readOnlyTextInput/ReadOnlyTextInput.stories.tsx +49 -0
- package/src/readOnlyTextInput/ReadOnlyTextInput.tsx +24 -24
- package/src/readOnlyTextInput/styles.module.css +19 -19
- package/src/scoreBadge/ScoreBadge.stories.tsx +45 -0
- package/src/scoreBadge/ScoreBadge.tsx +135 -133
- package/src/search/Search.stories.tsx +65 -0
- package/src/search/Search.tsx +82 -82
- package/src/search/styles.module.css +40 -39
- package/src/siteLogo/ExampleLogo.stories.tsx +40 -0
- package/src/siteLogo/SiteLogo.stories.tsx +28 -0
- package/src/siteLogo/SiteLogo.tsx +24 -24
- package/src/sortForm/SortForm.stories.tsx +111 -0
- package/src/sortForm/SortForm.tsx +121 -0
- package/src/sortForm/styles.module.css +40 -0
- package/src/switch/Switch.stories.tsx +68 -0
- package/src/switch/Switch.tsx +152 -86
- package/src/switch/styles.module.css +54 -7
- package/src/toolTip/ToolTip.stories.tsx +131 -0
- package/src/toolTip/ToolTip.tsx +55 -55
- package/src/toolTip/styles.module.css +49 -49
- package/src/topNavigation/TopNavigation.stories.tsx +71 -0
- package/src/topNavigation/TopNavigation.tsx +67 -67
- package/src/topNavigation/styles.module.css +54 -54
- package/tsconfig.json +122 -121
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { expect, waitFor } from "storybook/test";
|
|
3
|
+
import AlignBox from "../alignBox/AlignBox";
|
|
4
|
+
import Block from "../block/Block";
|
|
5
|
+
import InfoButton from "../infoButton/InfoButton";
|
|
6
|
+
import ToolTip from "./ToolTip";
|
|
7
|
+
|
|
8
|
+
// const waitForTimeout = (ms: number) =>
|
|
9
|
+
// new Promise<void>((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ToolTip toont `text` in een popover, gekoppeld aan een trigger-element.
|
|
13
|
+
*
|
|
14
|
+
* Zonder `children` wordt automatisch een `InfoButton` gerenderd met de
|
|
15
|
+
* juiste `command`/`commandfor`/`interestfor`-koppeling; met een eigen
|
|
16
|
+
* `children`-trigger moet die koppeling zelf worden meegegeven.
|
|
17
|
+
*/
|
|
18
|
+
const meta = {
|
|
19
|
+
title: "Components/ToolTip",
|
|
20
|
+
component: ToolTip,
|
|
21
|
+
tags: ["autodocs", "custom"],
|
|
22
|
+
args: {
|
|
23
|
+
text: "Nationale organisatie voor kadaster en vastgoedregistratie.",
|
|
24
|
+
"aria-label": "Meer informatie over Kadaster",
|
|
25
|
+
},
|
|
26
|
+
} satisfies Meta<typeof ToolTip>;
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
type Story = StoryObj<typeof meta>;
|
|
30
|
+
|
|
31
|
+
export const Default: Story = {
|
|
32
|
+
play: async ({ canvas, args, userEvent }) => {
|
|
33
|
+
const tooltip = canvas.getByText(args.text);
|
|
34
|
+
expect(tooltip).not.toBeVisible();
|
|
35
|
+
|
|
36
|
+
await userEvent.click(
|
|
37
|
+
canvas.getByRole("button", { name: args["aria-label"] }),
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
await waitFor(() => expect(tooltip).toBeVisible());
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const WithCustomTrigger: Story = {
|
|
45
|
+
name: "Met eigen trigger-element",
|
|
46
|
+
render: (args) => (
|
|
47
|
+
<ToolTip {...args} id="tooltip-custom-trigger">
|
|
48
|
+
{/* With a custom trigger, the popover wiring isn't done automatically
|
|
49
|
+
and must be set on the trigger element to match the ToolTip's id. */}
|
|
50
|
+
<InfoButton
|
|
51
|
+
aria-label={args["aria-label"]}
|
|
52
|
+
iconSize="large"
|
|
53
|
+
command="toggle-popover"
|
|
54
|
+
commandfor="tooltip-custom-trigger"
|
|
55
|
+
interestfor="tooltip-custom-trigger"
|
|
56
|
+
/>
|
|
57
|
+
</ToolTip>
|
|
58
|
+
),
|
|
59
|
+
play: async ({ canvas, args, userEvent }) => {
|
|
60
|
+
const tooltip = canvas.getByText(args.text);
|
|
61
|
+
expect(tooltip).not.toBeVisible();
|
|
62
|
+
|
|
63
|
+
await userEvent.click(
|
|
64
|
+
canvas.getByRole("button", { name: args["aria-label"] }),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
await waitFor(() => expect(tooltip).toBeVisible());
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const CommandForVsInterestFor: Story = {
|
|
72
|
+
name: "commandfor vs. interestfor",
|
|
73
|
+
decorators: [
|
|
74
|
+
(Story) => (
|
|
75
|
+
<Block layout="flex-row">
|
|
76
|
+
<Story />
|
|
77
|
+
</Block>
|
|
78
|
+
),
|
|
79
|
+
],
|
|
80
|
+
render: (args) => (
|
|
81
|
+
<>
|
|
82
|
+
<AlignBox gap="medium">
|
|
83
|
+
<p>Klik om te openen (commandfor)</p>
|
|
84
|
+
<ToolTip text={args.text} id="tooltip-commandfor">
|
|
85
|
+
<InfoButton
|
|
86
|
+
aria-label="Meer informatie (klik om te openen)"
|
|
87
|
+
command="toggle-popover"
|
|
88
|
+
commandfor="tooltip-commandfor"
|
|
89
|
+
/>
|
|
90
|
+
</ToolTip>
|
|
91
|
+
</AlignBox>
|
|
92
|
+
<AlignBox gap="medium">
|
|
93
|
+
<p>Hover om te openen (interestfor)</p>
|
|
94
|
+
{/* interestfor targets a "hint" popover, which opens on hover/focus
|
|
95
|
+
instead of on click, unlike the "manual" popover used by commandfor. */}
|
|
96
|
+
<ToolTip text={args.text} id="tooltip-interestfor" popover="hint">
|
|
97
|
+
<InfoButton
|
|
98
|
+
aria-label="Meer informatie (hover om te openen)"
|
|
99
|
+
interestfor="tooltip-interestfor"
|
|
100
|
+
/>
|
|
101
|
+
</ToolTip>
|
|
102
|
+
</AlignBox>
|
|
103
|
+
</>
|
|
104
|
+
),
|
|
105
|
+
play: async ({ canvas, canvasElement, userEvent }) => {
|
|
106
|
+
const clickTooltip = canvasElement.querySelector("#tooltip-commandfor");
|
|
107
|
+
const hoverTrigger = canvas.getByRole("button", {
|
|
108
|
+
name: "Meer informatie (hover om te openen)",
|
|
109
|
+
});
|
|
110
|
+
expect(clickTooltip).not.toBeVisible();
|
|
111
|
+
|
|
112
|
+
await userEvent.click(
|
|
113
|
+
canvas.getByRole("button", {
|
|
114
|
+
name: "Meer informatie (klik om te openen)",
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
await waitFor(() => expect(clickTooltip).toBeVisible());
|
|
118
|
+
|
|
119
|
+
expect(hoverTrigger).toHaveAttribute("interestfor", "tooltip-interestfor");
|
|
120
|
+
// await userEvent.hover(hoverTrigger);
|
|
121
|
+
|
|
122
|
+
// // Interest Invokers defines a show delay before the interest state
|
|
123
|
+
// // activates, so give it a moment beyond hover before checking. Even with
|
|
124
|
+
// // this wait, `:interest-source` never matches in the test browser: the
|
|
125
|
+
// // browser recognizes the pseudo-class (matches() doesn't throw), but
|
|
126
|
+
// // actually activating it requires an experimental flag that isn't
|
|
127
|
+
// // guaranteed to be enabled here, so that part isn't asserted.
|
|
128
|
+
// await waitForTimeout(1000);
|
|
129
|
+
// expect(() => hoverTrigger.matches(":interest-source")).not.toThrow();
|
|
130
|
+
},
|
|
131
|
+
};
|
package/src/toolTip/ToolTip.tsx
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ButtonHTMLAttributes,
|
|
3
|
-
type HTMLAttributes,
|
|
4
|
-
type HTMLProps,
|
|
5
|
-
type PropsWithChildren,
|
|
6
|
-
useId,
|
|
7
|
-
} from "react";
|
|
8
|
-
import Infobutton, { type InfoButtonProps } from "../infoButton/InfoButton";
|
|
9
|
-
import styles from "./styles.module.css";
|
|
10
|
-
|
|
11
|
-
interface ToolTipProps extends HTMLProps<HTMLButtonElement> {
|
|
12
|
-
id?: string;
|
|
13
|
-
className?: string;
|
|
14
|
-
text: string;
|
|
15
|
-
type?: ButtonHTMLAttributes<HTMLButtonElement>["type"];
|
|
16
|
-
command?: InfoButtonProps["command"];
|
|
17
|
-
commandfor?: InfoButtonProps["commandfor"];
|
|
18
|
-
interestfor?: InfoButtonProps["interestfor"];
|
|
19
|
-
popover?: HTMLAttributes<HTMLDivElement>["popover"];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const ToolTip = (props: PropsWithChildren<ToolTipProps>) => {
|
|
23
|
-
const genId: string = useId();
|
|
24
|
-
const {
|
|
25
|
-
id = genId,
|
|
26
|
-
className,
|
|
27
|
-
text,
|
|
28
|
-
command = "toggle-popover",
|
|
29
|
-
commandfor = genId,
|
|
30
|
-
interestfor = genId,
|
|
31
|
-
popover = "manual",
|
|
32
|
-
children,
|
|
33
|
-
...restProps
|
|
34
|
-
} = props;
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<>
|
|
38
|
-
{children ? (
|
|
39
|
-
children
|
|
40
|
-
) : (
|
|
41
|
-
<Infobutton
|
|
42
|
-
interestfor={interestfor}
|
|
43
|
-
commandfor={commandfor}
|
|
44
|
-
command={command}
|
|
45
|
-
{...restProps}
|
|
46
|
-
/>
|
|
47
|
-
)}
|
|
48
|
-
<div className={styles.toolTip} id={id} popover={popover} role="tooltip">
|
|
49
|
-
{text}
|
|
50
|
-
</div>
|
|
51
|
-
</>
|
|
52
|
-
);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export default ToolTip;
|
|
1
|
+
import {
|
|
2
|
+
type ButtonHTMLAttributes,
|
|
3
|
+
type HTMLAttributes,
|
|
4
|
+
type HTMLProps,
|
|
5
|
+
type PropsWithChildren,
|
|
6
|
+
useId,
|
|
7
|
+
} from "react";
|
|
8
|
+
import Infobutton, { type InfoButtonProps } from "../infoButton/InfoButton";
|
|
9
|
+
import styles from "./styles.module.css";
|
|
10
|
+
|
|
11
|
+
export interface ToolTipProps extends HTMLProps<HTMLButtonElement> {
|
|
12
|
+
id?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
text: string;
|
|
15
|
+
type?: ButtonHTMLAttributes<HTMLButtonElement>["type"];
|
|
16
|
+
command?: InfoButtonProps["command"];
|
|
17
|
+
commandfor?: InfoButtonProps["commandfor"];
|
|
18
|
+
interestfor?: InfoButtonProps["interestfor"];
|
|
19
|
+
popover?: HTMLAttributes<HTMLDivElement>["popover"];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const ToolTip = (props: PropsWithChildren<ToolTipProps>) => {
|
|
23
|
+
const genId: string = useId();
|
|
24
|
+
const {
|
|
25
|
+
id = genId,
|
|
26
|
+
className,
|
|
27
|
+
text,
|
|
28
|
+
command = "toggle-popover",
|
|
29
|
+
commandfor = genId,
|
|
30
|
+
interestfor = genId,
|
|
31
|
+
popover = "manual",
|
|
32
|
+
children,
|
|
33
|
+
...restProps
|
|
34
|
+
} = props;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
{children ? (
|
|
39
|
+
children
|
|
40
|
+
) : (
|
|
41
|
+
<Infobutton
|
|
42
|
+
interestfor={interestfor}
|
|
43
|
+
commandfor={commandfor}
|
|
44
|
+
command={command}
|
|
45
|
+
{...restProps}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
<div className={styles.toolTip} id={id} popover={popover} role="tooltip">
|
|
49
|
+
{text}
|
|
50
|
+
</div>
|
|
51
|
+
</>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default ToolTip;
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
--don-tooltip-border-color: var(--rhc-color-cool-grey-300);
|
|
3
|
-
--don-tooltip-background-color: var(--rhc-color-cool-grey-50);
|
|
4
|
-
--don-tooltip-border-radius: var(--rhc-border-radius-md);
|
|
5
|
-
--don-tooltip-font-size: 0.875rem;
|
|
6
|
-
--don-tooltip-font-weigth: normal;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.triggerButton {
|
|
10
|
-
appearance: none;
|
|
11
|
-
cursor: pointer;
|
|
12
|
-
background: none;
|
|
13
|
-
border: none;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.toolTip {
|
|
17
|
-
position-area: block-end span-all;
|
|
18
|
-
border: var(--don-tooltip-border-width, 1px) solid
|
|
19
|
-
var(--don-tooltip-border-color, #cbd5e1);
|
|
20
|
-
border-radius: var(--don-tooltip-border-radius, 5px);
|
|
21
|
-
background-color: var(--don-tooltip-background-color, #f8fafc);
|
|
22
|
-
box-shadow: 0 0 1px 2px rgb(127, 127, 127, 0.05);
|
|
23
|
-
font-size: var(--don-tooltip-font-size, inherit);
|
|
24
|
-
font-weight: var(--don-tooltip-font-weigth, normal);
|
|
25
|
-
padding-block: var(--don-tooltip-padding-block, 0.5rem);
|
|
26
|
-
padding-inline: var(
|
|
27
|
-
--don-tooltip-padding-inline,
|
|
28
|
-
var(--don-tooltip-padding-block, 0.5rem)
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
/* needed for triangle */
|
|
32
|
-
margin: 5px;
|
|
33
|
-
overflow: visible;
|
|
34
|
-
|
|
35
|
-
&::before {
|
|
36
|
-
content: '';
|
|
37
|
-
display: block;
|
|
38
|
-
position: absolute;
|
|
39
|
-
position-area: top;
|
|
40
|
-
top: -5px;
|
|
41
|
-
left: calc(50% - 5px);
|
|
42
|
-
width: 0;
|
|
43
|
-
height: 0;
|
|
44
|
-
border-left: 5px solid transparent;
|
|
45
|
-
border-right: 5px solid transparent;
|
|
46
|
-
|
|
47
|
-
border-bottom: 5px solid var(--don-tooltip-border-color, #cbd5e1);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
1
|
+
:root {
|
|
2
|
+
--don-tooltip-border-color: var(--rhc-color-cool-grey-300);
|
|
3
|
+
--don-tooltip-background-color: var(--rhc-color-cool-grey-50);
|
|
4
|
+
--don-tooltip-border-radius: var(--rhc-border-radius-md);
|
|
5
|
+
--don-tooltip-font-size: 0.875rem;
|
|
6
|
+
--don-tooltip-font-weigth: normal;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.triggerButton {
|
|
10
|
+
appearance: none;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
background: none;
|
|
13
|
+
border: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.toolTip {
|
|
17
|
+
position-area: block-end span-all;
|
|
18
|
+
border: var(--don-tooltip-border-width, 1px) solid
|
|
19
|
+
var(--don-tooltip-border-color, #cbd5e1);
|
|
20
|
+
border-radius: var(--don-tooltip-border-radius, 5px);
|
|
21
|
+
background-color: var(--don-tooltip-background-color, #f8fafc);
|
|
22
|
+
box-shadow: 0 0 1px 2px rgb(127, 127, 127, 0.05);
|
|
23
|
+
font-size: var(--don-tooltip-font-size, inherit);
|
|
24
|
+
font-weight: var(--don-tooltip-font-weigth, normal);
|
|
25
|
+
padding-block: var(--don-tooltip-padding-block, 0.5rem);
|
|
26
|
+
padding-inline: var(
|
|
27
|
+
--don-tooltip-padding-inline,
|
|
28
|
+
var(--don-tooltip-padding-block, 0.5rem)
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
/* needed for triangle */
|
|
32
|
+
margin: 5px;
|
|
33
|
+
overflow: visible;
|
|
34
|
+
|
|
35
|
+
&::before {
|
|
36
|
+
content: '';
|
|
37
|
+
display: block;
|
|
38
|
+
position: absolute;
|
|
39
|
+
position-area: top;
|
|
40
|
+
top: -5px;
|
|
41
|
+
left: calc(50% - 5px);
|
|
42
|
+
width: 0;
|
|
43
|
+
height: 0;
|
|
44
|
+
border-left: 5px solid transparent;
|
|
45
|
+
border-right: 5px solid transparent;
|
|
46
|
+
|
|
47
|
+
border-bottom: 5px solid var(--don-tooltip-border-color, #cbd5e1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import TopNavigation from "./TopNavigation";
|
|
3
|
+
|
|
4
|
+
const items = [
|
|
5
|
+
{ id: "home", label: "Home", href: "https://developer.overheid.nl" },
|
|
6
|
+
{
|
|
7
|
+
id: "kennisbank",
|
|
8
|
+
label: "Kennisbank",
|
|
9
|
+
href: "https://developer.overheid.nl/kennisbank",
|
|
10
|
+
},
|
|
11
|
+
{ id: "apis", label: "API's", href: "/apis", current: true },
|
|
12
|
+
{
|
|
13
|
+
id: "oss",
|
|
14
|
+
label: "Repositories",
|
|
15
|
+
href: "https://oss.developer.overheid.nl",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "communities",
|
|
19
|
+
label: "Communities",
|
|
20
|
+
href: "https://developer.overheid.nl/communities",
|
|
21
|
+
},
|
|
22
|
+
{ id: "blog", label: "Blog", href: "https://developer.overheid.nl/blog" },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const endItems = [
|
|
26
|
+
{
|
|
27
|
+
id: "opendata",
|
|
28
|
+
label: "Open Data",
|
|
29
|
+
href: "https://data.overheid.nl",
|
|
30
|
+
icon: "_external",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "geodata",
|
|
34
|
+
label: "Geodata",
|
|
35
|
+
href: "https://www.pdok.nl",
|
|
36
|
+
icon: "_external",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "github",
|
|
40
|
+
label: "GitHub",
|
|
41
|
+
href: "https://github.com/developer-overheid-nl/don-register-site",
|
|
42
|
+
icon: "_external",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* TopNavigation toont de hoofdnavigatie (`items`) en optioneel een tweede
|
|
48
|
+
* groep aan het einde (`endItems`). Het huidige item wordt vetgedrukt
|
|
49
|
+
* getoond, en `icon` accepteert een korte sleutel (`_add`, `_external`) die
|
|
50
|
+
* automatisch naar het juiste icoon wordt omgezet.
|
|
51
|
+
*/
|
|
52
|
+
const meta = {
|
|
53
|
+
title: "Components/TopNavigation",
|
|
54
|
+
component: TopNavigation,
|
|
55
|
+
tags: ["autodocs", "custom"],
|
|
56
|
+
args: {
|
|
57
|
+
items,
|
|
58
|
+
endItems,
|
|
59
|
+
},
|
|
60
|
+
} satisfies Meta<typeof TopNavigation>;
|
|
61
|
+
|
|
62
|
+
export default meta;
|
|
63
|
+
type Story = StoryObj<typeof meta>;
|
|
64
|
+
|
|
65
|
+
export const Default: Story = {};
|
|
66
|
+
|
|
67
|
+
export const WithoutEndItems: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
endItems: undefined,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type IconProps,
|
|
3
|
-
NavBar,
|
|
4
|
-
type NavBarItemProps,
|
|
5
|
-
} from "@rijkshuisstijl-community/components-react";
|
|
6
|
-
import type { ReactElement } from "react";
|
|
7
|
-
import Icon from "../iconsSprite/Icon";
|
|
8
|
-
import styles from "./styles.module.css";
|
|
9
|
-
|
|
10
|
-
export interface NavBarItem {
|
|
11
|
-
id: string;
|
|
12
|
-
label: string;
|
|
13
|
-
href: string;
|
|
14
|
-
current?: boolean;
|
|
15
|
-
icon?: string | ReactElement<IconProps>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface TopNavigationProps {
|
|
19
|
-
items: Array<NavBarItem>;
|
|
20
|
-
endItems?: Array<NavBarItem>;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const processIcon = (
|
|
24
|
-
icon: NavBarItem["icon"],
|
|
25
|
-
): ReactElement<IconProps> | undefined => {
|
|
26
|
-
if (typeof icon === "string") {
|
|
27
|
-
switch (icon) {
|
|
28
|
-
case "_add":
|
|
29
|
-
return <Icon name="plus-cirkel-inline" />;
|
|
30
|
-
case "_external":
|
|
31
|
-
return (
|
|
32
|
-
<Icon name="externe-link-inline" aria-label={`Externe link naar`} />
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
return icon;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const processNavBarItems = (
|
|
41
|
-
items: Array<NavBarItem>,
|
|
42
|
-
): NavBarItemProps[] => {
|
|
43
|
-
return items.map((item) => {
|
|
44
|
-
const { current, ...rest } = item;
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
...rest,
|
|
48
|
-
bold: current,
|
|
49
|
-
icon: processIcon(item.icon),
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export default function TopNavigation({ items, endItems }: TopNavigationProps) {
|
|
55
|
-
const processedItems = processNavBarItems(items);
|
|
56
|
-
const processedEndItems = endItems && processNavBarItems(endItems);
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<div className={styles.container}>
|
|
60
|
-
<NavBar
|
|
61
|
-
items={processedItems}
|
|
62
|
-
endItems={processedEndItems}
|
|
63
|
-
className={styles.navbar}
|
|
64
|
-
/>
|
|
65
|
-
</div>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
type IconProps,
|
|
3
|
+
NavBar,
|
|
4
|
+
type NavBarItemProps,
|
|
5
|
+
} from "@rijkshuisstijl-community/components-react";
|
|
6
|
+
import type { ReactElement } from "react";
|
|
7
|
+
import Icon from "../iconsSprite/Icon";
|
|
8
|
+
import styles from "./styles.module.css";
|
|
9
|
+
|
|
10
|
+
export interface NavBarItem {
|
|
11
|
+
id: string;
|
|
12
|
+
label: string;
|
|
13
|
+
href: string;
|
|
14
|
+
current?: boolean;
|
|
15
|
+
icon?: string | ReactElement<IconProps>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface TopNavigationProps {
|
|
19
|
+
items: Array<NavBarItem>;
|
|
20
|
+
endItems?: Array<NavBarItem>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const processIcon = (
|
|
24
|
+
icon: NavBarItem["icon"],
|
|
25
|
+
): ReactElement<IconProps> | undefined => {
|
|
26
|
+
if (typeof icon === "string") {
|
|
27
|
+
switch (icon) {
|
|
28
|
+
case "_add":
|
|
29
|
+
return <Icon name="plus-cirkel-inline" />;
|
|
30
|
+
case "_external":
|
|
31
|
+
return (
|
|
32
|
+
<Icon name="externe-link-inline" aria-label={`Externe link naar`} />
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
return icon;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const processNavBarItems = (
|
|
41
|
+
items: Array<NavBarItem>,
|
|
42
|
+
): NavBarItemProps[] => {
|
|
43
|
+
return items.map((item) => {
|
|
44
|
+
const { current, ...rest } = item;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...rest,
|
|
48
|
+
bold: current,
|
|
49
|
+
icon: processIcon(item.icon),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export default function TopNavigation({ items, endItems }: TopNavigationProps) {
|
|
55
|
+
const processedItems = processNavBarItems(items);
|
|
56
|
+
const processedEndItems = endItems && processNavBarItems(endItems);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className={styles.container}>
|
|
60
|
+
<NavBar
|
|
61
|
+
items={processedItems}
|
|
62
|
+
endItems={processedEndItems}
|
|
63
|
+
className={styles.navbar}
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
.container {
|
|
2
|
-
/* border-block-end: 1px solid var(--rhc-nav-bar-border-color); */
|
|
3
|
-
margin-block-end: 1rem;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.navbar {
|
|
7
|
-
:global(.rhc-nav-bar__link) {
|
|
8
|
-
align-items: center;
|
|
9
|
-
:global(.don-icon-externe-link-inline) {
|
|
10
|
-
order: 1;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@media (--md-and-below-viewport) {
|
|
16
|
-
.navbar {
|
|
17
|
-
flex-wrap: wrap;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/* TODO: hamburger menu ? */
|
|
22
|
-
@media (--xs-and-below-viewport) {
|
|
23
|
-
.navbar.navbar {
|
|
24
|
-
flex-direction: column;
|
|
25
|
-
align-items: stretch;
|
|
26
|
-
|
|
27
|
-
:global(.rhc-nav-bar__list) {
|
|
28
|
-
justify-content: center;
|
|
29
|
-
border-block-end: 1px solid var(--rhc-nav-bar-border-color);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
:global(.rhc-nav-bar__list--end) {
|
|
33
|
-
margin-inline-start: revert;
|
|
34
|
-
border-block-end: revert;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@media (--xxs-and-below-viewport) {
|
|
40
|
-
.navbar {
|
|
41
|
-
font-size: 0.875rem;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
@media (--xxxs-viewport) {
|
|
46
|
-
.navbar {
|
|
47
|
-
font-size: 0.75rem;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/* modifier style wasn't implemented in RHC */
|
|
52
|
-
:global(.rhc-nav-bar__link--bold) {
|
|
53
|
-
font-weight: bold;
|
|
54
|
-
}
|
|
1
|
+
.container {
|
|
2
|
+
/* border-block-end: 1px solid var(--rhc-nav-bar-border-color); */
|
|
3
|
+
margin-block-end: 1rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.navbar {
|
|
7
|
+
:global(.rhc-nav-bar__link) {
|
|
8
|
+
align-items: center;
|
|
9
|
+
:global(.don-icon-externe-link-inline) {
|
|
10
|
+
order: 1;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (--md-and-below-viewport) {
|
|
16
|
+
.navbar {
|
|
17
|
+
flex-wrap: wrap;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* TODO: hamburger menu ? */
|
|
22
|
+
@media (--xs-and-below-viewport) {
|
|
23
|
+
.navbar.navbar {
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
align-items: stretch;
|
|
26
|
+
|
|
27
|
+
:global(.rhc-nav-bar__list) {
|
|
28
|
+
justify-content: center;
|
|
29
|
+
border-block-end: 1px solid var(--rhc-nav-bar-border-color);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:global(.rhc-nav-bar__list--end) {
|
|
33
|
+
margin-inline-start: revert;
|
|
34
|
+
border-block-end: revert;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media (--xxs-and-below-viewport) {
|
|
40
|
+
.navbar {
|
|
41
|
+
font-size: 0.875rem;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@media (--xxxs-viewport) {
|
|
46
|
+
.navbar {
|
|
47
|
+
font-size: 0.75rem;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* modifier style wasn't implemented in RHC */
|
|
52
|
+
:global(.rhc-nav-bar__link--bold) {
|
|
53
|
+
font-weight: bold;
|
|
54
|
+
}
|