위젯 영역은 사이트 템플릿 안의 이름이 있는 위치입니다. 그곳에 무엇이 나타날지는 에디터가 고르고, 영역이 어디에 놓일지와 출력을 어떻게 스타일링할지는 템플릿이 제어합니다.
사이드바, 푸터 열, 프로모션 메시지처럼 영역이 나타나는 모든 곳에서 동기화된 상태를 유지해야 하는 콘텐츠에는 위젯 영역을 사용하세요. 에디터가 항목 안에 독립적인 사본을 삽입한 다음 사용자 지정해야 한다면 섹션을 사용하세요.
위젯 영역 추가
위젯 영역은 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(슬러그만), :path(슬러그 또는 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을 추가하세요. 요청 본문과 응답은 위젯 영역 엔드포인트를 참고하세요.