React
Page Banner
페이지 상단에 위치하며 사용자에게 전체적인 상태나 중요한 메시지를 전달하는 상위 레벨 메시지 컴포넌트입니다.
사용 가능 버전@seed-design/[email protected], @seed-design/[email protected]
import { VStack } from "@seed-design/react";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
} from "seed-design/ui/page-banner";
export default function PageBannerPreview() {
return (
<VStack gap="x4" width="full">
<PageBanner description="Ut veniam in ea ea anim laborum magna dolore ea laborum duis ut aute mollit amet." />
<ActionablePageBanner description="Ut veniam in ea ea anim laborum magna dolore ea laborum duis ut aute mollit amet." />
<DismissiblePageBanner description="Ut veniam in ea ea anim laborum magna dolore ea laborum duis ut aute mollit amet." />
</VStack>
);
}Installation
npx @seed-design/cli@latest add ui:page-bannerpnpm dlx @seed-design/cli@latest add ui:page-banneryarn dlx @seed-design/cli@latest add ui:page-bannerbun x @seed-design/cli@latest add ui:page-banner의존성 설치
npm install @karrotmarket/react-monochrome-icon @seed-design/reactyarn add @karrotmarket/react-monochrome-icon @seed-design/reactpnpm add @karrotmarket/react-monochrome-icon @seed-design/reactbun add @karrotmarket/react-monochrome-icon @seed-design/react아래 코드를 복사 후 붙여넣고 사용하세요
/**
* @file ui:page-banner
* @requires @seed-design/react@^2.0.0 || ^3.0.0
**/
"use client";
import { PrefixIcon, PageBanner as SeedPageBanner, SuffixIcon } from "@seed-design/react";
import * as React from "react";
import { IconChevronRightLine, IconXmarkLine } from "@karrotmarket/react-monochrome-icon"; // "@daangn/react-monochrome-icon"과 동일합니다.
export interface PageBannerProps
extends Omit<
SeedPageBanner.RootProps,
"children" | "title" | "asChild" | "open" | "defaultOpen" | "onDismiss"
> {
prefixIcon?: React.ReactNode;
title?: React.ReactNode;
description: React.ReactNode;
suffix?: React.ReactNode;
}
/**
* @see https://seed-design.io/react/components/page-banner
*/
export const PageBanner = React.forwardRef<
React.ElementRef<typeof SeedPageBanner.Root>,
PageBannerProps
>(({ prefixIcon, title, description, suffix, ...otherProps }, ref) => {
return (
<SeedPageBanner.Root ref={ref} {...otherProps}>
{prefixIcon && <PrefixIcon svg={prefixIcon} />}
<SeedPageBanner.Content>
<SeedPageBanner.Body>
{title && <SeedPageBanner.Title>{title}</SeedPageBanner.Title>}
<SeedPageBanner.Description>{description}</SeedPageBanner.Description>
</SeedPageBanner.Body>
{suffix}
</SeedPageBanner.Content>
</SeedPageBanner.Root>
);
});
PageBanner.displayName = "PageBanner";
export interface PageBannerButtonProps extends SeedPageBanner.ButtonProps {}
export const PageBannerButton = SeedPageBanner.Button;
export interface ActionablePageBannerProps
extends Omit<
SeedPageBanner.RootProps,
"children" | "title" | "asChild" | "open" | "defaultOpen" | "onDismiss"
> {
prefixIcon?: React.ReactNode;
title?: React.ReactNode;
description: React.ReactNode;
}
/**
* @see https://seed-design.io/react/components/page-banner
*/
export const ActionablePageBanner = React.forwardRef<
React.ElementRef<typeof SeedPageBanner.Root>,
ActionablePageBannerProps
>(({ prefixIcon, title, description, ...otherProps }, ref) => {
return (
<SeedPageBanner.Root ref={ref} {...otherProps} asChild>
<button type="button">
{prefixIcon && <PrefixIcon svg={prefixIcon} />}
<SeedPageBanner.Content>
<SeedPageBanner.Body>
{title && <SeedPageBanner.Title>{title}</SeedPageBanner.Title>}
<SeedPageBanner.Description>{description}</SeedPageBanner.Description>
</SeedPageBanner.Body>
</SeedPageBanner.Content>
<SuffixIcon svg={<IconChevronRightLine />} />
</button>
</SeedPageBanner.Root>
);
});
ActionablePageBanner.displayName = "ActionablePageBanner";
export interface DismissiblePageBannerProps
extends Omit<SeedPageBanner.RootProps, "children" | "title" | "asChild"> {
prefixIcon?: React.ReactNode;
title?: React.ReactNode;
description: React.ReactNode;
}
/**
* @see https://seed-design.io/react/components/page-banner
*/
export const DismissiblePageBanner = React.forwardRef<
React.ElementRef<typeof SeedPageBanner.Root>,
DismissiblePageBannerProps
>(({ prefixIcon, title, description, ...otherProps }, ref) => {
return (
<SeedPageBanner.Root ref={ref} {...otherProps}>
{prefixIcon && <PrefixIcon svg={prefixIcon} />}
<SeedPageBanner.Content>
<SeedPageBanner.Body>
{title && <SeedPageBanner.Title>{title}</SeedPageBanner.Title>}
<SeedPageBanner.Description>{description}</SeedPageBanner.Description>
</SeedPageBanner.Body>
</SeedPageBanner.Content>
{/* You may implement your own i18n for dismiss label */}
<SeedPageBanner.CloseButton aria-label="닫기">
<SuffixIcon svg={<IconXmarkLine />} />
</SeedPageBanner.CloseButton>
</SeedPageBanner.Root>
);
});
DismissiblePageBanner.displayName = "DismissiblePageBanner";
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
Props
PageBanner
Prop
Type
prefixIcon?React.ReactNodetitle?React.ReactNodedescriptionReact.ReactNodesuffix?React.ReactNodePageBannerButton
Prop
Type
ActionablePageBanner
Prop
Type
prefixIcon?React.ReactNodetitle?React.ReactNodedescriptionReact.ReactNodeDismissiblePageBanner
Prop
Type
prefixIcon?React.ReactNodetitle?React.ReactNodedescriptionReact.ReactNodeopen?boolean | undefineddefaultOpen?boolean | undefinedonDismiss?(() => void) | undefinedExamples
Extending to Safe Area
extendSafeAreaX를 지정하면 배경이 좌우 safe area inset까지 화면 끝으로 넓어지고, 아이콘과 글자, 버튼은 safe area 안에 남습니다. AppScreenContent처럼 inset을 반영한 컨테이너 바로 안에서 사용하세요. 화면 끝까지 채우는 다른 방법은 Safe Area 구현 가이드를 참고하세요.
With Button
PageBanner의 suffix prop에 PageBannerButton을 전달하여 버튼을 추가할 수 있습니다.
import { PageBanner, PageBannerButton } from "seed-design/ui/page-banner";
export default function PageBannerWithButton() {
return (
<PageBanner
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>자세히 보기</PageBannerButton>}
/>
);
}Rendering PageBannerButton as a Child
import { PageBanner, PageBannerButton } from "seed-design/ui/page-banner";
export default function PageBannerButtonAsChild() {
return (
<PageBanner
description="사업자 정보를 등록해주세요."
suffix={
<PageBannerButton asChild>
<a href="https://www.daangn.com" target="_blank" rel="noreferrer">
새 탭에서 열기
</a>
</PageBannerButton>
}
/>
);
}Tones and Variants
Neutral
import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerNeutral() {
return (
<div className="w-full grid grid-cols-2 items-start gap-4">
<PageBanner
tone="neutral"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<PageBanner
tone="neutral"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<ActionablePageBanner
tone="neutral"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<ActionablePageBanner
tone="neutral"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="neutral"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="neutral"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
</div>
);
}Positive
import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerPositive() {
return (
<div className="w-full grid grid-cols-2 items-start gap-4">
<PageBanner
tone="positive"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<PageBanner
tone="positive"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<ActionablePageBanner
tone="positive"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<ActionablePageBanner
tone="positive"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="positive"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="positive"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
</div>
);
}Informative
import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerInformative() {
return (
<div className="w-full grid grid-cols-2 items-start gap-4">
<PageBanner
tone="informative"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<PageBanner
tone="informative"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<ActionablePageBanner
tone="informative"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<ActionablePageBanner
tone="informative"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="informative"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="informative"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
</div>
);
}Warning
import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerWarning() {
return (
<div className="w-full grid grid-cols-2 items-start gap-4">
<PageBanner
tone="warning"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<PageBanner
tone="warning"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<ActionablePageBanner
tone="warning"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<ActionablePageBanner
tone="warning"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="warning"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="warning"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
</div>
);
}Critical
import { IconExclamationmarkCircleFill } from "@karrotmarket/react-monochrome-icon";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerCritical() {
return (
<div className="w-full grid grid-cols-2 items-start gap-4">
<PageBanner
tone="critical"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<PageBanner
tone="critical"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
suffix={<PageBannerButton>등록하기</PageBannerButton>}
/>
<ActionablePageBanner
tone="critical"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<ActionablePageBanner
tone="critical"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="critical"
variant="weak"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
<DismissiblePageBanner
tone="critical"
variant="solid"
prefixIcon={<IconExclamationmarkCircleFill />}
title="미노출"
description="사업자 정보를 등록해주세요."
/>
</div>
);
}Magic
tone="magic"은 variant="weak" 조합으로만 사용할 수 있습니다.
import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon";
import { VStack } from "@seed-design/react";
import {
ActionablePageBanner,
DismissiblePageBanner,
PageBanner,
PageBannerButton,
} from "seed-design/ui/page-banner";
export default function PageBannerMagic() {
return (
<VStack gap="x4" width="full">
<PageBanner
tone="magic"
variant="weak"
prefixIcon={<IconSparkle2 />}
title="새로운 기능"
description="마법 같은 소식이 도착했어요!"
suffix={<PageBannerButton>둘러보기</PageBannerButton>}
/>
<ActionablePageBanner
tone="magic"
variant="weak"
prefixIcon={<IconSparkle2 />}
title="새로운 기능"
description="마법 같은 소식이 도착했어요!"
/>
<DismissiblePageBanner
tone="magic"
variant="weak"
prefixIcon={<IconSparkle2 />}
title="새로운 기능"
description="마법 같은 소식이 도착했어요!"
/>
</VStack>
);
}Last updated on