style(space): 스테이지 중심 첫 인상과 Setup/Focus 톤을 정리

맥락:
- /space 첫 화면이 그라데이션 안내 화면처럼 보이며 공간 서비스의 무대감이 약했습니다.
- Setup 안내 카드/상단 크롬/도크 존재감이 커서 몰입형 인상(Portal/LifeAt 톤)을 해치고 있었습니다.

변경사항:
- 배경을 실제 공간 프리뷰 이미지 우선 렌더로 전환하고, 실패 시 그라데이션 fallback만 남기도록 조정했습니다.
- 배경 오버레이를 과한 비네팅 대신 단일 규칙(얕은 읽기용 필터 + 고정 그레인)으로 정리했습니다.
- Setup 상태의 중앙 안내 카드를 제거하고, 진입 시 Setup Drawer 자동 오픈 흐름만 남겼습니다.
- Setup Drawer 헤더 안내 문구를 1줄로 축약하고 섹션을 3단(Space/Goal/Sound) 번호 체계로 고정했습니다.
- Setup 상태에서는 Drawer 닫기를 막아 설명 박스 없이도 자연스러운 입력 흐름을 유지했습니다.
- 상단 크롬을 최소화하고 Focus 상태의 Setup 열기 버튼을 약한 보조 액션으로 낮췄습니다.
- 오른쪽 도크 레일의 폭/간격/아이콘 박스를 정돈하고 Focus 기본 opacity를 낮춰 몰입 방해를 줄였습니다.

검증:
- npx tsc --noEmit
- npm run build

세션-상태: /space 첫 진입이 장면+드로어 중심으로 정리되어 설명 없이도 시작 흐름이 읽힙니다.
세션-다음: 필요 시 Setup Drawer 내부 타이포 스케일과 칩 밀도를 추가 미세 조정합니다.
세션-리스크: 외부 이미지 소스 품질 편차에 따라 장면 밝기 체감이 달라질 수 있습니다.
This commit is contained in:
2026-03-02 15:12:03 +09:00
parent 564e53fa8c
commit 78a65fa15b
5 changed files with 64 additions and 75 deletions

View File

@@ -11,6 +11,7 @@ interface SpaceSideSheetProps {
children: ReactNode;
footer?: ReactNode;
widthClassName?: string;
dismissible?: boolean;
}
export const SpaceSideSheet = ({
@@ -21,6 +22,7 @@ export const SpaceSideSheet = ({
children,
footer,
widthClassName,
dismissible = true,
}: SpaceSideSheetProps) => {
useEffect(() => {
if (!open) {
@@ -46,12 +48,16 @@ export const SpaceSideSheet = ({
return (
<>
<button
type="button"
aria-label="시트 닫기"
onClick={onClose}
className="fixed inset-0 z-40 bg-slate-950/22 backdrop-blur-[1px]"
/>
{dismissible ? (
<button
type="button"
aria-label="시트 닫기"
onClick={onClose}
className="fixed inset-0 z-40 bg-slate-950/18 backdrop-blur-[1px]"
/>
) : (
<div aria-hidden className="fixed inset-0 z-40 bg-slate-950/12 backdrop-blur-[1px]" />
)}
<aside
className={cn(
@@ -59,20 +65,22 @@ export const SpaceSideSheet = ({
widthClassName ?? 'w-[min(360px,92vw)]',
)}
>
<div className="flex h-full flex-col overflow-hidden rounded-3xl border border-white/16 bg-slate-950/68 text-white shadow-[0_24px_70px_rgba(2,6,23,0.55)] backdrop-blur-2xl">
<div className="flex h-full flex-col overflow-hidden rounded-3xl border border-white/20 bg-slate-950/58 text-white shadow-[0_20px_60px_rgba(2,6,23,0.42)] backdrop-blur-2xl">
<header className="flex items-start justify-between gap-3 border-b border-white/10 px-4 py-3 sm:px-5">
<div>
<h2 className="text-base font-semibold text-white">{title}</h2>
{subtitle ? <p className="mt-1 text-xs text-white/58">{subtitle}</p> : null}
</div>
<button
type="button"
onClick={onClose}
aria-label="닫기"
className="inline-flex h-8 w-8 items-center justify-center rounded-full border border-white/18 bg-white/8 text-sm text-white/80 transition-colors hover:bg-white/14 hover:text-white"
>
</button>
{dismissible ? (
<button
type="button"
onClick={onClose}
aria-label="닫기"
className="inline-flex h-8 w-8 items-center justify-center rounded-full border border-white/18 bg-white/8 text-sm text-white/80 transition-colors hover:bg-white/14 hover:text-white"
>
</button>
) : null}
</header>
<div className="min-h-0 flex-1 overflow-y-auto px-4 py-4 sm:px-5">{children}</div>