Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(SLB-299): accordion block #214

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
74e61e9
feat(SLB-300): add accordion block
colorfield May 3, 2024
abec41f
feat(SLB-300): accordion validators
colorfield May 3, 2024
b6a65f4
feat(SLB-300): accordion schema
colorfield May 3, 2024
cca7934
chore(SLB-300): add placeholder for storybook integration
colorfield May 3, 2024
7d5cd06
feat(SLB-300): add accordion fragments
colorfield May 3, 2024
8b75635
fix(SLB-300): don't use union for now
colorfield May 3, 2024
f93cc5e
refactor(SLB-300): use InnerBlocks instead of RichText
colorfield May 3, 2024
6835bb6
test(SLB-300): accordion block
colorfield May 3, 2024
18d3aa5
feat(SLB-301): accordion storybook
colorfield May 3, 2024
4652071
refactor(SLB-301): use custom theme
colorfield May 3, 2024
0186299
refactor(SLB-301): styling
colorfield May 3, 2024
faf98ca
refactor(SLB-301): styling
colorfield May 3, 2024
c3da87c
refactor(SLB-301): styling
colorfield May 3, 2024
c0935d5
fix(SLB-301): adjust width
colorfield May 3, 2024
bc0ba2b
feat(SLB-299): adjust accordion style, add to page story
colorfield May 6, 2024
42f3036
fix(SLB-299): last border
colorfield May 7, 2024
431a7c8
fix(SLB-364): remove dark mode
colorfield May 13, 2024
73820e1
refactor(SLB-365): add arrows back
colorfield May 13, 2024
c748c49
test(SLB-299): use more content
colorfield May 13, 2024
e48d22b
refactor(SLB-369): collapseAll by default
colorfield May 13, 2024
adccb1f
feat(SLB-366): display title icons in the editor
colorfield May 13, 2024
714b1cd
fix(SLB-377): font weight
colorfield May 15, 2024
b4cefc6
Merge branch 'release' into SLB-299-accordion
colorfield May 15, 2024
bed4a54
fix(SLB-377): specifically set font weight
colorfield May 15, 2024
a79e42b
test(SLB-299): title using 2 lines
colorfield May 15, 2024
b17d168
fix: fix contained blocks
HagerDakroury May 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/drupal/gutenberg_blocks/css/edit.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,18 @@
transform-origin: 0 0;
transform: rotate(90deg);
}

.gutenberg__editor .custom-block-accordion-item-text.questionmark h3::before {
margin-right: 7px;
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");
}

.gutenberg__editor .custom-block-accordion-item-text.checkmark h3::before {
margin-right: 7px;
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 12Zm13.707-1.293a1 1 0 0 0-1.414-1.414L11 12.586l-1.793-1.793a1 1 0 0 0-1.414 1.414l2.5 2.5a1 1 0 0 0 1.414 0l4-4Z' clip-rule='evenodd'%3E%3C/path%3E%3C/svg%3E");
}

