小工具區域是站台範本中的一個命名位置。編輯決定那裡顯示什麼,而範本控制區域放在哪裡以及其輸出如何設定樣式。
對於需要在區域出現的任何位置保持同步的內容,請使用小工具區域,例如側邊欄、頁尾欄或推廣訊息。如果編輯需要在項目中插入一份獨立的副本並隨後自訂它,請改用 Section。
新增小工具區域
在 EmDash 管理後台的 Widgets 中建立並填入小工具區域。
-
點擊 Add Widget Area。輸入範本將要查詢的名稱、管理後台中顯示的標籤,以及選填的出現位置說明。
-
將小工具從 Available Widgets 拖入新區域。
-
設定該小工具,然後在區域內拖動小工具以設定其順序。
可用的小工具類型如下:
- Content 算繪編輯輸入的 Portable Text。
- Menu 算繪依名稱選擇的選單。
- Component 算繪內建元件之一:最新文章、分類、標籤、搜尋或封存。
管理後台中的元件設定可控制項目數量上限、日期、計數和搜尋預留位置文字等細節。
以下內建元件小工具可用:
| 元件 | 算繪內容 |
|---|---|
core:recent-posts | 最新文章,可選顯示日期、縮圖和連結 URL 範本(例如 /blog/:slug) |
core:categories | 分類連結和選填的項目計數 |
core:tags | 數量有限的標籤連結清單和選填的計數 |
core:search | 提交到 /search 的搜尋表單 |
core:archives | 按月或按年的文章封存連結 |
core:recent-posts 的連結範本接受與 LiveSearch 的 routeMap 相同的標記::collection、:id(內容的 ULID)、:slug(純 slug)和 :path(slug 或 ID)。沒有範本時,連結保持其現有形式,包括任何 Astro i18n 語言前綴。
在範本中放置區域
從 emdash/ui 匯入 WidgetArea。該元件會取得指定名稱的區域、保持設定的順序,並在區域不存在或為空時不算繪任何內容。
以下版面將側邊欄區域放在頁面內容旁邊:
---
import { WidgetArea } from "emdash/ui";
---
<div class="page-with-sidebar">
<main>
<slot />
</main>
<aside aria-label="Sidebar">
<WidgetArea name="sidebar" class="sidebar-widgets" />
</aside>
</div>
WidgetArea 會在其包裝元素上加入 widget-area 以及傳入的 class。每個項目使用 widget、widget__title 和 widget__content 類別。內容、選單和內建元件小工具會在其下加入更具體的類別。
Astro 元件樣式預設是限定作用域的。為 WidgetArea 內部算繪的標記設定樣式時,請使用全域樣式區塊:
<style is:global>
.page-with-sidebar {
display: grid;
grid-template-columns: minmax(0, 1fr) 18rem;
gap: 2rem;
}
.sidebar-widgets {
display: grid;
gap: 1.5rem;
}
.sidebar-widgets .widget__title {
margin-block-end: 0.75rem;
}
@media (max-width: 48rem) {
.page-with-sidebar {
grid-template-columns: 1fr;
}
}
</style>
小工具中的選單與分類法
選單、分類和標籤小工具會依目前請求的語言查詢資料。當存在翻譯後的內容或術語時,選單參照也會解析到對應的翻譯版本。
內建小工具算繪器使用選單或分類法輔助函式回傳的根相對 URL,不會加入 Astro 的語言前綴。在多語言站台上,如果這些連結需要語言前綴,請使用選單算繪模式或術語列表模式來算繪導覽和分類法清單。內容、搜尋、最新文章和封存小工具仍可使用標準的 WidgetArea 元件。
自行算繪區域
當站台需要內建算繪器無法提供的標記時,請呼叫 getWidgetArea()。以下範例算繪一個包含內容小工具和選單小工具的區域,並為選單連結加入 Astro 的語言前綴。
首先,取得區域並將每個已設定的小工具傳給算繪器:
---
import { getWidgetArea } from "emdash";
import LocalizedWidget from "./LocalizedWidget.astro";
interface Props {
name: string;
}
const area = await getWidgetArea(Astro.props.name);
---
{area && area.widgets.length > 0 && (
<div class="widget-area" data-widget-area={area.name}>
{area.widgets.map((widget) => (
<LocalizedWidget widget={widget} />
))}
</div>
)}
然後明確處理內容小工具和選單小工具:
---
import { getMenu } from "emdash";
import type { Widget } from "emdash";
import { PortableText } from "emdash/ui";
import { getRelativeLocaleUrl } from "astro:i18n";
interface Props {
widget: Widget;
}
const { widget } = Astro.props;
const locale = Astro.currentLocale;
const menu = widget.type === "menu" && widget.menuName
? await getMenu(widget.menuName, { locale })
: null;
function menuHref(url: string) {
return locale && url.startsWith("/")
? getRelativeLocaleUrl(locale, url)
: url;
}
---
{widget.type !== "component" && (
<section class="widget" data-widget-id={widget.id}>
{widget.title && <h3>{widget.title}</h3>}
{widget.type === "content" && widget.content && (
<PortableText value={widget.content} />
)}
{widget.type === "menu" && menu && (
<nav aria-label={widget.title}>
<ul>
{menu.items.map((item) => (
<li>
<a
href={menuHref(item.url)}
target={item.target}
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
>
{item.label}
</a>
</li>
))}
</ul>
</nav>
)}
</section>
)}
這個專用算繪器不會為元件小工具產生任何輸出。請將元件小工具保留在標準的 WidgetArea 中,或為你要支援的站台元件加入明確的元件 ID 分支。
執行階段 API 參考記錄了 getWidgetArea() 和 getWidgetAreas()。如需以程式方式修改,請使用 Bearer 權杖進行驗證,並在每個會改變狀態的請求中加入 X-EmDash-Request: 1。請求主體和回應請參閱小工具區域端點。