Les zones de widgets sont des régions nommées dans vos templates où les administrateurs peuvent placer des blocs de contenu. Utilisez-les pour les barres latérales, colonnes de pied de page, bannières promotionnelles ou toute section que les éditeurs doivent contrôler sans toucher au code.
Interroger les zones de widgets
Utilisez getWidgetArea() pour récupérer une zone de widget par nom :
---
import { getWidgetArea } from "emdash";
const sidebar = await getWidgetArea("sidebar");
---
{sidebar && sidebar.widgets.length > 0 && (
<aside class="sidebar">
{sidebar.widgets.map(widget => (
<div class="widget">
{widget.title && <h3>{widget.title}</h3>}
<!-- Rendre le contenu du widget -->
</div>
))}
</aside>
)}
La fonction retourne null si la zone de widget n’existe pas.
Structure d’une zone de widgets
Une zone de widget contient des métadonnées et un tableau de widgets :
interface WidgetArea {
id: string;
name: string; // Identifiant unique ("sidebar", "footer-1")
label: string; // Nom d'affichage ("Barre latérale principale")
description?: string;
widgets: Widget[];
}
interface Widget {
id: string;
type: "content" | "menu" | "component";
title?: string;
// Champs spécifiques au type
content?: PortableTextBlock[]; // Pour les widgets de contenu
menuName?: string; // Pour les widgets de menu
componentId?: string; // Pour les widgets de composant
componentProps?: Record<string, unknown>;
}
Types de widgets
EmDash prend en charge trois types de widgets :
Widgets de contenu
Contenu texte riche stocké en Portable Text. Rendez-le avec le composant PortableText :
---
import { PortableText } from "emdash/ui";
---
{widget.type === "content" && widget.content && (
<div class="widget-content">
<PortableText value={widget.content} />
</div>
)}
Widgets de menu
Affichez un menu de navigation dans une zone de widget :
---
import { getMenu } from "emdash";
const menu = widget.menuName ? await getMenu(widget.menuName) : null;
---
{widget.type === "menu" && menu && (
<nav class="widget-nav">
<ul>
{menu.items.map(item => (
<li><a href={item.url}>{item.label}</a></li>
))}
</ul>
</nav>
)}
Widgets de composant
Rendez un composant enregistré avec des props configurables. EmDash inclut ces composants de base :
| ID du composant | Description | Props |
|---|---|---|
core:recent-posts | Liste des articles récents | count, showThumbnails, showDate |
core:categories | Liste des catégories | showCount, hierarchical |
core:tags | Nuage de tags | showCount, limit |
core:search | Formulaire de recherche | placeholder |
core:archives | Archives mensuelles/annuelles | type, limit |
Rendre les widgets
Créez un composant de rendu de widgets réutilisable :
---
import { PortableText } from "emdash/ui";
import { getMenu } from "emdash";
import type { Widget } from "emdash";
// Importer vos composants de widget
import RecentPosts from "./widgets/RecentPosts.astro";
import Categories from "./widgets/Categories.astro";
import TagCloud from "./widgets/TagCloud.astro";
import SearchForm from "./widgets/SearchForm.astro";
import Archives from "./widgets/Archives.astro";
interface Props {
widget: Widget;
}
const { widget } = Astro.props;
const componentMap: Record<string, any> = {
"core:recent-posts": RecentPosts,
"core:categories": Categories,
"core:tags": TagCloud,
"core:search": SearchForm,
"core:archives": Archives,
};
const menu = widget.type === "menu" && widget.menuName
? await getMenu(widget.menuName)
: null;
---
<div class="widget">
{widget.title && <h3 class="widget-title">{widget.title}</h3>}
{widget.type === "content" && widget.content && (
<div class="widget-content">
<PortableText value={widget.content} />
</div>
)}
{widget.type === "menu" && menu && (
<nav class="widget-menu">
<ul>
{menu.items.map(item => (
<li><a href={item.url}>{item.label}</a></li>
))}
</ul>
</nav>
)}
{widget.type === "component" && widget.componentId && componentMap[widget.componentId] && (
<Fragment>
{(() => {
const Component = componentMap[widget.componentId!];
return <Component {...widget.componentProps} />;
})()}
</Fragment>
)}
</div>
Exemples de composants widget
Widget des articles récents
Le composant suivant rend les articles les plus récents, avec des miniatures et dates optionnelles :
---
import { getEmDashCollection } from "emdash";
import { Image } from "emdash/ui";
interface Props {
count?: number;
showThumbnails?: boolean;
showDate?: boolean;
}
const { count = 5, showThumbnails = false, showDate = true } = Astro.props;
const { entries: posts } = await getEmDashCollection("posts", {
limit: count,
orderBy: { publishedAt: "desc" },
});
---
<ul class="recent-posts">
{posts.map(post => (
<li>
{showThumbnails && post.data.featured_image && (
<Image image={post.data.featured_image} alt="" class="thumbnail" />
)}
<a href={`/posts/${post.data.slug}`}>{post.data.title}</a>
{showDate && post.data.publishedAt && (
<time datetime={post.data.publishedAt.toISOString()}>
{post.data.publishedAt.toLocaleDateString()}
</time>
)}
</li>
))}
</ul>
Widget de recherche
Le composant suivant rend un formulaire de recherche qui soumet vers une page de recherche :
---
interface Props {
placeholder?: string;
}
const { placeholder = "Rechercher..." } = Astro.props;
---
<form action="/search" method="get" class="search-form">
<input
type="search"
name="q"
placeholder={placeholder}
aria-label="Rechercher"
/>
<button type="submit">Rechercher</button>
</form>
Utiliser les zones de widgets dans les layouts
L’exemple suivant montre un layout de blog avec une zone de widget dans la barre latérale :
---
import { getWidgetArea } from "emdash";
import WidgetRenderer from "../components/WidgetRenderer.astro";
const sidebar = await getWidgetArea("sidebar");
---
<div class="layout">
<main class="content">
<slot />
</main>
{sidebar && sidebar.widgets.length > 0 && (
<aside class="sidebar">
{sidebar.widgets.map(widget => (
<WidgetRenderer widget={widget} />
))}
</aside>
)}
</div>
<style>
.layout {
display: grid;
grid-template-columns: 1fr 300px;
gap: 2rem;
}
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
}
}
</style>
Lister toutes les zones de widgets
Utilisez getWidgetAreas() pour récupérer toutes les zones de widget avec leurs widgets :
import { getWidgetAreas } from "emdash";
const areas = await getWidgetAreas();
// Retourne toutes les zones avec les widgets remplis
Créer des zones de widgets
Créez des zones de widgets via l’interface d’administration à /_emdash/admin/widgets, ou utilisez l’API d’administration :
POST /_emdash/api/widget-areas
Content-Type: application/json
{
"name": "footer-1",
"label": "Pied de page colonne 1",
"description": "Première colonne du pied de page"
}
Ajouter un widget de contenu :
POST /_emdash/api/widget-areas/footer-1/widgets
Content-Type: application/json
{
"type": "content",
"title": "À propos",
"content": [
{
"_type": "block",
"style": "normal",
"children": [{ "_type": "span", "text": "Bienvenue sur notre site." }]
}
]
}
Ajouter un widget de composant :
POST /_emdash/api/widget-areas/sidebar/widgets
Content-Type: application/json
{
"type": "component",
"title": "Articles récents",
"componentId": "core:recent-posts",
"componentProps": { "count": 5, "showDate": true }
}
Référence API
getWidgetArea(name)
Récupérer une zone de widget par nom avec tous les widgets.
Paramètres :
name— L’identifiant unique de la zone de widget (string)
Retourne : Promise<WidgetArea | null>
getWidgetAreas()
Lister toutes les zones de widget avec leurs widgets.
Retourne : Promise<WidgetArea[]>
getWidgetComponents()
Lister les définitions de composants widget disponibles pour l’UI d’administration.
Retourne : WidgetComponentDef[]