nnuer
강희태@gmlxo9917

데스크톱은 사이드 메뉴, 모바일은 드롭다운이 되는 계정 설정 내비

기타 블록

넓은 화면에서는 왼쪽 세로 메뉴(구분선으로 묶음), 좁은 화면에서는 현재 메뉴 이름과 화살표가 있는 드롭다운으로 바뀌는 계정 설정 레이아웃입니다.

블록 신고

운영자가 확인한 뒤 필요하면 블록을 숨깁니다.

사유
Claude Code · claude-opus-5-5 · React (TSX)
결과 코드펼치기
import { useState } from "react";

const line = { fill: "none", stroke: "currentColor", strokeWidth: 1.4, strokeLinecap: "round" as const, strokeLinejoin: "round" as const };

const GROUPS = [
  [
    {
      id: "orders",
      label: "주문 내역",
      icon: (
        <svg width="16" height="16" viewBox="0 0 16 16" {...line} aria-hidden>
          <path d="M3 2.5h10v11H3z" />
          <path d="M5.5 5.5h5M5.5 8h5M5.5 10.5h3" />
        </svg>
      ),
      body: "최근 3개월 주문 4건이 있어요. 배송 중인 주문은 1건입니다.",
    },
    {
      id: "address",
      label: "배송지 관리",
      icon: (
        <svg width="16" height="16" viewBox="0 0 16 16" {...line} aria-hidden>
          <path d="M8 14s4.5-4 4.5-7.5a4.5 4.5 0 0 0-9 0C3.5 10 8 14 8 14Z" />
          <circle cx="8" cy="6.5" r="1.5" />
        </svg>
      ),
      body: "기본 배송지: 서울시 성동구 성수이로 00, 3층",
    },
    {
      id: "payment",
      label: "결제 수단",
      icon: (
        <svg width="16" height="16" viewBox="0 0 16 16" {...line} aria-hidden>
          <rect x="2" y="3.5" width="12" height="9" rx="1.5" />
          <path d="M2 6.5h12" />
        </svg>
      ),
      body: "등록된 카드 2장. 간편결제 비밀번호를 설정해 두면 더 빨라요.",
    },
  ],
  [
    {
      id: "notify",
      label: "알림 설정",
      icon: (
        <svg width="16" height="16" viewBox="0 0 16 16" {...line} aria-hidden>
          <path d="M4 11V7a4 4 0 0 1 8 0v4l1 1.5H3L4 11Z" />
          <path d="M6.5 14h3" />
        </svg>
      ),
      body: "배송 알림은 켜져 있고, 할인 소식은 꺼져 있어요.",
    },
  ],
];

export default function AccountSettingsNav() {
  const all = GROUPS.flat();
  const [active, setActive] = useState(all[0].id);
  const [open, setOpen] = useState(false);
  const current = all.find((s) => s.id === active) ?? all[0];

  const groups = (compact: boolean) =>
    GROUPS.map((group, i) => (
      <ul key={i} className={i > 0 ? "border-t border-zinc-200 pt-2" : ""}>
        {group.map((s) => {
          const selected = s.id === active;
          return (
            <li key={s.id}>
              <button
                type="button"
                aria-current={selected ? "page" : undefined}
                onClick={() => {
                  setActive(s.id);
                  setOpen(false);
                }}
                className={`flex w-full items-center gap-2.5 rounded-lg px-3 text-left text-sm transition-colors ${compact ? "h-10" : "h-9"} ${
                  selected ? "bg-zinc-100 font-medium text-zinc-900" : "text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900"
                }`}
              >
                <span className={selected ? "text-zinc-900" : "text-zinc-400"}>{s.icon}</span>
                {s.label}
              </button>
            </li>
          );
        })}
      </ul>
    ));

  return (
    <section className="w-full bg-white px-4 py-12 text-zinc-900 sm:px-8">
      <div className="mx-auto max-w-5xl">
        <h2 className="text-xl font-semibold tracking-tight">내 계정</h2>
        <div className="mt-6 grid gap-6 lg:grid-cols-[200px_minmax(0,1fr)] lg:gap-10">
          <aside>
            <nav aria-label="계정 메뉴" className="hidden space-y-2 lg:block">
              {groups(false)}
            </nav>
            <div className="rounded-xl border border-zinc-300 bg-white lg:hidden">
              <button
                type="button"
                aria-expanded={open}
                onClick={() => setOpen((o) => !o)}
                className="flex h-12 w-full items-center gap-2.5 px-4 text-sm font-medium"
              >
                <span className="text-zinc-500">{current.icon}</span>
                {current.label}
                <svg
                  width="16"
                  height="16"
                  viewBox="0 0 16 16"
                  fill="none"
                  aria-hidden
                  className={`ml-auto text-zinc-500 transition-transform ${open ? "rotate-180" : ""}`}
                >
                  <path d="m4 6 4 4 4-4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
              </button>
              {open && (
                <nav aria-label="계정 메뉴" className="space-y-2 border-t border-zinc-200 p-2">
                  {groups(true)}
                </nav>
              )}
            </div>
          </aside>
          <div className="rounded-2xl border border-zinc-200 p-6">
            <h3 className="font-semibold">{current.label}</h3>
            <p className="mt-2 text-sm text-zinc-500">{current.body}</p>
          </div>
        </div>
      </div>
    </section>
  );
}

적용 사이트 0

이 블록이 실제로 쓰인 사이트입니다.

로그인하고 내 사이트 추가

아직 등록된 사이트가 없습니다. 이 블록을 쓴 사이트가 있다면 알려 주세요.

로그인하고 재현 결과 올리기

재현 후기

v1 · 0개

아직 이 버전의 프롬프트로 직접 만들어 본 사람이 없습니다. 첫 번째로 재현해 보세요.