.gutenberg__editor .custom-block-accordion-item-text.arrow h3::before {
margin-right: 7px;
content: url("data:image/svg+xml,%3Csvg aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='20' height='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");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Drupal\gutenberg_blocks\Plugin\Validation\GutenbergValidator;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorInterface;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorTrait;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergValidatorBase;

/**
* @GutenbergValidator(
* id="accordion_item_text_validator",
* label = @Translation("Accordion Item Text validator")
* )
*/
class AccordionItemTextValidator extends GutenbergValidatorBase {
use GutenbergCardinalityValidatorTrait;
use StringTranslationTrait;

/**
* {@inheritDoc}
*/
public function applies(array $block): bool {
return $block['blockName'] === 'custom/accordion-item-text';
}

/**
* {@inheritDoc}
*/
public function validatedFields($block = []): array {
return [
'title' => [
'field_label' => $this->t('Title'),
'rules' => ['required'],
],
];
}

/**
* {@inheritDoc}
*/
public function validateContent($block = []): array {
$expectedChildren = [
'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY,
'min' => 1,
'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
];
return $this->validateCardinality($block, $expectedChildren);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Drupal\gutenberg_blocks\Plugin\Validation\GutenbergValidator;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorInterface;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergCardinalityValidatorTrait;
use Drupal\silverback_gutenberg\GutenbergValidation\GutenbergValidatorBase;

/**
* @GutenbergValidator(
* id="accordion_validator",
* label = @Translation("Accordion validator")
* )
*/
class AccordionValidator extends GutenbergValidatorBase {
use GutenbergCardinalityValidatorTrait;
use StringTranslationTrait;

/**
* {@inheritDoc}
*/
public function applies(array $block): bool {
return $block['blockName'] === 'custom/accordion';
}

/**
* {@inheritDoc}
*/
public function validateContent($block = []): array {
$expectedChildren = [
[
'blockName' => 'custom/accordion-item-text',
'blockLabel' => $this->t('Accordion'),
'min' => 1,
'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED,
],
];
return $this->validateCardinality($block, $expectedChildren);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import clsx from 'clsx';
import React, { Fragment } from 'react';
import {
InnerBlocks,
InspectorControls,
RichText,
} from 'wordpress__block-editor';
import { registerBlockType } from 'wordpress__blocks';
import { PanelBody, SelectControl } from 'wordpress__components';
import { compose, withState } from 'wordpress__compose';

// @ts-ignore
const { t: __ } = Drupal;
// @ts-ignore
registerBlockType('custom/accordion-item-text', {
title: 'Accordion Item Text',
icon: 'text',
category: 'layout',
parent: ['custom/accordion'],
attributes: {
title: {
type: 'string',
},
icon: {
type: 'string',
},
},
// @ts-ignore
edit: compose(withState())((props) => {
const { attributes, setAttributes } = props;
const icons = [
{ label: __('- Select an optional icon -'), value: '' },
{ label: __('Checkmark'), value: 'checkmark' },
{ label: __('Questionmark'), value: 'questionmark' },
{ label: __('Arrow'), value: 'arrow' },
];
setAttributes({
icon: attributes.icon === undefined ? '' : attributes.icon,
});

return (
<Fragment>
<InspectorControls>
<PanelBody title={__('Block settings')}>
<SelectControl
value={attributes.icon}
options={icons}
onChange={(newValue) => {
setAttributes({
icon: newValue,
});
}}
/>
</PanelBody>
</InspectorControls>
<div className={'container-wrapper'}>
<div className={'container-label'}>{__('Accordion Item Text')}</div>
<div
className={clsx(
'custom-block-accordion-item-text',
attributes.icon,
)}
>
<RichText
identifier="title"
tagName="h3"
value={attributes.title}
allowedFormats={[]}
// @ts-ignore
disableLineBreaks={true}
placeholder={__('Title')}
keepPlaceholderOnFocus={true}
onChange={(newValue) => {
setAttributes({ title: newValue });
}}
/>
<InnerBlocks
templateLock={false}
allowedBlocks={['core/paragraph', 'core/list', 'core/heading']}
template={[['core/paragraph', {}]]}
/>
</div>
</div>
</Fragment>
);
}),

save: () => {
return <InnerBlocks.Content />;
},
});
25 changes: 25 additions & 0 deletions packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { InnerBlocks } from 'wordpress__block-editor';
import { registerBlockType } from 'wordpress__blocks';

// @ts-ignore
const { t: __ } = Drupal;

registerBlockType('custom/accordion', {
title: __('Accordion'),
icon: 'menu',
category: 'layout',
attributes: {},
edit: () => {
return (
<div className={'container-wrapper'}>
<div className={'container-label'}>{__('Accordion')}</div>
<InnerBlocks
templateLock={false}
allowedBlocks={['custom/accordion-item-text']}
template={[['custom/accordion-item-text']]}
/>
</div>
);
},
save: () => <InnerBlocks.Content />,
});
2 changes: 2 additions & 0 deletions packages/drupal/gutenberg_blocks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ import './filters/list';
import './blocks/cta';
import './blocks/quote';
import './blocks/horizontal-separator';
import './blocks/accordion';
import './blocks/accordion-item-text';
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,23 @@ default:

<!-- wp:custom/quote {"quote":"Lorem ipsum dolor sit amet, \u003cstrong\u003econsectetur\u003c/strong\u003e adipiscing elit. Vivamus sagittis nisi nec neque porta, a ornare ligula efficitur.","author":"John Doe","role":"Project manager","mediaEntityIds":["5dfc1856-e9e4-4f02-9cd6-9d888870ce1a"]} /-->

<!-- wp:custom/accordion -->
<!-- wp:custom/accordion-item-text {"title":"With a single paragraph and no icon","icon":""} -->
<!-- wp:paragraph -->
<p></p>
<p>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.</p>
<!-- /wp:paragraph -->
<!-- /wp:custom/accordion-item-text -->

<!-- wp:custom/accordion-item-text {"title":"With a list and a paragraph and arrow icon","icon":"arrow"} -->
<!-- wp:list -->
<ul><li>Moitié-moitié</li><li>Fribourgeoise</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>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.</p>
<!-- /wp:paragraph -->
<!-- /wp:custom/accordion-item-text -->
<!-- /wp:custom/accordion -->
<!-- /wp:custom/content -->
format: gutenberg
summary: ''
Expand Down
1 change: 1 addition & 0 deletions packages/schema/src/fragments/Page.gql
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fragment Page on Page {
...BlockImageWithText
...BlockQuote
...BlockHorizontalSeparator
...BlockAccordion
}
metaTags {
tag
Expand Down
13 changes: 13 additions & 0 deletions packages/schema/src/fragments/PageContent/BlockAccordion.gql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fragment BlockAccordion on BlockAccordion {
items {
...BlockAccordionItemText
}
}

fragment BlockAccordionItemText on BlockAccordionItemText {
title
icon
textContent {
markup
}
}
11 changes: 11 additions & 0 deletions packages/schema/src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ union PageContent @resolveEditorBlockType =
| BlockImageWithText
| BlockQuote
| BlockHorizontalSeparator
| BlockAccordion

type BlockForm @type(id: "custom/form") {
url: Url @resolveEditorBlockAttribute(key: "formId") @webformIdToUrl(id: "$")
Expand Down Expand Up @@ -246,6 +247,16 @@ 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")
Expand Down
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Markup } from '@custom/schema';
import { Meta, StoryObj } from '@storybook/react';

import { BlockAccordion } from './BlockAccordion';

export default {
component: BlockAccordion,
} satisfies Meta<typeof BlockAccordion>;

export const AccordionItemText = {
args: {
items: [
{
title: 'Cheese Fondue',
icon: 'arrow',
textContent: {
markup: `
<p>The earliest known recipe for the modern form of cheese fondue comes from a 1699 book published in Zürich, under the name "Käss mit Wein zu kochen" 'to cook cheese with wine'.</p>
<p>It calls for grated or cut-up cheese to be melted with wine, and for bread to be dipped in it. However, the name "cheese fondue", until the late 19th century, referred to a dish composed of eggs and cheese, as in la Chapelle's 1735 Fonduë de Fromage, aux Truffes Fraiches; it was something between scrambled eggs with cheese and a cheese soufflé. Brillat-Savarin wrote in 1834 that it is "nothing other than scrambled eggs with cheese". Variations included cream ("à la genevoise") and truffles ("à la piémontaise") in addition to eggs, as well as what is now called "raclette" ("fondue valaisanne").</p>
<ul>
<li>Fribourgeoise</li>
<li>Moitié-Moitié</li>
</ul>
` as Markup,
},
},
{
title: 'Rösti',
icon: 'questionmark',
textContent: {
markup: `
<p>Rösti is a kind of fried potato cake served as a main course or side dish.</p>
<p>As a main dish, rösti is usually accompanied with cheese, onions and cold meat or eggs. This dish, originally from Zürich, was first simply made by frying grated raw potatoes in a pan. It has then spread towards Bern where it is made with boiled potatoes instead. This is where it took the name Rösti. There are many variants in Switzerland and outside the borders. This culinary specialty gives its name to the röstigraben, which designates the cultural differences between the German- and French-speaking parts of the country.</p>
` as Markup,
},
},
{
title: 'Älplermagronen',
icon: 'checkmark',
textContent: {
markup: `
<p>Älplermagronen are now regarded as a traditional dish of the Swiss Alps and a classic of Swiss comfort foods. According to a popular theory, pasta became widespread in northern Switzerland in the late 19th century, when the Gotthard Tunnel was built, partly by Italian workers who brought dry pasta with them.</p>
` as Markup,
},
},
{
title:
'Meringue with double cream, a dessert made of whipped egg whites, traditionally accompanied by double Gruyère cream',
icon: '',
textContent: {
markup: `
<p>The Oxford English Dictionary states that the French word is of unknown origin. The name meringue for this confection first appeared in print in François Massialot's cookbook of 1692.</p>
` as Markup,
},
},
],
},
} satisfies StoryObj<typeof BlockAccordion>;
Loading
Loading