SEED Design

Help Bubble

Help Bubble은 사용자에게 컴포넌트의 상태나 특정 기능에 대한 추가 정보를 제공하는 부가적인 도움말 컴포넌트입니다.

import { IconILowercaseSerifCircleLine } from "@karrotmarket/react-monochrome-icon";
import { HelpBubbleTrigger } from "seed-design/ui/help-bubble";
import { ActionButton } from "seed-design/ui/action-button";
import { Icon } from "@seed-design/react";

export default function HelpBubblePreview() {
  return (
    <HelpBubbleTrigger defaultOpen title="아래 버튼이나 바깥 영역을 클릭해서 닫아보세요.">
      <ActionButton variant="ghost" size="small" layout="iconOnly" aria-label="도움말">
        <Icon svg={<IconILowercaseSerifCircleLine />} />
      </ActionButton>
    </HelpBubbleTrigger>
  );
}

Installation

npx @seed-design/cli@latest add ui:help-bubble

Props

HelpBubbleTrigger

Prop

Type

HelpBubbleAnchor

Prop

Type

Examples

Trigger

HelpBubbleTriggerchildren을 클릭하면 Help Bubble이 열리고 닫힙니다.

children으로는 button 등 포커스 가능한 요소를 넣어야 합니다.

import { VStack } from "@seed-design/react";
import { useState } from "react";
import { HelpBubbleTrigger } from "seed-design/ui/help-bubble";
import { Switch } from "seed-design/ui/switch";
import { ActionButton } from "seed-design/ui/action-button";

export default function () {
  const [isControlledHelpBubbleOpen, setIsControlledHelpBubbleOpen] = useState(true);

  return (
    <VStack gap="x16" align="center">
      <HelpBubbleTrigger
        defaultOpen
        title="Trigger, uncontrolled"
        description="클릭으로 열고 닫는 동작이 있는 트리거입니다."
        placement="right"
        showCloseButton
        closeOnInteractOutside={false}
      >
        <ActionButton variant="neutralSolid">토글</ActionButton>
      </HelpBubbleTrigger>
      <VStack gap="spacingY.componentDefault" align="center">
        <HelpBubbleTrigger
          open={isControlledHelpBubbleOpen}
          onOpenChange={setIsControlledHelpBubbleOpen}
          title="Trigger, controlled"
          description="클릭으로 열고 닫는 동작이 있는 트리거입니다."
          placement="right"
          showCloseButton
          closeOnInteractOutside={false}
        >
          <ActionButton variant="neutralSolid">토글</ActionButton>
        </HelpBubbleTrigger>
        <Switch
          size="24"
          tone="neutral"
          label="열림"
          checked={isControlledHelpBubbleOpen}
          onCheckedChange={setIsControlledHelpBubbleOpen}
        />
      </VStack>
    </VStack>
  );
}

Anchor

HelpBubbleAnchorchildren은 Help Bubble이 위치를 잡는 데에만 사용되며 클릭으로 열고 닫는 동작은 없습니다.

defaultOpenshowCloseButton을 사용하여 적절하게 열리고 닫히도록 하거나, open prop을 controlled하게 사용하여 열리고 닫힌 상태를 직접 관리할 수 있습니다.

import { VStack } from "@seed-design/react";
import { useState } from "react";
import { Avatar } from "seed-design/ui/avatar";
import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";
import { Switch } from "seed-design/ui/switch";

export default function () {
  const [isControlledHelpBubbleOpen, setIsControlledHelpBubbleOpen] = useState(true);

  return (
    <VStack gap="x16" align="center">
      <HelpBubbleAnchor
        defaultOpen
        title="Anchor, uncontrolled"
        description="클릭으로 열고 닫는 동작 없이 위치만 지정합니다."
        placement="right"
        showCloseButton
        closeOnInteractOutside={false}
      >
        <Avatar size="64" src="https://avatars.githubusercontent.com/u/54893898?v=4" fallback="L" />
      </HelpBubbleAnchor>
      <VStack gap="spacingY.componentDefault" align="center">
        <HelpBubbleAnchor
          open={isControlledHelpBubbleOpen}
          onOpenChange={setIsControlledHelpBubbleOpen}
          title="Anchor, controlled"
          description="클릭으로 열고 닫는 동작 없이 위치만 지정합니다."
          placement="right"
          showCloseButton
          closeOnInteractOutside={false}
        >
          <Avatar
            size="64"
            src="https://avatars.githubusercontent.com/u/54893898?v=4"
            fallback="L"
          />
        </HelpBubbleAnchor>
        <Switch
          size="24"
          tone="neutral"
          label="열림"
          checked={isControlledHelpBubbleOpen}
          onCheckedChange={setIsControlledHelpBubbleOpen}
        />
      </VStack>
    </VStack>
  );
}

Close On Interact Outside

closeOnInteractOutside prop을 false로 설정하면 Help Bubble 및 HelpBubbleTrigger, HelpBubbleAnchor 외부를 클릭해도 Help Bubble이 닫히지 않습니다. 기본값은 true입니다.

