nnuer
강희태@gmlxo9917

대표 색을 바꿀 수 있는 사진가 포트폴리오 프로필 헤더

콘텐츠 블록

오로라 커버, 이니셜 아바타, 소개와 링크, 숫자 통계를 담은 프로필 헤더입니다. 색 점을 누르면 커버, 아바타, 강조색이 함께 바뀝니다.

블록 신고

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

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

const ACCENTS = [
  { id: "amber", label: "앰버", a: "#fcd34d", b: "#fb923c" },
  { id: "teal", label: "틸", a: "#5eead4", b: "#38bdf8" },
  { id: "rose", label: "로즈", a: "#fda4af", b: "#e879f9" },
  { id: "violet", label: "바이올렛", a: "#a78bfa", b: "#f472b6" },
];

const mix = (c: string, p: number) => `color-mix(in srgb, ${c} ${p}%, transparent)`;

export default function PortfolioProfileHeader() {
  const [accent, setAccent] = useState(ACCENTS[0]);
  const [following, setFollowing] = useState(false);
  const cover = `radial-gradient(60% 140% at 12% 0%, ${mix(accent.a, 55)}, transparent 70%), radial-gradient(55% 120% at 88% 10%, ${mix(accent.b, 45)}, transparent 70%), #18181b`;

  return (
    <section className="w-full bg-[#09090b] px-4 py-12 text-zinc-100 sm:px-8">
      <div className="mx-auto max-w-5xl">
        <div className="overflow-hidden rounded-2xl border border-white/10 bg-[#111113]">
          <div className="relative h-36 transition-[background] duration-500 sm:h-48" style={{ background: cover }} aria-hidden>
            <div className="absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-[#111113]/70 to-transparent" />
          </div>
          <div className="px-5 pb-6 sm:px-8">
            <div className="relative -mt-12 flex flex-wrap items-end justify-between gap-4">
              <div className="rounded-full bg-[#111113] p-1">
                <span
                  className="flex h-[92px] w-[92px] items-center justify-center rounded-full text-3xl font-semibold text-zinc-900"
                  style={{ background: `linear-gradient(135deg, ${accent.a}, ${accent.b})` }}
                  aria-hidden
                >
                  윤
                </span>
              </div>
              <button
                type="button"
                onClick={() => setFollowing((f) => !f)}
                className="h-9 rounded-lg px-4 text-sm font-medium text-zinc-900 transition active:scale-[0.98]"
                style={following ? { background: "#27272a", color: "#e4e4e7" } : { background: accent.a }}
              >
                {following ? "구독 중" : "구독하기"}
              </button>
            </div>
            <p className="mt-4 text-[11px] font-semibold uppercase tracking-[0.22em]" style={{ color: accent.a }}>
              Portfolio
            </p>
            <h2 className="mt-1 text-2xl font-semibold tracking-tight sm:text-3xl">빛과 그림자 사진관</h2>
            <p className="mt-1 text-sm text-zinc-400">윤서하 · @seoha.lens · 2021년부터 활동</p>
            <p className="mt-3 max-w-2xl text-[15px] leading-relaxed text-zinc-300">
              도시의 오후 빛을 찍습니다. 필름 느낌의 보정 프리셋과 촬영 노트를 함께 올려요.
            </p>
            <ul aria-label="링크" className="mt-4 flex flex-wrap gap-2">
              {["instagram.com", "behance.net", "작업 의뢰"].map((l) => (
                <li key={l}>
                  <a
                    href="#"
                    className="inline-flex h-8 items-center gap-1.5 rounded-lg border border-white/10 bg-white/[0.04] px-3 text-[13px] text-zinc-400 transition hover:text-zinc-100"
                  >
                    <svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden style={{ color: accent.a }}>
                      <path
                        d="M6.5 9.5a3 3 0 0 0 4.24 0l2.12-2.12a3 3 0 0 0-4.24-4.24l-.7.7M9.5 6.5a3 3 0 0 0-4.24 0L3.14 8.62a3 3 0 0 0 4.24 4.24l.7-.7"
                        stroke="currentColor"
                        strokeWidth="1.4"
                        strokeLinecap="round"
                      />
                    </svg>
                    {l}
                  </a>
                </li>
              ))}
            </ul>
            <div className="mt-5 flex flex-wrap items-end justify-between gap-4">
              <dl className="flex gap-8 text-sm">
                {[
                  ["작품", 128],
                  ["구독자", 2340],
                  ["프리셋", 12],
                ].map(([label, value]) => (
                  <div key={label}>
                    <dt className="text-xs text-zinc-500">{label}</dt>
                    <dd className="mt-0.5 text-lg font-semibold tabular-nums">{Number(value).toLocaleString("ko-KR")}</dd>
                  </div>
                ))}
              </dl>
              <div role="radiogroup" aria-label="대표 색" className="flex gap-2">
                {ACCENTS.map((c) => (
                  <button
                    key={c.id}
                    type="button"
                    role="radio"
                    aria-checked={accent.id === c.id}
                    aria-label={c.label}
                    onClick={() => setAccent(c)}
                    className={`h-7 w-7 rounded-full border-2 transition-transform hover:scale-110 ${
                      accent.id === c.id ? "border-white" : "border-transparent"
                    }`}
                    style={{ background: `linear-gradient(135deg, ${c.a}, ${c.b})` }}
                  />
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

적용 사이트 0

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

로그인하고 내 사이트 추가

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

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

재현 후기

v1 · 0개

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