Aree widget

In questa pagina

Le aree widget sono regioni nominate nei tuoi template dove gli amministratori possono posizionare blocchi di contenuto. Usale per barre laterali, colonne del piè di pagina, banner promozionali o qualsiasi sezione che gli editor devono controllare senza toccare il codice.

Interrogare le aree widget

Usa getWidgetArea() per recuperare un’area widget per nome:

---
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>}
        <!-- Renderizzare il contenuto del widget -->
      </div>
    ))}
  </aside>
)}

La funzione restituisce null se l’area widget non esiste.

Struttura dell’area widget

Un’area widget contiene metadati e un array di widget:

interface WidgetArea {
	id: string;
	name: string; // Identificatore unico ("sidebar", "footer-1")
	label: string; // Nome visualizzato ("Barra laterale principale")
	description?: string;
	widgets: Widget[];
}

interface Widget {
	id: string;
	type: "content" | "menu" | "component";
	title?: string;
	// Campi specifici del tipo
	content?: PortableTextBlock[]; // Per widget di contenuto
	menuName?: string; // Per widget di menu
	componentId?: string; // Per widget di componente
	componentProps?: Record<string, unknown>;
}

Tipi di widget

EmDash supporta tre tipi di widget:

Widget di contenuto

Contenuto in testo ricco memorizzato come Portable Text. Renderizza usando il componente PortableText:

---
import { PortableText } from "emdash/ui";
---

{widget.type === "content" && widget.content && (
  <div class="widget-content">
    <PortableText value={widget.content} />
  </div>
)}

Widget di menu

Mostra un menu di navigazione all’interno di un’area 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>
)}

Widget di componente

Renderizza un componente registrato con props configurabili. EmDash include questi componenti principali:

ID componenteDescrizioneProps
core:recent-postsLista post recenticount, showThumbnails, showDate
core:categoriesLista categorieshowCount, hierarchical
core:tagsNuvola di tagshowCount, limit
core:searchModulo di ricercaplaceholder
core:archivesArchivi mensili/annualitype, limit

Renderizzare i widget

Crea un componente renderizzatore di widget riutilizzabile:

---
import { PortableText } from "emdash/ui";
import { getMenu } from "emdash";
import type { Widget } from "emdash";

// Importare i componenti 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>

Esempi di componenti widget

Widget post recenti

Il seguente componente renderizza i post più recenti, con miniature e date opzionali:

---
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 di ricerca

Il seguente componente renderizza un modulo di ricerca che invia a una pagina di ricerca:

---
interface Props {
  placeholder?: string;
}

const { placeholder = "Cerca..." } = Astro.props;
---

<form action="/search" method="get" class="search-form">
  <input
    type="search"
    name="q"
    placeholder={placeholder}
    aria-label="Cerca"
  />
  <button type="submit">Cerca</button>
</form>

Usare le aree widget nei layout

L’esempio seguente mostra un layout blog con un’area widget nella barra laterale:

---
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>

Elencare tutte le aree widget

Usa getWidgetAreas() per recuperare tutte le aree widget con i loro widget:

import { getWidgetAreas } from "emdash";

const areas = await getWidgetAreas();
// Restituisce tutte le aree con i widget popolati

Creare aree widget

Crea aree widget tramite l’interfaccia admin su /_emdash/admin/widgets, o usa l’API di amministrazione:

POST /_emdash/api/widget-areas
Content-Type: application/json

{
  "name": "footer-1",
  "label": "Piè di pagina colonna 1",
  "description": "Prima colonna nel piè di pagina"
}

Aggiungere un widget di contenuto:

POST /_emdash/api/widget-areas/footer-1/widgets
Content-Type: application/json

{
  "type": "content",
  "title": "Chi siamo",
  "content": [
    {
      "_type": "block",
      "style": "normal",
      "children": [{ "_type": "span", "text": "Benvenuti nel nostro sito." }]
    }
  ]
}

Aggiungere un widget di componente:

POST /_emdash/api/widget-areas/sidebar/widgets
Content-Type: application/json

{
  "type": "component",
  "title": "Post recenti",
  "componentId": "core:recent-posts",
  "componentProps": { "count": 5, "showDate": true }
}

Riferimento API

getWidgetArea(name)

Recuperare un’area widget per nome con tutti i widget.

Parametri:

  • name — L’identificatore unico dell’area widget (string)

Restituisce: Promise<WidgetArea | null>

getWidgetAreas()

Elencare tutte le aree widget con i loro widget.

Restituisce: Promise<WidgetArea[]>

getWidgetComponents()

Elencare le definizioni dei componenti widget disponibili per l’UI admin.

Restituisce: WidgetComponentDef[]