WordPress posiada swój własny, wbudowany blok details. Ma on jednak pewne ograniczenia – możemy tam ładować tylko tekst. Nie możemy osadzać innych bloków, na przykład bloków z kodem. Napiszemy własny details, korzystając z tagów HTML5 oraz bloków zagnieżdżonych.
HTML5 <details> i <summary> – jak to działa
HTML5 wprowadził tagi <details> oraz <summary>. Ich użycie wygląda tak:
<details>
<summary>Details</summary>
Something small enough to escape casual notice.
</details>
Wewnątrz summary ląduje treść, którą widać zawsze (zazwyczaj z czarnym trójkątem obok, ale ostylować można dowolnie CSSem). Poza tagiem <summary>, ale wewnątrz <details> jest treść, która ma się rozwinąć po kliknięciu.
WordPress posiada taki element details, ale możemy tam wrzucać tekst tylko, możemy zapomnieć o wrzuceniu bloku z kodem, dlatego będziemy musieli wykorzystać bloki wewnętrzne.
Do summary wrzucimy <TextControl> i zawartość atrybutu tekstowego, zaś pod <summary> damy bloki wewnętrzne i możliwość dowolnego osadzania tam czegokolwiek.
Nauczymy się w ten sposób jak działają bloki wewnętrzne. Do dzieła.
Piszemy blok z możliwością osadzania bloków wewnętrznych
Tworzymy blok WordPressa, ale nie dynamiczny (–variant=dynamic) tylko statyczny (posiadający plik save.js, który odpowiada za wyświetlanie zapisanego bloku zamiast render.php).
npx @wordpress/create-block@latest details
W block.json tworzymy atrybut tekstowy do przechowywania tekstu wewnątrz tagu <summary>:
"attributes": {
"summary": {
"type": "string",
"default": "Your summary"
}
}
W edit.js importujemy <TextControl> (do wpisywania naszego summary) oraz InnerBlocks (do osadzania bloków):
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
import { TextControl } from '@wordpress/components';
Teraz zamieniamy nasz edit na poprawny element <details> <summary>:
export default function Edit({attributes, setAttributes}) {
return (
<details { ...useBlockProps() }>
<summary><TextControl
label="Strzeszczenie"
value={ attributes.summary }
onChange={ ( value ) => setAttributes({summary: value}) } />
</summary>
<InnerBlocks />
</details>
);
}
Już teraz można kompilować aby wypróbować edycję. Oczywiście aby dodać bloki zagnieżdżone będziemy musieli kliknąć ten trójkąt obok kontrolki tekstowej. Ja bym jednak jeszcze CSSa wyczyścił w style.scss:
.wp-block-create-block-details {
// background-color: #21759b;
// color: #fff;
// padding: 2px;
}
Aby blok mógł się poprawnie wyświetlać po zapisaniu musimy jeszcze napisać save.js. Komponent innerblocks jest podobny nieco do richtext, tutaj będziemy musieli zastosować jego 'content’:
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
(...)
export default function save({attributes}) {
return (
<details { ...useBlockProps.save() }>
<summary>{attributes.summary}</summary>
<InnerBlocks.Content />
</details>
);
}
Teraz mamy w pełni funkcjonalny blok. Możemy się bawić CSSem, dodawać nowe opcje, dalej to rozwijać, ale koniec końców mamy już gotowy blok, który korzysta z możliwości zagnieżdżania innych bloków w sobie.
Podobnie jak z <RichText> łatwiej się pisze <InnerBlocks> z poziomu save.js raczej niż render.php, choć to nie jest jedynie słuszna opcja. Ogólnie zawsze lepiej (moim zdaniem) pisać albo bloki dynamiczne z render.php na widoku po zapisaniu albo bardziej dynamiczne, frontendowe bloki wykorzystujące view.js (albo i view i render), ale to tylko moja preferencja.