diff --git a/accordion/.gitignore b/accordion/.gitignore
new file mode 100644
index 0000000..f42e1b1
--- /dev/null
+++ b/accordion/.gitignore
@@ -0,0 +1,35 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Output of `npm pack`
+*.tgz
+
+# Output of `wp-scripts plugin-zip`
+*.zip
+
+# dotenv environment variables file
+.env
+
+# Build files
+build/
+
+package-lock.json
\ No newline at end of file
diff --git a/accordion/accordion.php b/accordion/accordion.php
new file mode 100644
index 0000000..03164e2
--- /dev/null
+++ b/accordion/accordion.php
@@ -0,0 +1,33 @@
+
+
+
+ );
+}
diff --git a/accordion/src/accordion-content/index.js b/accordion/src/accordion-content/index.js
new file mode 100644
index 0000000..d37ee59
--- /dev/null
+++ b/accordion/src/accordion-content/index.js
@@ -0,0 +1,28 @@
+import { registerBlockType } from '@wordpress/blocks';
+import { SVG, Path } from '@wordpress/components';
+import Edit from './edit';
+import save from './save';
+import metadata from './block.json';
+
+const icon = (
+
+);
+
+registerBlockType( metadata.name, {
+ icon,
+ edit: Edit,
+ save,
+} );
diff --git a/accordion/src/accordion-content/save.js b/accordion/src/accordion-content/save.js
new file mode 100644
index 0000000..2698c87
--- /dev/null
+++ b/accordion/src/accordion-content/save.js
@@ -0,0 +1,46 @@
+import { __ } from '@wordpress/i18n';
+import {
+ InnerBlocks,
+ useBlockProps,
+ __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
+ __experimentalGetColorClassesAndStyles as getColorClassesAndStyles,
+ __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
+ __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
+} from '@wordpress/block-editor';
+import clsx from 'clsx';
+
+export default function save( { attributes } ) {
+ const blockProps = useBlockProps.save();
+ const borderProps = getBorderClassesAndStyles( attributes );
+ const colorProps = getColorClassesAndStyles( attributes );
+ const spacingProps = getSpacingClassesAndStyles( attributes );
+ const shadowProps = getShadowClassesAndStyles( attributes );
+
+ return (
+
+ );
+}
diff --git a/accordion/src/accordion-group/block.json b/accordion/src/accordion-group/block.json
new file mode 100644
index 0000000..0d035b4
--- /dev/null
+++ b/accordion/src/accordion-group/block.json
@@ -0,0 +1,52 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "wpcomsp/accordion-group",
+ "version": "0.1.0",
+ "title": "Accordion Group",
+ "category": "design",
+ "description": "A group of headers and associated expandable content.",
+ "example": {},
+ "supports": {
+ "html": false,
+ "align": [ "wide", "full" ],
+ "background": {
+ "backgroundImage": true,
+ "backgroundSize": true,
+ "__experimentalDefaultControls": {
+ "backgroundImage": true
+ }
+ },
+ "color": {
+ "background": true,
+ "gradient": true
+ },
+ "spacing": {
+ "padding": true,
+ "margin": [ "top", "bottom" ],
+ "blockGap": true
+ },
+ "shadow": true,
+ "layout": true,
+ "interactivity": true
+ },
+ "attributes": {
+ "iconPosition": {
+ "type": "string",
+ "default": "right"
+ },
+ "autoclose": {
+ "type": "boolean",
+ "default": false
+ },
+ "allowedBlocks": {
+ "type": "array"
+ }
+ },
+ "allowedBlocks": [ "wpcomsp/accordion-item" ],
+ "textdomain": "accordion",
+ "editorScript": "file:./index.js",
+ "viewScriptModule": "file:./view.js",
+ "render": "file:./render.php",
+ "style": "file:./style-index.css"
+}
diff --git a/accordion/src/accordion-group/edit.js b/accordion/src/accordion-group/edit.js
new file mode 100644
index 0000000..2802d5b
--- /dev/null
+++ b/accordion/src/accordion-group/edit.js
@@ -0,0 +1,42 @@
+import {
+ useBlockProps,
+ useInnerBlocksProps,
+ InspectorControls,
+} from '@wordpress/block-editor';
+import { __ } from '@wordpress/i18n';
+import { PanelBody, ToggleControl } from '@wordpress/components';
+
+const ACCORDION_BLOCK_NAME = 'wpcomsp/accordion-item';
+const ACCORDION_BLOCK = {
+ name: ACCORDION_BLOCK_NAME,
+};
+
+export default function Edit( { attributes: { autoclose }, setAttributes } ) {
+ const blockProps = useBlockProps();
+
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
+ template: [ [ ACCORDION_BLOCK_NAME ], [ ACCORDION_BLOCK_NAME ] ],
+ defaultBlock: ACCORDION_BLOCK,
+ directInsert: true,
+ } );
+
+ return (
+ <>
+
+
+ {
+ setAttributes( {
+ autoclose: value,
+ } );
+ } }
+ checked={ autoclose }
+ />
+
+
+
+ >
+ );
+}
diff --git a/accordion/src/accordion-group/index.js b/accordion/src/accordion-group/index.js
new file mode 100644
index 0000000..d954bf5
--- /dev/null
+++ b/accordion/src/accordion-group/index.js
@@ -0,0 +1,37 @@
+import { registerBlockType } from '@wordpress/blocks';
+import { SVG, Path } from '@wordpress/components';
+import Edit from './edit';
+import save from './save';
+import metadata from './block.json';
+import './style.scss';
+
+const icon = (
+
+);
+
+registerBlockType( metadata.name, {
+ icon,
+ edit: Edit,
+ save,
+} );
diff --git a/accordion/src/accordion-group/render.php b/accordion/src/accordion-group/render.php
new file mode 100644
index 0000000..c5668f1
--- /dev/null
+++ b/accordion/src/accordion-group/render.php
@@ -0,0 +1,12 @@
+next_tag() ){
+ if ( $p->has_class( 'wp-block-wpcomsp-accordion-group') ) {
+ $p->set_attribute( 'data-wp-interactive', 'wpcomsp/accordion' );
+ $p->set_attribute( 'data-wp-context', '{"isOpen":[],"autoclose":"' . $autoclose . '"}' );
+ }
+}
+
+echo $p->get_updated_html();
\ No newline at end of file
diff --git a/accordion/src/accordion-group/save.js b/accordion/src/accordion-group/save.js
new file mode 100644
index 0000000..b0d759b
--- /dev/null
+++ b/accordion/src/accordion-group/save.js
@@ -0,0 +1,16 @@
+import clsx from 'clsx';
+import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
+
+export default function save( { attributes } ) {
+ const { iconPosition } = attributes;
+
+ const className = clsx( {
+ 'icon-position-left': iconPosition === 'left',
+ } );
+
+ return (
+
+
+
+ );
+}
diff --git a/accordion/src/accordion-group/style.scss b/accordion/src/accordion-group/style.scss
new file mode 100644
index 0000000..2a5d3ac
--- /dev/null
+++ b/accordion/src/accordion-group/style.scss
@@ -0,0 +1,91 @@
+.wp-block-wpcomsp-accordion-item {
+ display: grid;
+ grid-template-rows: max-content 0fr;
+}
+
+.wp-block-wpcomsp-accordion-item.is-open {
+ grid-template-rows: max-content 1fr;
+}
+
+.wp-block-wpcomsp-accordion-item .wpcomsp-accordion-item__heading {
+ color: inherit;
+ padding: 0;
+ margin: 0;
+}
+
+.wpcomsp-accordion-item__toggle {
+ font-family: inherit;
+ font-size: inherit;
+ font-weight: inherit;
+ line-height: inherit;
+ letter-spacing: inherit;
+ text-transform: inherit;
+ text-decoration: inherit;
+ word-spacing: inherit;
+ background: none;
+ border: none;
+ color: inherit;
+ padding: 0;
+ cursor: pointer;
+ outline: none;
+ display: flex;
+ align-items: center;
+ text-align: inherit;
+ position: relative;
+ width: 100%;
+}
+
+.wpcomsp-accordion-item__toggle > span {
+ width: 100%;
+}
+
+.is-layout-flow > .wp-block-wpcomsp-accordion-content,
+.wp-block-wpcomsp-accordion-content {
+ overflow: hidden;
+ margin: 0;
+}
+
+
+/* No icon block style */
+.is-style-no-icon .wpcomsp-accordion-item__toggle-icon {
+ background-color: unset;
+}
+
+.wp-block-wpcomsp-accordion-trigger.icon-position-left .wpcomsp-accordion-item__toggle {
+ flex-direction: row-reverse;
+}
+
+.wpcomsp-accordion-item__toggle:focus,
+.wpcomsp-accordion-item__toggle:focus-visible {
+ outline: 2px solid -webkit-focus-ring-color;
+ outline-offset: 2px;
+}
+
+/* Add transitions only for users who do not prefer reduced motion */
+@media (prefers-reduced-motion: no-preference) {
+ .wp-block-wpcomsp-accordion-item .wpcomsp-accordion-item__toggle-icon {
+ transition: transform 0.2s ease-in-out;
+ }
+
+ .wp-block-wpcomsp-accordion-item {
+ transition: grid-template-rows 0.3s ease-out;
+ }
+}
+
+.is-open {
+ .wpcomsp-accordion-item__toggle-icon.has-icon-plus {
+ transform: rotate(45deg);
+ }
+ .wpcomsp-accordion-item__toggle-icon.has-icon-chevron {
+ transform: rotate(-180deg);
+ }
+ .wpcomsp-accordion-item__toggle-icon.has-icon-circlePlus {
+ transform: rotate(45deg);
+ }
+ .wpcomsp-accordion-item__toggle-icon.has-icon-caret {
+ transform: rotate(-180deg);
+ }
+ .wpcomsp-accordion-item__toggle-icon.has-icon-chevronRight {
+ transform: rotate(90deg);
+ }
+}
diff --git a/accordion/src/accordion-group/view.js b/accordion/src/accordion-group/view.js
new file mode 100644
index 0000000..e1e2f7c
--- /dev/null
+++ b/accordion/src/accordion-group/view.js
@@ -0,0 +1,44 @@
+import { store, getContext, getElement } from '@wordpress/interactivity';
+
+const { state, actions } = store( 'wpcomsp/accordion', {
+ state: {
+ get isOpen() {
+ const { attributes } = getElement();
+ const id =
+ attributes.id ||
+ attributes[ 'aria-controls' ] ||
+ attributes[ 'aria-labelledby' ];
+ const context = getContext();
+ return context.isOpen.includes( id );
+ },
+ },
+ actions: {
+ toggle: () => {
+ const { attributes } = getElement();
+ const id = attributes[ 'aria-controls' ];
+ const context = getContext();
+ if ( context.isOpen.includes( id ) ) {
+ if ( context.autoclose ) {
+ context.isOpen = [];
+ } else {
+ context.isOpen = context.isOpen.filter(
+ ( item ) => item !== id
+ );
+ }
+ } else {
+ if ( context.autoclose ) {
+ context.isOpen = [ id ];
+ } else {
+ context.isOpen = [ ...context.isOpen, id ];
+ }
+ }
+ },
+ },
+ callbacks: {
+ open: () => {
+ const context = getContext();
+ const { ref } = getElement();
+ context.isOpen.push( ref.id );
+ },
+ },
+} );
diff --git a/accordion/src/accordion-item/block.json b/accordion/src/accordion-item/block.json
new file mode 100644
index 0000000..d9ace5c
--- /dev/null
+++ b/accordion/src/accordion-item/block.json
@@ -0,0 +1,51 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "wpcomsp/accordion-item",
+ "version": "0.1.0",
+ "title": "Accordion",
+ "category": "design",
+ "description": "A single accordion that displays a header and expandable content.",
+ "example": {},
+ "parent": [ "wpcomsp/accordion-group" ],
+ "allowedBlocks": [
+ "wpcomsp/accordion-trigger",
+ "wpcomsp/accordion-content"
+ ],
+ "supports": {
+ "align": [ "wide", "full" ],
+ "color": {
+ "background": true,
+ "gradient": true
+ },
+ "border": true,
+ "interactivity": true,
+ "spacing": {
+ "margin": [ "top", "bottom" ],
+ "blockGap": true
+ },
+ "__experimentalBorder": {
+ "color": true,
+ "radius": true,
+ "style": true,
+ "width": true,
+ "__experimentalDefaultControls": {
+ "color": true,
+ "radius": true,
+ "style": true,
+ "width": true
+ }
+ },
+ "shadow": true,
+ "layout": true
+ },
+ "attributes": {
+ "openByDefault": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ "textdomain": "accordion",
+ "editorScript": "file:./index.js",
+ "render": "file:./render.php"
+}
diff --git a/accordion/src/accordion-item/edit.js b/accordion/src/accordion-item/edit.js
new file mode 100644
index 0000000..1c2d8af
--- /dev/null
+++ b/accordion/src/accordion-item/edit.js
@@ -0,0 +1,96 @@
+import { __ } from '@wordpress/i18n';
+import {
+ useBlockProps,
+ useInnerBlocksProps,
+ InspectorControls,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+import { useDispatch, useSelect } from '@wordpress/data';
+import { useEffect } from '@wordpress/element';
+import { PanelBody, ToggleControl } from '@wordpress/components';
+import clsx from 'clsx';
+
+export default function Edit( {
+ attributes: { openByDefault },
+ clientId,
+ setAttributes,
+} ) {
+ const [ isSelected, getBlockOrder ] = useSelect(
+ ( select ) => {
+ const { isBlockSelected, hasSelectedInnerBlock, getBlockOrder } =
+ select( blockEditorStore );
+ return [
+ isBlockSelected( clientId ) ||
+ hasSelectedInnerBlock( clientId, true ),
+ getBlockOrder,
+ ];
+ },
+ [ clientId ]
+ );
+
+ const contentBlockClientId = getBlockOrder( clientId )[ 1 ];
+ const { updateBlockAttributes, __unstableMarkNextChangeAsNotPersistent } =
+ useDispatch( blockEditorStore );
+
+ useEffect( () => {
+ if ( contentBlockClientId ) {
+ __unstableMarkNextChangeAsNotPersistent();
+ updateBlockAttributes( contentBlockClientId, {
+ isSelected: isSelected,
+ } );
+ }
+ }, [
+ isSelected,
+ contentBlockClientId,
+ __unstableMarkNextChangeAsNotPersistent,
+ updateBlockAttributes,
+ ] );
+
+ const blockProps = useBlockProps();
+ const innerBlocksProps = useInnerBlocksProps(
+ {
+ ...blockProps,
+ className: clsx( blockProps.className, {
+ 'is-open': openByDefault || isSelected,
+ } ),
+ },
+ {
+ template: [
+ [ 'wpcomsp/accordion-trigger', {} ],
+ [
+ 'wpcomsp/accordion-content',
+ {
+ isSelected: true,
+ openByDefault,
+ },
+ ],
+ ],
+ templateLock: 'all',
+ directInsert: true,
+ }
+ );
+
+ return (
+ <>
+
+
+ {
+ setAttributes( {
+ openByDefault: value,
+ } );
+ if ( contentBlockClientId ) {
+ updateBlockAttributes( contentBlockClientId, {
+ openByDefault: value,
+ } );
+ }
+ } }
+ checked={ openByDefault }
+ />
+
+
+
+ >
+ );
+}
diff --git a/accordion/src/accordion-item/icons.js b/accordion/src/accordion-item/icons.js
new file mode 100644
index 0000000..43017f6
--- /dev/null
+++ b/accordion/src/accordion-item/icons.js
@@ -0,0 +1,118 @@
+import { SVG, Path } from '@wordpress/components';
+
+export const chevron = ( { width, height } ) => {
+ return (
+
+ );
+};
+
+export const plus = ( { width, height } ) => {
+ return (
+
+ );
+};
+
+export const circlePlus = ( { width, height } ) => {
+ return (
+
+ );
+};
+
+export const circleMinus = ( { width, height } ) => {
+ return (
+
+ );
+};
+
+export const caret = ( { width, height } ) => {
+ return (
+
+ );
+};
+
+export const chevronRight = ( { width, height } ) => {
+ return (
+
+ );
+};
diff --git a/accordion/src/accordion-item/index.js b/accordion/src/accordion-item/index.js
new file mode 100644
index 0000000..7572151
--- /dev/null
+++ b/accordion/src/accordion-item/index.js
@@ -0,0 +1,41 @@
+import { registerBlockType } from '@wordpress/blocks';
+import { SVG, Path } from '@wordpress/components';
+import Edit from './edit';
+import save from './save';
+import metadata from './block.json';
+
+const icon = (
+
+);
+
+registerBlockType( metadata.name, {
+ icon,
+ edit: Edit,
+ save,
+} );
diff --git a/accordion/src/accordion-item/render.php b/accordion/src/accordion-item/render.php
new file mode 100644
index 0000000..3c1ac38
--- /dev/null
+++ b/accordion/src/accordion-item/render.php
@@ -0,0 +1,36 @@
+next_tag() ){
+ if ( $p->has_class( 'wp-block-wpcomsp-accordion-item') ) {
+ $p->set_attribute( 'id', $unique_id );
+ $p->set_attribute( 'data-wp-class--is-open', 'state.isOpen' );
+ if ( $attributes['openByDefault'] ) {
+ $p->set_attribute( 'data-wp-init', 'callbacks.open' );
+ }
+ }
+}
+
+$content = $p->get_updated_html();
+$p = new WP_HTML_Tag_Processor( $content );
+
+while ( $p->next_tag() ){
+ if ( $p->has_class( 'wpcomsp-accordion-item__toggle' ) ) {
+ $p->set_attribute( 'data-wp-on--click', 'actions.toggle' );
+ $p->set_attribute( 'aria-controls', $unique_id );
+ $p->set_attribute( 'data-wp-bind--aria-expanded', 'state.isOpen' );
+ }
+}
+
+$content = $p->get_updated_html();
+$p = new WP_HTML_Tag_Processor( $content );
+
+while ( $p->next_tag() ){
+ if ( $p->has_class( 'wp-block-wpcomsp-accordion-content' ) ) {
+ $p->set_attribute( 'aria-labelledby', $unique_id );
+ $p->set_attribute( 'data-wp-bind--aria-hidden', '!state.isOpen' );
+ }
+}
+
+echo $p->get_updated_html();
\ No newline at end of file
diff --git a/accordion/src/accordion-item/save.js b/accordion/src/accordion-item/save.js
new file mode 100644
index 0000000..4cd8884
--- /dev/null
+++ b/accordion/src/accordion-item/save.js
@@ -0,0 +1,11 @@
+import clsx from 'clsx';
+import { __ } from '@wordpress/i18n';
+import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
+
+export default function save( { attributes } ) {
+ return (
+
+
+
+ );
+}
diff --git a/accordion/src/accordion-trigger/block.json b/accordion/src/accordion-trigger/block.json
new file mode 100644
index 0000000..25743b4
--- /dev/null
+++ b/accordion/src/accordion-trigger/block.json
@@ -0,0 +1,95 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "wpcomsp/accordion-trigger",
+ "version": "0.1.0",
+ "title": "Trigger",
+ "category": "design",
+ "description": "Accordion item trigger.",
+ "example": {},
+ "parent": [ "wpcomsp/accordion-item" ],
+ "supports": {
+ "anchor": true,
+ "color": {
+ "background": true,
+ "gradient": true
+ },
+ "align": false,
+ "border": true,
+ "interactivity": true,
+ "spacing": {
+ "padding": true,
+ "margin": [ "top", "bottom" ],
+ "__experimentalDefaultControls": {
+ "padding": true,
+ "margin": true
+ }
+ },
+ "__experimentalBorder": {
+ "color": true,
+ "radius": true,
+ "style": true,
+ "width": true,
+ "__experimentalDefaultControls": {
+ "color": true,
+ "radius": true,
+ "style": true,
+ "width": true
+ }
+ },
+ "typography": {
+ "textAlign": true,
+ "fontSize": true,
+ "__experimentalFontFamily": true,
+ "__experimentalFontWeight": true,
+ "__experimentalFontStyle": true,
+ "__experimentalTextTransform": true,
+ "__experimentalTextDecoration": true,
+ "__experimentalLetterSpacing": true,
+ "__experimentalDefaultControls": {
+ "fontSize": true,
+ "fontFamily": true
+ }
+ },
+ "shadow": true,
+ "layout": true
+ },
+ "attributes": {
+ "openByDefault": {
+ "type": "boolean",
+ "default": false
+ },
+ "title": {
+ "type": "rich-text",
+ "source": "rich-text",
+ "selector": "span"
+ },
+ "level": {
+ "type": "number",
+ "default": 3
+ },
+ "textAlignment": {
+ "type": "string",
+ "default": "left"
+ },
+ "icon": {
+ "type": [ "string", "boolean" ],
+ "enum": [
+ "plus",
+ "chevron",
+ "chevronRight",
+ "caret",
+ "circlePlus",
+ false
+ ],
+ "default": "plus"
+ },
+ "iconPosition": {
+ "type": "string",
+ "enum": [ "left", "right" ],
+ "default": "right"
+ }
+ },
+ "textdomain": "accordion",
+ "editorScript": "file:./index.js"
+}
diff --git a/accordion/src/accordion-trigger/edit.js b/accordion/src/accordion-trigger/edit.js
new file mode 100644
index 0000000..1f8638f
--- /dev/null
+++ b/accordion/src/accordion-trigger/edit.js
@@ -0,0 +1,171 @@
+import clsx from 'clsx';
+import { __ } from '@wordpress/i18n';
+import {
+ useBlockProps,
+ __experimentalUseBorderProps as useBorderProps,
+ __experimentalUseColorProps as useColorProps,
+ __experimentalGetSpacingClassesAndStyles as useSpacingProps,
+ __experimentalGetShadowClassesAndStyles as useShadowProps,
+ BlockControls,
+ HeadingLevelDropdown,
+ RichText,
+ InspectorControls,
+} from '@wordpress/block-editor';
+import {
+ PanelBody,
+ ToolbarGroup,
+ __experimentalToggleGroupControl as ToggleGroupControl,
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
+ __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon,
+} from '@wordpress/components';
+import {
+ caret,
+ chevron,
+ chevronRight,
+ circlePlus,
+ plus,
+} from '../accordion-item/icons';
+
+const ICONS = {
+ plus,
+ circlePlus,
+ chevron,
+ chevronRight,
+ caret,
+};
+
+export default function Edit( { attributes, setAttributes } ) {
+ const { level, title, textAlign, icon, iconPosition } = attributes;
+ const TagName = 'h' + level;
+
+ const blockProps = useBlockProps();
+ const borderProps = useBorderProps( attributes );
+ const colorProps = useColorProps( attributes );
+ const spacingProps = useSpacingProps( attributes );
+ const shadowProps = useShadowProps( attributes );
+
+ const Icon = ICONS[ icon ];
+
+ return (
+ <>
+
+
+
+ setAttributes( { level: newLevel } )
+ }
+ />
+
+
+
+
+
+ setAttributes( { icon: value } )
+ }
+ >
+
+
+
+
+
+
+
+ {
+ setAttributes( { iconPosition: value } );
+ } }
+ >
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/accordion/src/accordion-trigger/index.js b/accordion/src/accordion-trigger/index.js
new file mode 100644
index 0000000..b5d5f1c
--- /dev/null
+++ b/accordion/src/accordion-trigger/index.js
@@ -0,0 +1,29 @@
+import { registerBlockType } from '@wordpress/blocks';
+import { SVG, Path } from '@wordpress/components';
+import Edit from './edit';
+import save from './save';
+import metadata from './block.json';
+
+const icon = (
+
+);
+
+registerBlockType( metadata.name, {
+ icon,
+ edit: Edit,
+ save,
+} );
diff --git a/accordion/src/accordion-trigger/save.js b/accordion/src/accordion-trigger/save.js
new file mode 100644
index 0000000..14adcea
--- /dev/null
+++ b/accordion/src/accordion-trigger/save.js
@@ -0,0 +1,81 @@
+import clsx from 'clsx';
+import { __ } from '@wordpress/i18n';
+import {
+ useBlockProps,
+ __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
+ __experimentalGetColorClassesAndStyles as getColorClassesAndStyles,
+ __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
+ __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
+ RichText,
+} from '@wordpress/block-editor';
+import {
+ caret,
+ chevron,
+ chevronRight,
+ circlePlus,
+ plus,
+} from '../accordion-item/icons';
+
+const ICONS = {
+ plus,
+ circlePlus,
+ chevron,
+ chevronRight,
+ caret,
+};
+
+export default function save( { attributes } ) {
+ const { level, title, iconPosition, textAlign, icon } = attributes;
+ const TagName = 'h' + level;
+
+ const blockProps = useBlockProps.save();
+ const borderProps = getBorderClassesAndStyles( attributes );
+ const colorProps = getColorClassesAndStyles( attributes );
+ const spacingProps = getSpacingClassesAndStyles( attributes );
+ const shadowProps = getShadowClassesAndStyles( attributes );
+
+ const Icon = ICONS[ icon ];
+
+ return (
+
+
+
+ );
+}