import { VStack } from "@seed-design/react";
import { HelpBubbleTrigger } from "seed-design/ui/help-bubble";
import { ActionButton } from "seed-design/ui/action-button";

export default function () {
  return (
    <VStack gap="x16" align="center">
      <HelpBubbleTrigger
        defaultOpen
        title="This closes on interactions outside"
        placement="right"
        closeOnInteractOutside
      >
        <ActionButton variant="neutralSolid">토글</ActionButton>
      </HelpBubbleTrigger>
      <HelpBubbleTrigger
        defaultOpen
        title="This does not close on interactions outside"
        placement="right"
        closeOnInteractOutside={false}
      >
        <ActionButton variant="neutralSolid">토글</ActionButton>
      </HelpBubbleTrigger>
    </VStack>
  );
}

Placement

import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon";
import { Box, Icon } from "@seed-design/react";
import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";

export default function HelpBubblePreview() {
  return (
    <div
      style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: "80px", padding: "80px" }}
    >
      <HelpBubbleAnchor
        open
        flip={false}
        placement="top-end"
        title="top-end"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor open flip={false} placement="top" title="top" description="est tempor aute">
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="top-start"
        title="top-start"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="left-end"
        title="left-end"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <Box />
      <HelpBubbleAnchor
        open
        flip={false}
        placement="right-end"
        title="right-end"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="left"
        title="left"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <Box />
      <HelpBubbleAnchor
        open
        flip={false}
        placement="right"
        title="right"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="left-start"
        title="left-start"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <Box />
      <HelpBubbleAnchor
        open
        flip={false}
        placement="right-start"
        title="right-start"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="bottom-end"
        title="bottom-end"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="bottom"
        title="bottom"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor
        open
        flip={false}
        placement="bottom-start"
        title="bottom-start"
        description="est tempor aute"
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
    </div>
  );
}

Flip

import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon";
import { Icon } from "@seed-design/react";
import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";

export default function HelpBubbleFlip() {
  return (
    <HelpBubbleAnchor
      open
      flip={false}
      title="Flip"
      description="Flip을 끄면 화면 경계에서 방향이 바뀌지 않아요."
    >
      <Icon svg={<IconSparkle2 />} />
    </HelpBubbleAnchor>
  );
}

Close Button

import { ActionButton } from "seed-design/ui/action-button";
import { HelpBubbleTrigger } from "seed-design/ui/help-bubble";

export default function HelpBubbleCloseButton() {
  return (
    <HelpBubbleTrigger
      defaultOpen
      showCloseButton
      title="Close Button"
      description="showCloseButton으로 닫기 버튼을 추가할 수 있어요."
    >
      <ActionButton variant="neutralSolid">토글</ActionButton>
    </HelpBubbleTrigger>
  );
}

Title Only

import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon";
import { Icon } from "@seed-design/react";
import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";

export default function HelpBubbleTitleOnly() {
  return (
    <HelpBubbleAnchor open title="Title Only">
      <Icon svg={<IconSparkle2 />} />
    </HelpBubbleAnchor>
  );
}

Setting Width Manually

contentProps에 인라인 스타일로 maxWidthwidth를 설정하여 너비를 조절할 수 있습니다.

import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";
import { SegmentedControl, SegmentedControlItem } from "seed-design/ui/segmented-control";
import { VStack } from "@seed-design/react";
import { useState } from "react";

const WIDTH_OPTIONS = ["200px", "300px", "unset"] as const;

export default function HelpBubbleWidth() {
  const [width, setWidth] = useState<(typeof WIDTH_OPTIONS)[number]>("300px");

  return (
    <VStack gap="spacingY.componentDefault" align="center" p="x10">
      <HelpBubbleAnchor
        open
        title="Pariatur aliqua commodo eu Lorem minim anim. Lorem ipsum voluptate eu duis eiusmod consequat."
        contentProps={{ style: { width } }}
      >
        <SegmentedControl
          aria-label="너비"
          value={width}
          onValueChange={(value) => setWidth(value as (typeof WIDTH_OPTIONS)[number])}
        >
          {WIDTH_OPTIONS.map((option) => (
            <SegmentedControlItem key={option} value={option}>
              {option}
            </SegmentedControlItem>
          ))}
        </SegmentedControl>
      </HelpBubbleAnchor>
    </VStack>
  );
}

Line Breaks

import { IconSparkle2 } from "@karrotmarket/react-multicolor-icon";
import { Icon } from "@seed-design/react";
import { HelpBubbleAnchor } from "seed-design/ui/help-bubble";
import { HStack } from "@seed-design/react";

export default function HelpBubbleLineBreaks() {
  return (
    <HStack gap="x16">
      <HelpBubbleAnchor
        open
        title={
          <>
            Breaking
            <br />
            lines
            <br />
            using
            <br />
            `&lt;br /&gt;`s
          </>
        }
      >
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
      <HelpBubbleAnchor open title={"Breaking\nlines\nusing\nnewlines"}>
        <Icon svg={<IconSparkle2 />} />
      </HelpBubbleAnchor>
    </HStack>
  );
}

Last updated on