Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.
+
+
+
+
+
+
Moitié-moitié
Fribourgeoise
+
+
+
+
Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.
+
+
format: gutenberg
summary: ''
diff --git a/packages/drupal/test_content/webforms/styling.yml b/packages/drupal/test_content/webforms/styling.yml
index 7cfdd2291..b73dbb9c2 100644
--- a/packages/drupal/test_content/webforms/styling.yml
+++ b/packages/drupal/test_content/webforms/styling.yml
@@ -25,11 +25,17 @@ elements: |-
Foo: Foo
Bar: 'Bar -- Bar has a description.'
Baz: Baz
- textfield:
- '#type': textfield
- '#title': Textfield
- '#description': 'Textfield description.'
- '#placeholder': 'Placeholder goes here'
+ flexbox:
+ '#type': webform_flexbox
+ textfield:
+ '#type': textfield
+ '#title': 'First name'
+ '#description': 'Textfield description.'
+ '#placeholder': 'Placeholder goes here'
+ '#required': true
+ last_name:
+ '#type': textfield
+ '#title': 'Last name'
email_with_a_conformation:
'#type': webform_email_confirm
'#title': 'Email with a confirmation'
@@ -56,6 +62,22 @@ elements: |-
Foo: Foo
Bar: Bar
Baz: Baz
+ terms_of_service:
+ '#type': webform_terms_of_service
+ '#title': 'I agree to the {terms of service} in modal'
+ '#required': true
+ '#terms_content': |-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a felis convallis, pharetra mauris a, eleifend justo. Sed massa ipsum, suscipit sit amet varius a, dignissim at ex. Integer euismod a sapien id auctor. Etiam dignissim scelerisque nunc in porttitor. Nam rutrum molestie mauris, a bibendum ligula. Etiam eget posuere enim. Quisque id condimentum ligula.
+
+ Duis sit amet sapien justo. Suspendisse potenti. Aliquam venenatis congue quam, quis eleifend tellus. Duis aliquam sollicitudin purus sed rutrum. Nullam vitae ante lorem. Curabitur malesuada nibh lectus, ut ultricies elit mattis sed. Ut pharetra urna nec lacus pellentesque vestibulum. Nulla turpis sem, aliquam finibus pharetra at, interdum sit amet ligula. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce ullamcorper justo in risus condimentum suscipit. Nam in nunc sit amet neque fringilla suscipit. Sed nec metus tempus, rhoncus dolor et, vehicula urna. Donec ultricies leo pharetra ante vulputate vulputate. Nullam tincidunt pharetra nisi eu faucibus. Duis efficitur, massa eget sagittis sodales, magna dolor dapibus justo, et facilisis tellus augue et est.
+ terms_of_service_01:
+ '#type': webform_terms_of_service
+ '#title': 'I agree to the {terms of service} in slideout'
+ '#terms_type': slideout
+ '#terms_content': |-
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a felis convallis, pharetra mauris a, eleifend justo. Sed massa ipsum, suscipit sit amet varius a, dignissim at ex. Integer euismod a sapien id auctor. Etiam dignissim scelerisque nunc in porttitor. Nam rutrum molestie mauris, a bibendum ligula. Etiam eget posuere enim. Quisque id condimentum ligula.
+
+ Duis sit amet sapien justo. Suspendisse potenti. Aliquam venenatis congue quam, quis eleifend tellus. Duis aliquam sollicitudin purus sed rutrum. Nullam vitae ante lorem. Curabitur malesuada nibh lectus, ut ultricies elit mattis sed. Ut pharetra urna nec lacus pellentesque vestibulum. Nulla turpis sem, aliquam finibus pharetra at, interdum sit amet ligula. In hac habitasse platea dictumst. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce ullamcorper justo in risus condimentum suscipit. Nam in nunc sit amet neque fringilla suscipit. Sed nec metus tempus, rhoncus dolor et, vehicula urna. Donec ultricies leo pharetra ante vulputate vulputate. Nullam tincidunt pharetra nisi eu faucibus. Duis efficitur, massa eget sagittis sodales, magna dolor dapibus justo, et facilisis tellus augue et est.
actions:
'#type': webform_actions
'#title': 'Submit button(s)'
diff --git a/packages/schema/src/fragments/Page.gql b/packages/schema/src/fragments/Page.gql
index cbf2227eb..59285ccc4 100644
--- a/packages/schema/src/fragments/Page.gql
+++ b/packages/schema/src/fragments/Page.gql
@@ -35,6 +35,8 @@ fragment Page on Page {
...BlockCta
...BlockImageWithText
...BlockQuote
+ ...BlockHorizontalSeparator
+ ...BlockAccordion
}
metaTags {
tag
diff --git a/packages/schema/src/fragments/PageContent/BlockAccordion.gql b/packages/schema/src/fragments/PageContent/BlockAccordion.gql
new file mode 100644
index 000000000..0f77b257d
--- /dev/null
+++ b/packages/schema/src/fragments/PageContent/BlockAccordion.gql
@@ -0,0 +1,13 @@
+fragment BlockAccordion on BlockAccordion {
+ items {
+ ...BlockAccordionItemText
+ }
+}
+
+fragment BlockAccordionItemText on BlockAccordionItemText {
+ title
+ icon
+ textContent {
+ markup
+ }
+}
diff --git a/packages/schema/src/fragments/PageContent/BlockCta.gql b/packages/schema/src/fragments/PageContent/BlockCta.gql
index 2dae0fda2..db56f5580 100644
--- a/packages/schema/src/fragments/PageContent/BlockCta.gql
+++ b/packages/schema/src/fragments/PageContent/BlockCta.gql
@@ -2,4 +2,6 @@ fragment BlockCta on BlockCta {
url
text
openInNewTab
+ icon
+ iconPosition
}
diff --git a/packages/schema/src/fragments/PageContent/BlockHorizontalSeparator.gql b/packages/schema/src/fragments/PageContent/BlockHorizontalSeparator.gql
new file mode 100644
index 000000000..ef992a139
--- /dev/null
+++ b/packages/schema/src/fragments/PageContent/BlockHorizontalSeparator.gql
@@ -0,0 +1,5 @@
+fragment BlockHorizontalSeparator on BlockHorizontalSeparator {
+ # This is not really used, but until we have other real setting fields, we
+ # have to provide a dummy one.
+ markup
+}
diff --git a/packages/schema/src/fragments/PageContent/BlockImageWithText.gql b/packages/schema/src/fragments/PageContent/BlockImageWithText.gql
index b026e8676..84da846c2 100644
--- a/packages/schema/src/fragments/PageContent/BlockImageWithText.gql
+++ b/packages/schema/src/fragments/PageContent/BlockImageWithText.gql
@@ -1,9 +1,10 @@
fragment BlockImageWithText on BlockImageWithText {
image {
- source(width: 1536, sizes: [[768, 768], [1536, 1536]])
+ source(width: 1536, height: 1336)
alt
}
textContent {
markup
}
+ imagePosition
}
diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql
index ca52d0ef3..fbeafa4e3 100644
--- a/packages/schema/src/schema.graphql
+++ b/packages/schema/src/schema.graphql
@@ -199,13 +199,15 @@ type Hero {
}
union PageContent @resolveEditorBlockType =
- BlockMarkup
+ | BlockMarkup
| BlockMedia
| BlockForm
| BlockImageTeasers
| BlockCta
| BlockImageWithText
| BlockQuote
+ | BlockHorizontalSeparator
+ | BlockAccordion
type BlockForm @type(id: "custom/form") {
url: Url @resolveEditorBlockAttribute(key: "formId") @webformIdToUrl(id: "$")
@@ -245,10 +247,33 @@ type BlockImageTeaser @default @value {
ctaUrl: Url @resolveEditorBlockAttribute(key: "ctaUrl")
}
+type BlockAccordion @type(id: "custom/accordion") {
+ items: [BlockAccordionItemText!]! @resolveEditorBlockChildren
+}
+
+type BlockAccordionItemText @default @value {
+ title: String! @resolveEditorBlockAttribute(key: "title")
+ icon: String! @resolveEditorBlockAttribute(key: "icon")
+ textContent: BlockMarkup @resolveEditorBlockChildren @seek(pos: 0)
+}
+
type BlockCta @type(id: "custom/cta") {
url: Url @resolveEditorBlockAttribute(key: "url")
text: String @resolveEditorBlockAttribute(key: "text")
openInNewTab: Boolean @resolveEditorBlockAttribute(key: "openInNewTab")
+ icon: CTAIconType @resolveEditorBlockAttribute(key: "icon")
+ iconPosition: CTAIconPosition
+ @resolveEditorBlockAttribute(key: "iconPosition")
+}
+
+enum CTAIconType {
+ NONE
+ ARROW
+}
+
+enum CTAIconPosition {
+ AFTER
+ BEFORE
}
type BlockImageWithText @type(id: "custom/image-with-text") {
@@ -270,6 +295,10 @@ type BlockQuote @type(id: "custom/quote") {
image: MediaImage @resolveEditorBlockMedia
}
+type BlockHorizontalSeparator @type(id: "custom/horizontal-separator") {
+ markup: Markup! @resolveEditorBlockMarkup
+}
+
input PaginationInput {
limit: Int!
offset: Int!
diff --git a/packages/ui/package.json b/packages/ui/package.json
index f3320b5ce..967e148ea 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -44,6 +44,7 @@
"@heroicons/react": "^2.1.1",
"@hookform/resolvers": "^3.3.3",
"clsx": "^2.1.0",
+ "flowbite-react": "^0.9.0",
"framer-motion": "^10.17.4",
"hast-util-is-element": "^2.1.3",
"hast-util-select": "^5.0.5",
diff --git a/packages/ui/src/components/Atoms/Container.css b/packages/ui/src/components/Atoms/Container.css
index 8985bc6dc..566f31114 100644
--- a/packages/ui/src/components/Atoms/Container.css
+++ b/packages/ui/src/components/Atoms/Container.css
@@ -1,5 +1,5 @@
.container-page {
- @apply max-w-full px-[1.25rem] md:px-[3.75rem];
+ @apply max-w-full px-[1.25rem] md:px-[3.75rem] lg:px-[5rem];
}
.container-content {
@@ -7,7 +7,7 @@
}
.container-text {
- @apply max-w-[40.75rem] xl:ml-[11rem] lg:ml-[7rem];
+ @apply max-w-3xl mx-auto;
}
.nested-container .container-page {
@@ -27,7 +27,7 @@
}
.nested-container .container-page:first-child .container-text,
-.nested-container .container-page:first-child .container-text *:first-child{
+.nested-container .container-page:first-child .container-text *:first-child {
@apply mt-0;
}
.nested-container .container-page:last-child .container-text,
@@ -35,6 +35,7 @@
@apply mb-0;
}
-.container-nested .prose ul:not(ul ul), .container-nested .prose ol:not(ol ol) {
+.container-nested .prose ul:not(ul ul),
+.container-nested .prose ol:not(ol ol) {
@apply mt-0;
}
diff --git a/packages/ui/src/components/Atoms/List.css b/packages/ui/src/components/Atoms/List.css
new file mode 100644
index 000000000..f185321e6
--- /dev/null
+++ b/packages/ui/src/components/Atoms/List.css
@@ -0,0 +1,49 @@
+ul li {
+ @apply !text-base !font-medium !text-gray-900;
+}
+
+ul {
+ @apply !pl-4;
+}
+
+.list-style--arrows li,
+.list-style--checkmarks li,
+.list-style--question-marks li {
+ list-style-type: none;
+ position: relative;
+ padding-left: 0.625rem;
+ margin-left: 0;
+ line-height: 1.25rem !important;
+}
+
+ul li::marker {
+ @apply !text-gray-500;
+}
+
+.list-style--arrows li::before {
+ position: absolute;
+ left: -1.25rem;
+ line-height: 1.25rem;
+ height: 1.25rem;
+ vertical-align: middle;
+ content: url("data:image/svg+xml,%3Csvg aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='%236B7280' %3E%3Cpath fill-rule='evenodd' d='M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM6.75 9.25a.75.75 0 0 0 0 1.5h4.59l-2.1 1.95a.75.75 0 0 0 1.02 1.1l3.5-3.25a.75.75 0 0 0 0-1.1l-3.5-3.25a.75.75 0 1 0-1.02 1.1l2.1 1.95H6.75Z' clip-rule='evenodd'%3E%3C/path%3E%3C/svg%3E");
+}
+
+.list-style--checkmarks li::before {
+ position: absolute;
+ left: -1.125rem;
+ line-height: 1.25rem;
+ height: 1.25rem;
+ vertical-align: middle;
+ margin-top: 0.5px;
+ content: url("data:image/svg+xml,%3Csvg width='18' height='19' viewBox='0 0 18 19' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect y='0.5' width='18' height='18' rx='9' fill='%23DEF7EC'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.6947 6.20519C13.8259 6.33646 13.8996 6.51448 13.8996 6.70009C13.8996 6.88571 13.8259 7.06372 13.6947 7.19499L8.0947 12.795C7.96343 12.9262 7.78541 12.9999 7.5998 12.9999C7.41418 12.9999 7.23617 12.9262 7.1049 12.795L4.3049 9.99499C4.17739 9.86297 4.10683 9.68615 4.10842 9.50261C4.11002 9.31908 4.18364 9.14351 4.31342 9.01372C4.44321 8.88394 4.61878 8.81032 4.80232 8.80872C4.98585 8.80713 5.16268 8.87768 5.2947 9.00519L7.5998 11.3103L12.7049 6.20519C12.8362 6.07397 13.0142 6.00024 13.1998 6.00024C13.3854 6.00024 13.5634 6.07397 13.6947 6.20519Z' fill='%230E9F6E'/%3E%3C/svg%3E ");
+}
+
+.list-style--question-marks li::before {
+ position: absolute;
+ left: -1.125rem;
+ vertical-align: middle;
+ line-height: 1.25rem;
+ height: 1.25rem;
+ content: url("data:image/svg+xml,%3Csvg aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='20' height='20' fill='%236B7280' viewBox='0 0 20 24'%3E%3Cpath fill-rule='evenodd' d='M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm9.008-3.018a1.502 1.502 0 0 1 2.522 1.159v.024a1.44 1.44 0 0 1-1.493 1.418 1 1 0 0 0-1.037.999V14a1 1 0 1 0 2 0v-.539a3.44 3.44 0 0 0 2.529-3.256 3.502 3.502 0 0 0-7-.255 1 1 0 0 0 2 .076c.014-.398.187-.774.48-1.044Zm.982 7.026a1 1 0 1 0 0 2H12a1 1 0 1 0 0-2h-.01Z' clip-rule='evenodd'/%3E%3C/svg%3E%0A");
+}
diff --git a/packages/ui/src/components/Molecules/Breadcrumbs.stories.tsx b/packages/ui/src/components/Molecules/Breadcrumbs.stories.tsx
new file mode 100644
index 000000000..9a7c6d0e5
--- /dev/null
+++ b/packages/ui/src/components/Molecules/Breadcrumbs.stories.tsx
@@ -0,0 +1,24 @@
+import { FrameQuery, OperationExecutor } from '@custom/schema';
+import { Meta } from '@storybook/react';
+import React from 'react';
+
+import { Default as FrameStory } from '../Routes/Frame.stories';
+import { BreadCrumbs } from './Breadcrumbs';
+
+export default {
+ component: BreadCrumbs,
+ parameters: {
+ layout: 'fullscreen',
+ location: new URL('local:/gatsby-turbo'),
+ },
+} satisfies Meta;
+
+export const Default = {
+ render: () => {
+ return (
+
+
+
+ );
+ },
+};
diff --git a/packages/ui/src/components/Molecules/Breadcrumbs.tsx b/packages/ui/src/components/Molecules/Breadcrumbs.tsx
new file mode 100644
index 000000000..431291137
--- /dev/null
+++ b/packages/ui/src/components/Molecules/Breadcrumbs.tsx
@@ -0,0 +1,56 @@
+import { Link } from '@custom/schema';
+import { ChevronRightIcon } from '@heroicons/react/24/outline';
+import clsx from 'clsx';
+import React from 'react';
+
+import { isTruthy } from '../../utils/isTruthy';
+import { useBreadcrumbs } from '../Routes/Menu';
+
+export function BreadCrumbs() {
+ const breadcrumbs = useBreadcrumbs();
+
+ if (!breadcrumbs.length) {
+ return null;
+ }
+
+ return (
+