diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml
index 535d653df..b25833d1c 100644
--- a/.github/workflows/chromatic.yml
+++ b/.github/workflows/chromatic.yml
@@ -34,7 +34,7 @@ jobs:
- run: yarn css:build
- name: Publish to Chromatic
- uses: chromaui/action@v11.7.1
+ uses: chromaui/action@v11.10.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: c6b96f9648b6
diff --git a/.stylelintrc b/.stylelintrc
index 6caf8a3eb..ce37096f6 100644
--- a/.stylelintrc
+++ b/.stylelintrc
@@ -1,5 +1,8 @@
{
- "extends": ["stylelint-config-recommended-scss", "stylelint-prettier/recommended"],
+ "extends": [
+ "stylelint-config-recommended-scss",
+ "stylelint-prettier/recommended"
+ ],
"rules": {
"max-nesting-depth": 3,
"selector-class-pattern": "^[a-z][a-z0-9_-]*$",
@@ -11,6 +14,18 @@
}
],
"property-no-vendor-prefix": null,
- "scss/dollar-variable-pattern": null
+ "scss/dollar-variable-pattern": null,
+ "property-no-unknown": [
+ true,
+ {
+ "ignoreProperties": ["transition-behavior"]
+ }
+ ],
+ "scss/at-rule-no-unknown": [
+ true,
+ {
+ "ignoreAtRules": ["starting-style"]
+ }
+ ]
}
}
diff --git a/admin-base.scss b/admin-base.scss
index f09652bd2..59ba8a893 100644
--- a/admin-base.scss
+++ b/admin-base.scss
@@ -1,6 +1,7 @@
@import "./src/styles/scss/tools";
// CSS sheets that are used to style the admin interface.
+@import "./src/stories/Library/dialog/dialog";
@import "./src/stories/Library/opening-hours-editor/opening-hours-editor";
@import "./src/stories/Library/material-search/material-search";
@import "./src/stories/Library/cover/cover";
diff --git a/base.scss b/base.scss
index b3acf30d5..5e798099d 100644
--- a/base.scss
+++ b/base.scss
@@ -21,6 +21,7 @@
@import "./src/stories/Library/counter/counter";
@import "./src/stories/Library/patron-info/patron-info";
@import "./src/stories/Library/Forms/checkbox/checkbox";
+@import "./src/stories/Library/Forms/radio/radio";
@import "./src/stories/Library/cover/cover";
@import "./src/stories/Library/Forms/input/input";
@import "./src/stories/Library/Forms/textarea/textarea";
@@ -138,11 +139,14 @@
@import "./src/stories/Library/opening-hours-editor/opening-hours-editor";
@import "./src/stories/Library/opening-hours/opening-hours";
@import "./src/stories/Library/opening-hours/opening-hours-skeleton";
+@import "./src/stories/Library/opening-hours-sidebar/opening-hours-sidebar";
@import "./src/stories/Library/filtered-event-list/filtered-event-list";
@import "./src/stories/Library/event-list-stacked/event-list-stacked";
@import "./src/stories/Library/material-search/material-search";
@import "./src/stories/Library/banner/banner";
@import "./src/stories/Library/simple-link/simple-link";
+@import "./src/stories/Library/search-full-text/search-full-text";
+@import "./src/stories/empty-view/empty-view";
// Autosuggest block styling needs to be loaded before the rest of the scss for autosuggest
@import "./src/stories/Blocks/autosuggest/autosuggest";
diff --git a/package.json b/package.json
index 03714cdaa..f55b62e65 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,7 @@
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^14.5.2",
- "@types/jest": "^29.5.12",
+ "@types/jest": "^29.5.13",
"@types/node": "^16.0.0",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
@@ -70,13 +70,13 @@
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "^4.2.1",
- "eslint-plugin-react": "^7.35.2",
+ "eslint-plugin-react": "^7.36.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-webpack-plugin": "^4.2.0",
"flatpickr": "^4.6.13",
"json": "^11.0.0",
"markdownlint-cli2": "^0.4.0",
- "postcss": "^8.4.45",
+ "postcss": "^8.4.47",
"prettier": "^2.7.1",
"react": "^17.0.2",
"react-docgen-typescript": "^2.1.0",
diff --git a/src/stories/Blocks/content-list-page/ContentListPage.tsx b/src/stories/Blocks/content-list-page/ContentListPage.tsx
index fa72882ff..a46ff431d 100644
--- a/src/stories/Blocks/content-list-page/ContentListPage.tsx
+++ b/src/stories/Blocks/content-list-page/ContentListPage.tsx
@@ -3,6 +3,7 @@ import ContentList from "../../Library/content-list/ContentList";
import contentListData from "../../Library/content-list/ContentListData";
import { InputLabel } from "../../Library/input-label/InputLabel";
import { Dropdown } from "../../Library/dropdown/Dropdown";
+import SearchFullText from "../../Library/search-full-text/SearchFullText";
const filters = [
{
@@ -47,6 +48,10 @@ const ContentListPage: React.FC = () => {
{
);
})}
+
+
+
+
diff --git a/src/stories/Blocks/content-list-page/content-list-page.scss b/src/stories/Blocks/content-list-page/content-list-page.scss
index 6b9c05bed..ed56a83f2 100644
--- a/src/stories/Blocks/content-list-page/content-list-page.scss
+++ b/src/stories/Blocks/content-list-page/content-list-page.scss
@@ -33,3 +33,9 @@
flex-direction: row;
}
}
+
+.content-list-page__filter--right {
+ @include media-query__small {
+ margin-left: auto;
+ }
+}
diff --git a/src/stories/Blocks/form/form.scss b/src/stories/Blocks/form/form.scss
index a9207e9aa..2a7b079fd 100644
--- a/src/stories/Blocks/form/form.scss
+++ b/src/stories/Blocks/form/form.scss
@@ -59,3 +59,35 @@
max-width: 550px;
}
}
+
+.dpl-fieldset {
+ @include typography($typo__small-caption);
+
+ border: 0;
+ padding-block-start: 0;
+ padding-block-end: 0;
+ padding-inline-start: 0;
+ padding-inline-end: 0;
+ margin-inline-start: 0;
+ margin-inline-end: 0;
+ margin-bottom: $s-lg;
+
+ legend {
+ @include typography($typo__body-medium);
+ color: $color__text-secondary-gray;
+ padding-inline-start: 0;
+ padding-inline-end: 0;
+ margin-bottom: 6px;
+ max-width: 550px;
+
+ &--full-width {
+ max-width: 750px;
+ }
+
+ &:has(p) {
+ @include typography($typo__links);
+ color: $color__global-tertiary-2;
+ max-width: 550px;
+ }
+ }
+}
diff --git a/src/stories/Blocks/header/Header.tsx b/src/stories/Blocks/header/Header.tsx
index b46b6d62c..e891f2a4b 100644
--- a/src/stories/Blocks/header/Header.tsx
+++ b/src/stories/Blocks/header/Header.tsx
@@ -150,10 +150,10 @@ export const Header = ({
diff --git a/src/stories/Blocks/header/header.scss b/src/stories/Blocks/header/header.scss
index 2f1f05f99..53eb1b06e 100644
--- a/src/stories/Blocks/header/header.scss
+++ b/src/stories/Blocks/header/header.scss
@@ -214,6 +214,7 @@
}
.header__clock {
+ height: 100%;
border-left: 1px solid $color__global-tertiary-1;
display: none;
@@ -224,9 +225,12 @@
.header__clock-items {
text-decoration: none;
+ border: none;
+ cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
+ width: 100%;
}
// has-burger-menu is added dynamically using JS, by calculating if there
diff --git a/src/stories/Library/Forms/checkbox/Checkbox.stories.tsx b/src/stories/Library/Forms/checkbox/Checkbox.stories.tsx
index 8d30847ae..079653533 100644
--- a/src/stories/Library/Forms/checkbox/Checkbox.stories.tsx
+++ b/src/stories/Library/Forms/checkbox/Checkbox.stories.tsx
@@ -1,6 +1,7 @@
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { withDesign } from "storybook-addon-designs";
import { Checkbox } from "./Checkbox";
+import { CheckboxDrupal } from "./CheckboxDrupal";
export default {
title: "Library / Forms / Checkbox",
@@ -28,6 +29,17 @@ export default {
defaultValue: "",
},
},
+ includeHeadline: {
+ control: {
+ type: "null",
+ },
+ },
+ description: {
+ control: {
+ type: "text",
+ defaultValue: "This is a description.",
+ },
+ },
// We disable the isChecked control, since it is not possible to
// get the states from the React component to work with Storybook controls.
isChecked: {
@@ -90,3 +102,21 @@ Multiple.args = {
isChecked: false,
label: "Checkbox",
};
+
+// The stories below mimic HTML structure from Drupal for checkbox usage.
+const DrupalCheckboxExample: ComponentStory = (args) => (
+
+);
+
+export const DrupalCheckbox = DrupalCheckboxExample.bind({});
+DrupalCheckbox.args = {
+ label: "Toggle this checkbox",
+ description: "This is a description.",
+};
+
+export const DrupalMultiple = DrupalCheckboxExample.bind({});
+DrupalMultiple.args = {
+ label: "Toggle this checkbox",
+ includeHeadline: true,
+ description: "This is a description.",
+};
diff --git a/src/stories/Library/Forms/checkbox/CheckboxDrupal.tsx b/src/stories/Library/Forms/checkbox/CheckboxDrupal.tsx
new file mode 100644
index 000000000..1f6ed1974
--- /dev/null
+++ b/src/stories/Library/Forms/checkbox/CheckboxDrupal.tsx
@@ -0,0 +1,94 @@
+import clsx from "clsx";
+import React from "react";
+
+export type CheckboxDrupalProps = {
+ label: string;
+ validation?: string;
+ classNames?: string;
+ includeHeadline?: boolean;
+ description?: string;
+};
+
+// This component and styling are meant to target specifically the Drupal HTML structure.
+// Note that some of the classes are also copied from there. The classes we created ourselves
+// can be found in the ./checkbox.scss file in this directory.
+export const CheckboxDrupal: React.FC = ({
+ label,
+ validation,
+ classNames,
+ includeHeadline,
+ description,
+}) => {
+ const checkboxElement = (checkboxLabel: string) => {
+ return (
+
+
+
+ {!!description && (
+
+ )}
+ {validation &&
{validation}
}
+
+ );
+ };
+
+ const checkboxElementMultiple = (checkboxLabel: string) => {
+ return (
+
+ );
+ };
+
+ return (
+
+ {includeHeadline && checkboxElementMultiple(label || "")}
+ {!includeHeadline && checkboxElement(label || "label")}
+
+ );
+};
diff --git a/src/stories/Library/Forms/checkbox/checkbox.scss b/src/stories/Library/Forms/checkbox/checkbox.scss
index da72b4632..2cf21cd8b 100644
--- a/src/stories/Library/Forms/checkbox/checkbox.scss
+++ b/src/stories/Library/Forms/checkbox/checkbox.scss
@@ -94,3 +94,38 @@
transform: scale(0.9);
}
}
+
+// Classes below are meant to target specifically overwriting Drupal component styling.
+// These checkboxes are always used inside a .dpl-input container in Drupal.
+.dpl-form {
+ .dpl-input.checkbox-override {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ padding: 6px $s-sm 6px 0;
+ margin-bottom: 0;
+ }
+
+ .dpl-input.checkbox-override input {
+ accent-color: black;
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ margin-left: 0;
+ }
+
+ .dpl-input.checkbox-override .input-label,
+ .dpl-input.checkbox-override .description {
+ @include typography($typo__small-caption);
+ color: $color__text-secondary-gray;
+ padding: 0 $s-sm 0 $s-sm;
+ width: fit-content;
+ max-width: 300px;
+ margin: 0;
+ height: auto;
+ }
+
+ .dpl-input.checkbox-override .input-label {
+ cursor: pointer;
+ }
+}
diff --git a/src/stories/Library/Forms/radio/Radio.stories.tsx b/src/stories/Library/Forms/radio/Radio.stories.tsx
new file mode 100644
index 000000000..00fab0358
--- /dev/null
+++ b/src/stories/Library/Forms/radio/Radio.stories.tsx
@@ -0,0 +1,36 @@
+import { ComponentMeta, ComponentStory } from "@storybook/react";
+import { withDesign } from "storybook-addon-designs";
+import { RadioDrupal } from "./RadioDrupal";
+
+export default {
+ title: "Library / Forms / Radio",
+ component: RadioDrupal,
+ decorators: [withDesign],
+ argTypes: {
+ legend: {
+ control: {
+ type: "text",
+ defaultValue: "This is a legend.",
+ },
+ },
+ description: {
+ control: {
+ type: "text",
+ defaultValue: "This is a description.",
+ },
+ },
+ },
+ parameters: {
+ layout: "centered",
+ },
+} as ComponentMeta;
+
+const Template: ComponentStory = (args) => (
+
+);
+
+export const drupalRadio = Template.bind({});
+drupalRadio.args = {
+ legend: "Try this radio",
+ description: "This is a description.",
+};
diff --git a/src/stories/Library/Forms/radio/RadioDrupal.tsx b/src/stories/Library/Forms/radio/RadioDrupal.tsx
new file mode 100644
index 000000000..95d710215
--- /dev/null
+++ b/src/stories/Library/Forms/radio/RadioDrupal.tsx
@@ -0,0 +1,61 @@
+export type CheckboxProps = {
+ legend?: string;
+ description?: string;
+};
+
+export const RadioDrupal: React.FC = ({
+ legend,
+ description,
+}) => {
+ return (
+
+
+
+ );
+};
diff --git a/src/stories/Library/Forms/radio/radio.scss b/src/stories/Library/Forms/radio/radio.scss
new file mode 100644
index 000000000..617ccd5a5
--- /dev/null
+++ b/src/stories/Library/Forms/radio/radio.scss
@@ -0,0 +1,32 @@
+.dpl-form {
+ .dpl-input.radio-override {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ padding: 6px $s-sm 6px 0;
+ margin-bottom: 0;
+
+ input[type="radio"] {
+ accent-color: black;
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ margin: 3px 3px 3px 0;
+ }
+
+ label,
+ .description {
+ @include typography($typo__small-caption);
+ color: $color__text-secondary-gray;
+ padding: 0 $s-sm 0 $s-sm;
+ width: fit-content;
+ max-width: 300px;
+ margin: 0;
+ height: auto;
+ }
+
+ label {
+ cursor: pointer;
+ }
+ }
+}
diff --git a/src/stories/Library/Modals/modal-pause/modal-pause.scss b/src/stories/Library/Modals/modal-pause/modal-pause.scss
index 65a2d3bd6..01cd2b874 100644
--- a/src/stories/Library/Modals/modal-pause/modal-pause.scss
+++ b/src/stories/Library/Modals/modal-pause/modal-pause.scss
@@ -38,7 +38,7 @@
box-sizing: border-box;
background-color: $color__global-primary;
min-width: 100%;
- height: 50px;
+ height: $form_input_height;
padding: 0 10px;
color: $color__text-secondary-gray;
@include typography($typo__button);
diff --git a/src/stories/Library/dialog/Dialog.tsx b/src/stories/Library/dialog/Dialog.tsx
index 1b2655369..e871a04e8 100644
--- a/src/stories/Library/dialog/Dialog.tsx
+++ b/src/stories/Library/dialog/Dialog.tsx
@@ -1,15 +1,17 @@
+import clsx from "clsx";
import React, { forwardRef } from "react";
export type DialogType = {
children: React.ReactNode;
closeDialog: () => void;
+ isSidebar?: boolean;
};
const Dialog = forwardRef(
- ({ children, closeDialog }, ref) => {
+ ({ children, closeDialog, isSidebar }, ref) => {
return (