@developer-overheid-nl/don-register-components 1.3.1 → 1.6.2
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 +176 -130
- package/LICENSE.md +291 -291
- package/README.md +20 -20
- package/package.json +10 -8
- package/src/Introduction.mdx +52 -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 -56
- 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 -419
- 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
|
@@ -1,133 +1,135 @@
|
|
|
1
|
-
import clsx from "clsx";
|
|
2
|
-
|
|
3
|
-
export interface ScoreBadgeProps {
|
|
4
|
-
className?: string;
|
|
5
|
-
name: string;
|
|
6
|
-
ariaLabelPrefix?: string;
|
|
7
|
-
score?: number | null;
|
|
8
|
-
max?: number;
|
|
9
|
-
showScore?: boolean;
|
|
10
|
-
showMax?: boolean;
|
|
11
|
-
inPercentage?: boolean;
|
|
12
|
-
colors?: {
|
|
13
|
-
background: string;
|
|
14
|
-
gradient: string[];
|
|
15
|
-
arrow: [string, string];
|
|
16
|
-
text: string;
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
|
|
3
|
+
export interface ScoreBadgeProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
name: string;
|
|
6
|
+
ariaLabelPrefix?: string;
|
|
7
|
+
score?: number | null;
|
|
8
|
+
max?: number;
|
|
9
|
+
showScore?: boolean;
|
|
10
|
+
showMax?: boolean;
|
|
11
|
+
inPercentage?: boolean;
|
|
12
|
+
colors?: {
|
|
13
|
+
background: string;
|
|
14
|
+
gradient: string[];
|
|
15
|
+
arrow: [string, string];
|
|
16
|
+
text: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Not used anymore. This component will be removed in a later version.
|
|
22
|
+
*/
|
|
23
|
+
export default function ScoreBadge(props: ScoreBadgeProps) {
|
|
24
|
+
const defaultcolors: ScoreBadgeProps["colors"] = {
|
|
25
|
+
background: "#CBD5E1",
|
|
26
|
+
gradient: ["#FEE9B7", "#FDDE94", "#A5C991", "#6AA549", "#39870C"],
|
|
27
|
+
arrow: ["#D52B1E", "#F9DFDD"],
|
|
28
|
+
text: "#334155",
|
|
29
|
+
};
|
|
30
|
+
const {
|
|
31
|
+
className,
|
|
32
|
+
name,
|
|
33
|
+
ariaLabelPrefix,
|
|
34
|
+
score,
|
|
35
|
+
max = 10,
|
|
36
|
+
showScore = true,
|
|
37
|
+
showMax = false,
|
|
38
|
+
inPercentage = false,
|
|
39
|
+
colors = defaultcolors,
|
|
40
|
+
...restProps
|
|
41
|
+
} = props;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<span
|
|
45
|
+
className={clsx(["score-badge", `score-badge--${score}`, className])}
|
|
46
|
+
{...restProps}
|
|
47
|
+
>
|
|
48
|
+
<svg
|
|
49
|
+
width="5rem"
|
|
50
|
+
height="2.5rem"
|
|
51
|
+
viewBox="0 0 32 16"
|
|
52
|
+
name={name}
|
|
53
|
+
role="img"
|
|
54
|
+
aria-label={`${ariaLabelPrefix || ""}${score + (inPercentage ? "%" : "") || "onbekend"}`}
|
|
55
|
+
>
|
|
56
|
+
<defs>
|
|
57
|
+
<linearGradient id="gradient">
|
|
58
|
+
{colors.gradient?.map((color, index) => (
|
|
59
|
+
<stop
|
|
60
|
+
key={`grd-${color}`}
|
|
61
|
+
offset={`${(index * 100) / (colors.gradient.length - 1)}%`}
|
|
62
|
+
style={{ stopColor: color, stopOpacity: 1 }}
|
|
63
|
+
/>
|
|
64
|
+
))}
|
|
65
|
+
</linearGradient>
|
|
66
|
+
<linearGradient id="arrow" gradientTransform="rotate(90)">
|
|
67
|
+
{colors.arrow?.map((color, index) => (
|
|
68
|
+
<stop
|
|
69
|
+
key={`arr-${color}`}
|
|
70
|
+
offset={index}
|
|
71
|
+
style={{ stopColor: color }}
|
|
72
|
+
/>
|
|
73
|
+
))}
|
|
74
|
+
</linearGradient>
|
|
75
|
+
<filter id="glow">
|
|
76
|
+
<feDropShadow
|
|
77
|
+
dx="0.25"
|
|
78
|
+
dy="0.25"
|
|
79
|
+
stdDeviation="0.5"
|
|
80
|
+
floodColor="#fff"
|
|
81
|
+
floodOpacity="1"
|
|
82
|
+
/>
|
|
83
|
+
</filter>
|
|
84
|
+
</defs>
|
|
85
|
+
<circle
|
|
86
|
+
cx="16"
|
|
87
|
+
cy="13"
|
|
88
|
+
r="10"
|
|
89
|
+
fill="none"
|
|
90
|
+
stroke={colors.background}
|
|
91
|
+
strokeWidth="5"
|
|
92
|
+
strokeDasharray={`${Math.PI * 10} 1000`}
|
|
93
|
+
strokeDashoffset={-1 * Math.PI * 10}
|
|
94
|
+
strokeLinecap="round"
|
|
95
|
+
/>
|
|
96
|
+
{score && score > 0 && (
|
|
97
|
+
<>
|
|
98
|
+
<circle
|
|
99
|
+
cx="16"
|
|
100
|
+
cy="13"
|
|
101
|
+
r="10"
|
|
102
|
+
fill="none"
|
|
103
|
+
stroke="url(#gradient)"
|
|
104
|
+
strokeWidth="5"
|
|
105
|
+
strokeDasharray={`${(Math.PI * 10 * score) / max} 1000`}
|
|
106
|
+
strokeDashoffset={-1 * Math.PI * 10}
|
|
107
|
+
strokeLinecap="round"
|
|
108
|
+
/>
|
|
109
|
+
<polygon
|
|
110
|
+
points="16,15 14,13 16,2 18,13"
|
|
111
|
+
transform={`rotate(${-90 + score * 1.8}, 16, 13)`}
|
|
112
|
+
fill="url(#arrow)"
|
|
113
|
+
/>
|
|
114
|
+
</>
|
|
115
|
+
)}
|
|
116
|
+
{showScore && (
|
|
117
|
+
<text
|
|
118
|
+
x="16"
|
|
119
|
+
y="15"
|
|
120
|
+
textAnchor="middle"
|
|
121
|
+
fontSize="0.4rem"
|
|
122
|
+
fontWeight={600}
|
|
123
|
+
fill={colors.text}
|
|
124
|
+
lengthAdjust="spacing"
|
|
125
|
+
filter="url(#glow)"
|
|
126
|
+
>
|
|
127
|
+
{typeof score === "number"
|
|
128
|
+
? `${score}${showMax ? `/${max}` : ""}${inPercentage ? "%" : ""}`
|
|
129
|
+
: "–"}
|
|
130
|
+
</text>
|
|
131
|
+
)}
|
|
132
|
+
</svg>
|
|
133
|
+
</span>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { expect } from "storybook/test";
|
|
3
|
+
import Block from "../block/Block";
|
|
4
|
+
import Search from "./Search";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Search is een zoekformulier (native GET-formulier) met een zoekveld en
|
|
8
|
+
* verzendknop. Actieve filters kunnen worden meegestuurd als verborgen
|
|
9
|
+
* velden via `hiddenFields`.
|
|
10
|
+
*/
|
|
11
|
+
const meta = {
|
|
12
|
+
title: "Components/Search",
|
|
13
|
+
component: Search,
|
|
14
|
+
tags: ["autodocs", "custom"],
|
|
15
|
+
args: {
|
|
16
|
+
searchUrl: "/apis",
|
|
17
|
+
searchKey: "q",
|
|
18
|
+
},
|
|
19
|
+
decorators: [
|
|
20
|
+
(Story) => (
|
|
21
|
+
<Block style={{ maxWidth: 400 }}>
|
|
22
|
+
<Story />
|
|
23
|
+
</Block>
|
|
24
|
+
),
|
|
25
|
+
],
|
|
26
|
+
} satisfies Meta<typeof Search>;
|
|
27
|
+
|
|
28
|
+
export default meta;
|
|
29
|
+
type Story = StoryObj<typeof meta>;
|
|
30
|
+
|
|
31
|
+
export const Default: Story = {};
|
|
32
|
+
|
|
33
|
+
export const WithSearchTerm: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
searchTerm: "adressen",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const WithHiddenFields: Story = {
|
|
40
|
+
name: "Met verborgen velden (actieve filters)",
|
|
41
|
+
args: {
|
|
42
|
+
hiddenFields: [
|
|
43
|
+
["organisation", "kadaster"],
|
|
44
|
+
["lifecycle", "active"],
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
play: async ({ canvas, canvasElement, userEvent }) => {
|
|
48
|
+
const form = canvasElement.querySelector("form");
|
|
49
|
+
// Prevent the native GET submit from navigating away during the test.
|
|
50
|
+
form?.addEventListener("submit", (event) => event.preventDefault());
|
|
51
|
+
|
|
52
|
+
await expect(form?.querySelector('input[name="organisation"]')).toHaveValue(
|
|
53
|
+
"kadaster",
|
|
54
|
+
);
|
|
55
|
+
await expect(form?.querySelector('input[name="lifecycle"]')).toHaveValue(
|
|
56
|
+
"active",
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const searchInput = canvas.getByLabelText("Voer een zoekterm in");
|
|
60
|
+
await userEvent.type(searchInput, "kadaster");
|
|
61
|
+
await expect(searchInput).toHaveValue("kadaster");
|
|
62
|
+
|
|
63
|
+
await userEvent.click(canvas.getByRole("button", { name: "Zoek" }));
|
|
64
|
+
},
|
|
65
|
+
};
|
package/src/search/Search.tsx
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FormFieldTextInput,
|
|
3
|
-
PrimaryActionButton,
|
|
4
|
-
} from "@rijkshuisstijl-community/components-react";
|
|
5
|
-
import clsx from "clsx";
|
|
6
|
-
import type { PropsWithChildren } from "react";
|
|
7
|
-
import { I18nextProvider, useTranslation } from "react-i18next";
|
|
8
|
-
import Heading from "../heading/Heading";
|
|
9
|
-
import i18n from "../i18n";
|
|
10
|
-
import Icon from "../iconsSprite/Icon";
|
|
11
|
-
import styles from "./styles.module.css";
|
|
12
|
-
|
|
13
|
-
export interface SearchProps {
|
|
14
|
-
searchUrl: string;
|
|
15
|
-
searchKey?: string;
|
|
16
|
-
searchTerm?: string;
|
|
17
|
-
hiddenFields?: [string, string][];
|
|
18
|
-
className?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const Search = (props: SearchProps) => {
|
|
22
|
-
const { t } = useTranslation();
|
|
23
|
-
const {
|
|
24
|
-
searchUrl,
|
|
25
|
-
searchKey = "q",
|
|
26
|
-
searchTerm,
|
|
27
|
-
hiddenFields = [],
|
|
28
|
-
className,
|
|
29
|
-
} = props;
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<search
|
|
33
|
-
aria-labelledby="search-heading"
|
|
34
|
-
className={clsx(styles.search, className)}
|
|
35
|
-
>
|
|
36
|
-
<Heading id="search-heading" level={2} appearanceLevel={3}>
|
|
37
|
-
{t("components.search")}
|
|
38
|
-
</Heading>
|
|
39
|
-
<form action={searchUrl} method="GET" className={styles.form}>
|
|
40
|
-
{hiddenFields.map(([name, value], index) => (
|
|
41
|
-
<input
|
|
42
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: duplicate query params can share name and value
|
|
43
|
-
key={`${name}-${value}-${index}`}
|
|
44
|
-
type="hidden"
|
|
45
|
-
name={name}
|
|
46
|
-
value={value}
|
|
47
|
-
/>
|
|
48
|
-
))}
|
|
49
|
-
<FormFieldTextInput
|
|
50
|
-
className={styles.input}
|
|
51
|
-
aria-describedby="search-help"
|
|
52
|
-
label={t("components.search-label")}
|
|
53
|
-
name={searchKey}
|
|
54
|
-
type="text"
|
|
55
|
-
defaultValue={searchTerm}
|
|
56
|
-
>
|
|
57
|
-
<div className="sr-only" id="search-help">
|
|
58
|
-
{t("components.search-help")}
|
|
59
|
-
</div>
|
|
60
|
-
</FormFieldTextInput>
|
|
61
|
-
|
|
62
|
-
<PrimaryActionButton
|
|
63
|
-
aria-label={t("components.search-button")}
|
|
64
|
-
className={styles.button}
|
|
65
|
-
type="submit"
|
|
66
|
-
>
|
|
67
|
-
<Icon name="zoek-inline" width="1.5rem" height="1.5rem" />
|
|
68
|
-
</PrimaryActionButton>
|
|
69
|
-
</form>
|
|
70
|
-
</search>
|
|
71
|
-
);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const TranslatedSearch = (props: PropsWithChildren<SearchProps>) => {
|
|
75
|
-
return (
|
|
76
|
-
<I18nextProvider i18n={i18n}>
|
|
77
|
-
<Search {...props} />
|
|
78
|
-
</I18nextProvider>
|
|
79
|
-
);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export default TranslatedSearch;
|
|
1
|
+
import {
|
|
2
|
+
FormFieldTextInput,
|
|
3
|
+
PrimaryActionButton,
|
|
4
|
+
} from "@rijkshuisstijl-community/components-react";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import type { PropsWithChildren } from "react";
|
|
7
|
+
import { I18nextProvider, useTranslation } from "react-i18next";
|
|
8
|
+
import Heading from "../heading/Heading";
|
|
9
|
+
import i18n from "../i18n";
|
|
10
|
+
import Icon from "../iconsSprite/Icon";
|
|
11
|
+
import styles from "./styles.module.css";
|
|
12
|
+
|
|
13
|
+
export interface SearchProps {
|
|
14
|
+
searchUrl: string;
|
|
15
|
+
searchKey?: string;
|
|
16
|
+
searchTerm?: string;
|
|
17
|
+
hiddenFields?: [string, string][];
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const Search = (props: SearchProps) => {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const {
|
|
24
|
+
searchUrl,
|
|
25
|
+
searchKey = "q",
|
|
26
|
+
searchTerm,
|
|
27
|
+
hiddenFields = [],
|
|
28
|
+
className,
|
|
29
|
+
} = props;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<search
|
|
33
|
+
aria-labelledby="search-heading"
|
|
34
|
+
className={clsx(styles.search, className)}
|
|
35
|
+
>
|
|
36
|
+
<Heading id="search-heading" level={2} appearanceLevel={3}>
|
|
37
|
+
{t("components.search")}
|
|
38
|
+
</Heading>
|
|
39
|
+
<form action={searchUrl} method="GET" className={styles.form}>
|
|
40
|
+
{hiddenFields.map(([name, value], index) => (
|
|
41
|
+
<input
|
|
42
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: duplicate query params can share name and value
|
|
43
|
+
key={`${name}-${value}-${index}`}
|
|
44
|
+
type="hidden"
|
|
45
|
+
name={name}
|
|
46
|
+
value={value}
|
|
47
|
+
/>
|
|
48
|
+
))}
|
|
49
|
+
<FormFieldTextInput
|
|
50
|
+
className={styles.input}
|
|
51
|
+
aria-describedby="search-help"
|
|
52
|
+
label={t("components.search-label")}
|
|
53
|
+
name={searchKey}
|
|
54
|
+
type="text"
|
|
55
|
+
defaultValue={searchTerm}
|
|
56
|
+
>
|
|
57
|
+
<div className="sr-only" id="search-help">
|
|
58
|
+
{t("components.search-help")}
|
|
59
|
+
</div>
|
|
60
|
+
</FormFieldTextInput>
|
|
61
|
+
|
|
62
|
+
<PrimaryActionButton
|
|
63
|
+
aria-label={t("components.search-button")}
|
|
64
|
+
className={styles.button}
|
|
65
|
+
type="submit"
|
|
66
|
+
>
|
|
67
|
+
<Icon name="zoek-inline" width="1.5rem" height="1.5rem" aria-hidden />
|
|
68
|
+
</PrimaryActionButton>
|
|
69
|
+
</form>
|
|
70
|
+
</search>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const TranslatedSearch = (props: PropsWithChildren<SearchProps>) => {
|
|
75
|
+
return (
|
|
76
|
+
<I18nextProvider i18n={i18n}>
|
|
77
|
+
<Search {...props} />
|
|
78
|
+
</I18nextProvider>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default TranslatedSearch;
|
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
.search {
|
|
2
|
-
--utrecht-textbox-border-width: 2px;
|
|
3
|
-
--utrecht-textbox-border-radius: 5px;
|
|
4
|
-
--utrecht-textbox-border-color: var(--rhc-color-cool-grey-900);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.form {
|
|
8
|
-
display: grid;
|
|
9
|
-
grid-template-areas: 'input button';
|
|
10
|
-
grid-template-columns: auto min-content;
|
|
11
|
-
gap: 0;
|
|
12
|
-
align-items: end;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
@media (--xxs-and-below-viewport) {
|
|
16
|
-
.form {
|
|
17
|
-
justify-content: center;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
.input {
|
|
22
|
-
grid-area: input;
|
|
23
|
-
|
|
24
|
-
:global(.utrecht-textbox) {
|
|
25
|
-
|
|
26
|
-
border-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
border-
|
|
39
|
-
|
|
1
|
+
.search {
|
|
2
|
+
--utrecht-textbox-border-width: 2px;
|
|
3
|
+
--utrecht-textbox-border-radius: 5px;
|
|
4
|
+
--utrecht-textbox-border-color: var(--rhc-color-cool-grey-900);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.form {
|
|
8
|
+
display: grid;
|
|
9
|
+
grid-template-areas: 'input button';
|
|
10
|
+
grid-template-columns: auto min-content;
|
|
11
|
+
gap: 0;
|
|
12
|
+
align-items: end;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (--xxs-and-below-viewport) {
|
|
16
|
+
.form {
|
|
17
|
+
justify-content: center;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.input {
|
|
22
|
+
grid-area: input;
|
|
23
|
+
|
|
24
|
+
:global(.utrecht-textbox) {
|
|
25
|
+
max-width: none;
|
|
26
|
+
border-top-right-radius: 0;
|
|
27
|
+
border-bottom-right-radius: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:global(.utrecht-textbox--html-input:focus-visible) {
|
|
31
|
+
position: relative;
|
|
32
|
+
z-index: 1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.button:global(.utrecht-button) {
|
|
37
|
+
grid-area: button;
|
|
38
|
+
border-top-left-radius: 0;
|
|
39
|
+
border-bottom-left-radius: 0;
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import Logo from "../../../../proprietary-example/logos/react/Logo";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Dit is het placeholder-logo uit `proprietary-example`, het sjabloon voor
|
|
6
|
+
* organisaties die deze componentenbibliotheek naar hun eigen huisstijl
|
|
7
|
+
* willen aanpassen. `SiteLogo` gebruikt in dit project echter het echte
|
|
8
|
+
* logo uit `proprietary-don` (via de `@developer-overheid-nl/proprietary`-
|
|
9
|
+
* alias), dus dit voorbeeldlogo wordt in productie niet gebruikt.
|
|
10
|
+
*/
|
|
11
|
+
const meta = {
|
|
12
|
+
title: "Components/SiteLogo/Voorbeeldlogo (proprietary-example)",
|
|
13
|
+
component: Logo,
|
|
14
|
+
tags: ["autodocs", "custom"],
|
|
15
|
+
argTypes: {
|
|
16
|
+
forced: {
|
|
17
|
+
control: "select",
|
|
18
|
+
options: [false, "light", "dark"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
} satisfies Meta<typeof Logo>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof meta>;
|
|
25
|
+
|
|
26
|
+
export const Default: Story = {};
|
|
27
|
+
|
|
28
|
+
export const ForcedLight: Story = {
|
|
29
|
+
name: "Forced light",
|
|
30
|
+
args: {
|
|
31
|
+
forced: "light",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const ForcedDark: Story = {
|
|
36
|
+
name: "Forced dark",
|
|
37
|
+
args: {
|
|
38
|
+
forced: "dark",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import SiteLogo from "./SiteLogo";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SiteLogo toont het sitelogo. Op de homepage (`isRoot`) wordt het zonder
|
|
6
|
+
* link gerenderd; elders als link naar `href`.
|
|
7
|
+
*/
|
|
8
|
+
const meta = {
|
|
9
|
+
title: "Components/SiteLogo",
|
|
10
|
+
component: SiteLogo,
|
|
11
|
+
tags: ["autodocs", "custom"],
|
|
12
|
+
args: {
|
|
13
|
+
isRoot: false,
|
|
14
|
+
href: "https://developer.overheid.nl",
|
|
15
|
+
},
|
|
16
|
+
} satisfies Meta<typeof SiteLogo>;
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Linked: Story = {};
|
|
22
|
+
|
|
23
|
+
export const Root: Story = {
|
|
24
|
+
name: "Op de homepage (geen link)",
|
|
25
|
+
args: {
|
|
26
|
+
isRoot: true,
|
|
27
|
+
},
|
|
28
|
+
};
|