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, les colonnes de pied de page, les 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 widgets 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 renvoie null si la zone de widgets n’existe pas.
Structure de la Zone de Widgets
Une zone de widgets contient des métadonnées et un tableau de widgets :
interface WidgetArea {
id: string;
name: string; // Unique identifier ("sidebar", "footer-1")
label: string; // Display name ("Main Sidebar")
description?: string;
widgets: Widget[];
}
interface Widget {
id: string;
type: "content" | "menu" | "component";
title?: string;
// Type-specific fields
content?: PortableTextBlock[]; // For content widgets
menuName?: string; // For menu widgets
componentId?: string; // For component widgets
componentProps?: Record<string, unknown>;
}
Types de Widgets
EmDash prend en charge trois types de widgets :
Widgets de Contenu
Contenu en texte enrichi stocké sous forme de Portable Text. Rendez-le en utilisant 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 widgets :
---
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 Composants
Rendez un composant enregistré avec des props configurables. EmDash inclut ces composants principaux :
| Component ID | 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";
// Import your widget components
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 de Widgets
Widget Articles Récents
Le composant suivant affiche les articles les plus récents, avec des vignettes et des dates optionnelles :
---
import { getEmDashCollection } from "emdash";
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 && (
<img src={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 affiche un formulaire de recherche qui soumet vers une page de recherche :
---
interface Props {
placeholder?: string;
}
const { placeholder = "Search..." } = Astro.props;
---
<form action="/search" method="get" class="search-form">
<input
type="search"
name="q"
placeholder={placeholder}
aria-label="Search"
/>
<button type="submit">Search</button>
</form>
Utiliser les Zones de Widgets dans les Layouts
L’exemple suivant montre un layout de blog avec une zone de widgets 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 widgets avec leurs widgets :
import { getWidgetAreas } from "emdash";
const areas = await getWidgetAreas();
// Returns all areas with widgets populated
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": "Footer Column 1",
"description": "First column in the footer"
}
Ajouter un widget de contenu :
POST /_emdash/api/widget-areas/footer-1/widgets
Content-Type: application/json
{
"type": "content",
"title": "About Us",
"content": [
{
"_type": "block",
"style": "normal",
"children": [{ "_type": "span", "text": "Welcome to our site." }]
}
]
}
Ajouter un widget de composant :
POST /_emdash/api/widget-areas/sidebar/widgets
Content-Type: application/json
{
"type": "component",
"title": "Recent Posts",
"componentId": "core:recent-posts",
"componentProps": { "count": 5, "showDate": true }
}
Référence API
getWidgetArea(name)
Récupère une zone de widgets par nom avec tous les widgets.
Paramètres :
name— L’identifiant unique de la zone de widgets (string)
Renvoie : Promise<WidgetArea | null>
getWidgetAreas()
Liste toutes les zones de widgets avec leurs widgets.
Renvoie : Promise<WidgetArea[]>
getWidgetComponents()
Liste les définitions de composants de widgets disponibles pour l’interface d’administration.
Renvoie : WidgetComponentDef[]