FEATURE introducing the tab and tab-group component
This commit is contained in:
parent
b387694f07
commit
67ccfdee1f
25
plugins/carhop-blocks/src/tab-group/block.json
Normal file
25
plugins/carhop-blocks/src/tab-group/block.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "carhop-blocks/tab-group",
|
||||
"version": "0.1.0",
|
||||
"title": "Tab Group",
|
||||
"category": "carhop-blocks",
|
||||
"icon": "smiley",
|
||||
"description": "Tab Group pour la mise en forme supérieure d'éléments de contenu",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"html": false,
|
||||
"color": {
|
||||
"text": true,
|
||||
"background": false,
|
||||
"link": false
|
||||
}
|
||||
},
|
||||
"textdomain": "tab-group",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js",
|
||||
"render": "file:./render.php"
|
||||
}
|
||||
54
plugins/carhop-blocks/src/tab-group/edit.js
Normal file
54
plugins/carhop-blocks/src/tab-group/edit.js
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { __ } from "@wordpress/i18n";
|
||||
import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
|
||||
import { useSelect } from "@wordpress/data";
|
||||
import "./editor.scss";
|
||||
|
||||
export default function Edit({ attributes, setAttributes, clientId }) {
|
||||
const blockProps = useBlockProps({
|
||||
className: "tab-group",
|
||||
});
|
||||
|
||||
const tabs = useSelect(
|
||||
(select) => {
|
||||
const block = select("core/block-editor").getBlock(clientId);
|
||||
if (!block?.innerBlocks) return [];
|
||||
return block.innerBlocks.map((innerBlock, index) => ({
|
||||
id: `tab-${index + 1}`,
|
||||
panelId: `tabpanel-${index + 1}`,
|
||||
title: innerBlock.attributes?.title || __("Sans titre", "tab-group"),
|
||||
iconUrl: innerBlock.attributes?.iconUrl || "",
|
||||
}));
|
||||
},
|
||||
[clientId],
|
||||
);
|
||||
|
||||
return (
|
||||
<section {...blockProps}>
|
||||
<div className="tab-group__toolbar">
|
||||
<div role="tablist" aria-labelledby="tablist-1" className="tablist">
|
||||
{tabs.map((tab, index) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
id={tab.id}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={index === 0}
|
||||
aria-controls={tab.panelId}
|
||||
tabIndex={index === 0 ? 0 : -1}
|
||||
data-tab={index}
|
||||
>
|
||||
{tab.iconUrl && (
|
||||
<img src={tab.iconUrl} alt="" className="tab__icon" aria-hidden />
|
||||
)}
|
||||
<span>{tab.title}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<InnerBlocks
|
||||
allowedBlocks={["carhop-blocks/tab"]}
|
||||
template={[["carhop-blocks/tab"]]}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
9
plugins/carhop-blocks/src/tab-group/editor.scss
Normal file
9
plugins/carhop-blocks/src/tab-group/editor.scss
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* The following styles get applied inside the editor only.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.wp-block-create-block-chapo {
|
||||
border: 1px dotted #f00;
|
||||
}
|
||||
26
plugins/carhop-blocks/src/tab-group/index.js
Normal file
26
plugins/carhop-blocks/src/tab-group/index.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { registerBlockType } from "@wordpress/blocks";
|
||||
import "./style.scss";
|
||||
|
||||
import Edit from "./edit";
|
||||
import save from "./save";
|
||||
import metadata from "./block.json";
|
||||
|
||||
registerBlockType(metadata.name, {
|
||||
icon: {
|
||||
src: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
>
|
||||
<path
|
||||
d="M46,10H8c-2.1,0-4.2.8-5.7,2.3s-2.3,3.5-2.3,5.7v38c0,2.1.8,4.2,2.3,5.7s3.5,2.3,5.7,2.3h38c2.1,0,4.2-.8,5.7-2.3s2.3-3.5,2.3-5.7V18c0-2.1-.8-4.2-2.3-5.7s-3.5-2.3-5.7-2.3ZM25.8,18.3c.5-.5,1.3-.8,2-.8h0c1.1,0,2.2.7,2.6,1.8.4,1.1.2,2.3-.6,3.1s-2,1.1-3.1.6c-1.1-.4-1.7-1.5-1.8-2.6,0-.8.3-1.5.8-2ZM19.5,17.5c1.1,0,2.2.7,2.6,1.8.4,1.1.2,2.3-.6,3.1s-2,1.1-3.1.6c-1.1-.4-1.7-1.5-1.8-2.6,0-1.6,1.3-2.8,2.8-2.8ZM11.2,17.5c1.6,0,2.8,1.3,2.8,2.8s-1.3,2.8-2.8,2.8-2.8-1.3-2.8-2.8,1.3-2.8,2.8-2.8ZM50,56c0,2.2-1.8,4-4,4H8c-2.2,0-4-1.8-4-4v-25.3h46v25.3ZM61.7,2.3C60.2.8,58.1,0,56,0H18C15.9,0,13.8.8,12.3,2.3s-2.3,3.5-2.3,5.7h36c5.5,0,10,4.5,10,10v36c2.1,0,4.2-.8,5.7-2.3s2.3-3.5,2.3-5.7V8c0-2.1-.8-4.2-2.3-5.7Z"
|
||||
fill="#146E63"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
edit: Edit,
|
||||
save,
|
||||
});
|
||||
48
plugins/carhop-blocks/src/tab-group/render.php
Normal file
48
plugins/carhop-blocks/src/tab-group/render.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
$wrapper_attributes = get_block_wrapper_attributes(['class' => 'tab-group']);
|
||||
$inner_blocks = $block->parsed_block['innerBlocks'] ?? [];
|
||||
|
||||
// Extraire les titres et icônes des blocs tab pour les boutons
|
||||
$tabs = array_map(function ($inner_block) {
|
||||
return [
|
||||
'title' => $inner_block['attrs']['title'] ?? __('Sans titre', 'tab-group'),
|
||||
'iconUrl' => $inner_block['attrs']['iconUrl'] ?? '',
|
||||
];
|
||||
}, array_filter($inner_blocks, fn($b) => ($b['blockName'] ?? '') === 'carhop-blocks/tab'));
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<section <?php echo $wrapper_attributes; ?>>
|
||||
<div class="tab-group__toolbar">
|
||||
<div role="tablist" aria-label="<?php esc_attr_e('Onglets', 'tab-group'); ?>" class="tablist">
|
||||
<?php foreach ($tabs as $index => $tab) : ?>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected="<?php echo $index === 0 ? 'true' : 'false'; ?>"
|
||||
aria-controls="tabpanel-<?php echo esc_attr($index + 1); ?>"
|
||||
tabindex="<?php echo $index === 0 ? '0' : '-1'; ?>"
|
||||
data-tab="<?php echo esc_attr($index); ?>">
|
||||
<?php if (!empty($tab['iconUrl'])) : ?>
|
||||
<img src="<?php echo esc_url($tab['iconUrl']); ?>" alt="" class="tab__icon" aria-hidden />
|
||||
<?php endif; ?>
|
||||
<span><?php echo esc_html($tab['title']); ?></span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-group__innerblocks">
|
||||
<?php foreach ($inner_blocks as $index => $inner_block) : ?>
|
||||
<div class="wp-block-carhop-blocks-tab tab" id="tabpanel-<?php echo esc_attr($index + 1); ?>" role="tabpanel" data-active="<?php echo $index === 0 ? 'true' : 'false'; ?>">
|
||||
<?php echo render_block($inner_block); ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</section>
|
||||
6
plugins/carhop-blocks/src/tab-group/save.js
Normal file
6
plugins/carhop-blocks/src/tab-group/save.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import { useBlockProps } from "@wordpress/block-editor";
|
||||
import { InnerBlocks } from "@wordpress/block-editor";
|
||||
|
||||
export default function save() {
|
||||
return <InnerBlocks.Content />;
|
||||
}
|
||||
36
plugins/carhop-blocks/src/tab-group/style.scss
Normal file
36
plugins/carhop-blocks/src/tab-group/style.scss
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
.tab__title {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.tablist {
|
||||
button {
|
||||
gap: 10px !important;
|
||||
}
|
||||
button[aria-selected="false"] {
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-group__toolbar {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.tablist .tab__icon {
|
||||
--iconSize: 1.5rem;
|
||||
|
||||
width: var(--iconSize);
|
||||
height: var(--iconSize);
|
||||
// background: blue;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.wp-block-carhop-blocks-tab[data-active="false"] {
|
||||
display: none;
|
||||
}
|
||||
.wp-block-carhop-blocks-tab[data-active="true"] {
|
||||
display: block !important;
|
||||
}
|
||||
34
plugins/carhop-blocks/src/tab-group/view.js
Normal file
34
plugins/carhop-blocks/src/tab-group/view.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.querySelectorAll(".tab-group").forEach((TabGroup) => {
|
||||
const toolbar = TabGroup.querySelector(".tab-group__toolbar");
|
||||
const tabs = toolbar.querySelectorAll("button");
|
||||
|
||||
function setActiveTab(currentTab) {
|
||||
tabs.forEach((tab) => {
|
||||
tab.setAttribute("aria-selected", "false");
|
||||
});
|
||||
currentTab.setAttribute("aria-selected", "true");
|
||||
}
|
||||
function setActiveTabPanel(currentTabButton) {
|
||||
const currentTabPanelId = currentTabButton.getAttribute("aria-controls");
|
||||
const currentTabPanel = TabGroup.querySelector(`#${currentTabPanelId}`);
|
||||
console.log(currentTabPanel);
|
||||
hideAllTabPanels();
|
||||
currentTabPanel.setAttribute("data-active", "true");
|
||||
}
|
||||
function hideAllTabPanels() {
|
||||
const tabPanels = TabGroup.querySelectorAll(
|
||||
".tab-group__innerblocks .tab",
|
||||
);
|
||||
tabPanels.forEach((tabPanel) => {
|
||||
tabPanel.setAttribute("data-active", "false");
|
||||
});
|
||||
}
|
||||
tabs.forEach((tab) => {
|
||||
tab.addEventListener("click", () => {
|
||||
setActiveTab(tab);
|
||||
setActiveTabPanel(tab);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
30
plugins/carhop-blocks/src/tab/block.json
Normal file
30
plugins/carhop-blocks/src/tab/block.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "carhop-blocks/tab",
|
||||
"version": "0.1.0",
|
||||
"title": "Tab",
|
||||
"category": "carhop-blocks",
|
||||
"icon": "smiley",
|
||||
"description": "Tab pour la mise en forme supérieure d'éléments de contenu",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"html": false,
|
||||
"color": {
|
||||
"text": true,
|
||||
"background": false,
|
||||
"link": false
|
||||
}
|
||||
},
|
||||
"textdomain": "tab",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js",
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
109
plugins/carhop-blocks/src/tab/edit.js
Normal file
109
plugins/carhop-blocks/src/tab/edit.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { __ } from "@wordpress/i18n";
|
||||
import {
|
||||
useBlockProps,
|
||||
RichText,
|
||||
InnerBlocks,
|
||||
InspectorControls,
|
||||
MediaUpload,
|
||||
MediaUploadCheck,
|
||||
} from "@wordpress/block-editor";
|
||||
import "./editor.scss";
|
||||
import { PanelBody, TextControl, Button } from "@wordpress/components";
|
||||
|
||||
export default function Edit({ attributes, setAttributes }) {
|
||||
const { title, iconId, iconUrl } = attributes;
|
||||
|
||||
const blockProps = useBlockProps({
|
||||
className: "block-chapo",
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={__("Tab", "carhop-blocks")}>
|
||||
<TextControl
|
||||
label={__("Titre", "carhop-blocks")}
|
||||
value={title}
|
||||
onChange={(value) => setAttributes({ title: value })}
|
||||
/>
|
||||
</PanelBody>
|
||||
<PanelBody title={__("Icône", "carhop-blocks")}>
|
||||
<MediaUploadCheck>
|
||||
<MediaUpload
|
||||
onSelect={(media) =>
|
||||
setAttributes({
|
||||
iconId: media.id,
|
||||
iconUrl: media.url,
|
||||
})
|
||||
}
|
||||
allowedTypes={["image"]}
|
||||
value={iconId}
|
||||
render={({ open }) => (
|
||||
<>
|
||||
{iconUrl ? (
|
||||
<div className="tab__icon-preview">
|
||||
<img src={iconUrl} alt="" style={{ maxWidth: 48, height: "auto" }} />
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Button variant="secondary" onClick={open} style={{ marginRight: 8 }}>
|
||||
{__("Remplacer", "carhop-blocks")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="tertiary"
|
||||
isDestructive
|
||||
onClick={() =>
|
||||
setAttributes({ iconId: 0, iconUrl: "" })
|
||||
}
|
||||
>
|
||||
{__("Supprimer", "carhop-blocks")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<Button variant="secondary" onClick={open}>
|
||||
{__("Choisir une image", "carhop-blocks")}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</MediaUploadCheck>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div {...blockProps}>
|
||||
<RichText
|
||||
tagName="h2"
|
||||
className="tab__title"
|
||||
placeholder="Titre"
|
||||
value={title}
|
||||
onChange={(value) => setAttributes({ title: value })}
|
||||
/>
|
||||
<InnerBlocks
|
||||
allowedBlocks={[
|
||||
"core/heading",
|
||||
"core/paragraph",
|
||||
"core/list",
|
||||
"core/button",
|
||||
"core/buttons",
|
||||
"core/image",
|
||||
"core/embed",
|
||||
"core/quote",
|
||||
"core/pullquote",
|
||||
"core/media-text",
|
||||
"core/table",
|
||||
"core/group",
|
||||
"core/columns",
|
||||
"core/post-title",
|
||||
"carhop-blocks/cta",
|
||||
"carhop-blocks/heading",
|
||||
"carhop-blocks/cta-group",
|
||||
"carhop-blocks/audio-player",
|
||||
"carhop-blocks/content-box",
|
||||
"carhop-blocks/notice-panel",
|
||||
"shortcode",
|
||||
]}
|
||||
template={[["core/paragraph", { content: "Contenu" }]]}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
9
plugins/carhop-blocks/src/tab/editor.scss
Normal file
9
plugins/carhop-blocks/src/tab/editor.scss
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/**
|
||||
* The following styles get applied inside the editor only.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.wp-block-create-block-chapo {
|
||||
border: 1px dotted #f00;
|
||||
}
|
||||
26
plugins/carhop-blocks/src/tab/index.js
Normal file
26
plugins/carhop-blocks/src/tab/index.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { registerBlockType } from "@wordpress/blocks";
|
||||
import "./style.scss";
|
||||
|
||||
import Edit from "./edit";
|
||||
import save from "./save";
|
||||
import metadata from "./block.json";
|
||||
|
||||
registerBlockType(metadata.name, {
|
||||
icon: {
|
||||
src: (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="83.3"
|
||||
height="83.3"
|
||||
viewBox="0 0 83.3 83.3"
|
||||
>
|
||||
<path
|
||||
fill="#146E63"
|
||||
d="M72.7,0H10.7C4.8,0,0,4.8,0,10.7v62c0,5.9,4.8,10.7,10.7,10.7h62c5.9,0,10.7-4.8,10.7-10.7V10.7c0-5.9-4.8-10.7-10.7-10.7ZM10.7,5.8h62c2.7,0,4.8,2.2,4.8,4.8v8.7H5.8v-8.7c0-2.7,2.2-4.8,4.8-4.8ZM72.7,77.5H10.7c-2.7,0-4.8-2.2-4.8-4.8V25.2h71.7v47.5c0,1.3-.5,2.5-1.4,3.4s-2.1,1.4-3.4,1.4h0ZM9.7,12.5c0-1.5,1.3-2.7,2.8-2.8h19.5c.8-.1,1.7.2,2.3.7.6.6,1,1.3,1,2.2s-.4,1.6-1,2.2c-.6.6-1.5.8-2.3.7H12.5c-.8,0-1.5-.4-2-.9-.5-.6-.8-1.3-.8-2.1h0Z"
|
||||
/>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
edit: Edit,
|
||||
save,
|
||||
});
|
||||
17
plugins/carhop-blocks/src/tab/save.js
Normal file
17
plugins/carhop-blocks/src/tab/save.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { useBlockProps } from "@wordpress/block-editor";
|
||||
import { InnerBlocks } from "@wordpress/block-editor";
|
||||
import { RichText } from "@wordpress/block-editor";
|
||||
|
||||
export default function save({ attributes }) {
|
||||
const { title } = attributes;
|
||||
const blockProps = useBlockProps.save({
|
||||
className: "tab",
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<RichText.Content value={title} tagName="h2" className="tab__title" />
|
||||
<InnerBlocks.Content />
|
||||
</>
|
||||
);
|
||||
}
|
||||
12
plugins/carhop-blocks/src/tab/style.scss
Normal file
12
plugins/carhop-blocks/src/tab/style.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* The following styles get applied both on the front of your site
|
||||
* and in the editor.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.wp-block-create-block-chapo {
|
||||
background-color: #21759b;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
}
|
||||
25
plugins/carhop-blocks/src/tab/view.js
Normal file
25
plugins/carhop-blocks/src/tab/view.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Use this file for JavaScript code that you want to run in the front-end
|
||||
* on posts/pages that contain this block.
|
||||
*
|
||||
* When this file is defined as the value of the `viewScript` property
|
||||
* in `block.json` it will be enqueued on the front end of the site.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* "viewScript": "file:./view.js"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you're not making any changes to this file because your project doesn't need any
|
||||
* JavaScript running in the front-end, then you should delete this file and remove
|
||||
* the `viewScript` property from `block.json`.
|
||||
*
|
||||
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#view-script
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.log( 'Hello World! (from create-block-chapo block)' );
|
||||
/* eslint-enable no-console */
|
||||
Loading…
Reference in New Issue
Block a user