style(app-hub): 오늘의 공간 카드를 룸별 단색 팔레트로 전환
맥락: - 오늘의 공간 카드가 이미지 기반 배경이라 색/질감이 복잡하게 보였고, 카드와 페이지 배경의 톤 연결이 약했다. - 룸 이름별로 분리된 단색 팔레트를 사용해 카드 가독성과 허브의 색 일관성을 높일 필요가 있었다. 변경사항: - entities/room 모델에 hubColor 필드를 추가하고 10개 룸에 겹치지 않는 단색 팔레트를 정의했다. - RoomPreviewCard를 이미지 배경 대신 룸 고유 단색 배경으로 렌더링하도록 변경했다. - RoomPreviewCard 내부 텍스트/칩 스타일을 단색 카드 대비에 맞춰 어두운 텍스트 중심으로 재정렬했다. - AppHub 배경을 선택 룸의 hubColor로 동기화해 카드 선택과 페이지 배경이 같은 색 계열로 연결되게 조정했다. - 세션 문서(90_current_state, session_brief)에 이번 작업 내역과 리스크를 반영했다. 검증: - npx tsc --noEmit 세션-상태: /app 오늘의 공간 카드/허브 배경 단색 팔레트 전환 완료 세션-다음: RoomSheet/도크 패널의 인원수 기반 표현을 분위기형 정보로 전환 세션-리스크: 일부 디스플레이에서 단색 팔레트 간 체감 차이가 작아 보일 수 있어 기기별 색 분리도 점검 필요
This commit is contained in:
@@ -10,6 +10,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Rain Focus',
|
||||
recommendedTime: '밤',
|
||||
vibeLabel: '잔잔함',
|
||||
hubColor: '#D6E6F7',
|
||||
activeMembers: 32,
|
||||
presence: { focus: 23, break: 6, away: 3 },
|
||||
previewImage: '/spaces/rain-window.jpg',
|
||||
@@ -24,6 +25,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Cafe Murmur',
|
||||
recommendedTime: '새벽',
|
||||
vibeLabel: '포근함',
|
||||
hubColor: '#F5DDCB',
|
||||
activeMembers: 28,
|
||||
presence: { focus: 18, break: 7, away: 3 },
|
||||
previewImage: '/spaces/dawn-cafe.jpg',
|
||||
@@ -38,6 +40,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Deep White',
|
||||
recommendedTime: '오후',
|
||||
vibeLabel: '몰입',
|
||||
hubColor: '#DCE4D1',
|
||||
activeMembers: 41,
|
||||
presence: { focus: 31, break: 7, away: 3 },
|
||||
previewImage: '/spaces/library.jpg',
|
||||
@@ -52,6 +55,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Ocean Breath',
|
||||
recommendedTime: '밤',
|
||||
vibeLabel: '차분함',
|
||||
hubColor: '#CFE9EA',
|
||||
activeMembers: 19,
|
||||
presence: { focus: 13, break: 4, away: 2 },
|
||||
previewImage: '/spaces/ocean.jpg',
|
||||
@@ -66,6 +70,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Forest Hush',
|
||||
recommendedTime: '오전',
|
||||
vibeLabel: '맑음',
|
||||
hubColor: '#D1E7C9',
|
||||
activeMembers: 26,
|
||||
presence: { focus: 17, break: 6, away: 3 },
|
||||
previewImage: '/spaces/forest.jpg',
|
||||
@@ -80,6 +85,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Fireplace',
|
||||
recommendedTime: '밤',
|
||||
vibeLabel: '온기',
|
||||
hubColor: '#F2D4C0',
|
||||
activeMembers: 21,
|
||||
presence: { focus: 15, break: 4, away: 2 },
|
||||
previewImage: '/spaces/fireplace.jpg',
|
||||
@@ -94,6 +100,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Night Lo-fi',
|
||||
recommendedTime: '심야',
|
||||
vibeLabel: '고요함',
|
||||
hubColor: '#D9D3ED',
|
||||
activeMembers: 34,
|
||||
presence: { focus: 24, break: 7, away: 3 },
|
||||
previewImage: '/spaces/city-night.jpg',
|
||||
@@ -108,6 +115,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Cold Wind',
|
||||
recommendedTime: '새벽',
|
||||
vibeLabel: '선명함',
|
||||
hubColor: '#D8E7F3',
|
||||
activeMembers: 15,
|
||||
presence: { focus: 11, break: 3, away: 1 },
|
||||
previewImage: '/spaces/snow-mountain.jpg',
|
||||
@@ -122,6 +130,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Soft Daylight',
|
||||
recommendedTime: '오후',
|
||||
vibeLabel: '가벼움',
|
||||
hubColor: '#F6EDC7',
|
||||
activeMembers: 27,
|
||||
presence: { focus: 18, break: 6, away: 3 },
|
||||
previewImage: '/spaces/sun-window.jpg',
|
||||
@@ -136,6 +145,7 @@ export const ROOM_THEMES: RoomTheme[] = [
|
||||
recommendedSound: 'Deep Drone',
|
||||
recommendedTime: '심야',
|
||||
vibeLabel: '깊음',
|
||||
hubColor: '#D4DCF4',
|
||||
activeMembers: 23,
|
||||
presence: { focus: 17, break: 4, away: 2 },
|
||||
previewImage: '/spaces/outer-space.jpg',
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface RoomTheme {
|
||||
recommendedSound: string;
|
||||
recommendedTime: string;
|
||||
vibeLabel: string;
|
||||
hubColor: string;
|
||||
activeMembers: number;
|
||||
presence: RoomPresence;
|
||||
previewImage: string;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { RoomTheme } from '@/entities/room';
|
||||
import { getRoomBackgroundStyle } from '@/entities/room';
|
||||
import { cn } from '@/shared/lib/cn';
|
||||
|
||||
interface RoomPreviewCardProps {
|
||||
@@ -20,33 +19,29 @@ export const RoomPreviewCard = ({
|
||||
className={cn(
|
||||
'group relative overflow-hidden rounded-2xl border p-4 text-left transition-all duration-250 motion-reduce:transition-none',
|
||||
selected
|
||||
? 'border-sky-200/85 shadow-[0_0_0_1px_rgba(186,230,253,0.9)]'
|
||||
: 'border-white/18 hover:border-white/35',
|
||||
? 'border-brand-dark/28 shadow-[0_0_0_1px_rgba(48,77,109,0.18)]'
|
||||
: 'border-brand-dark/16 hover:border-brand-dark/28',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
...getRoomBackgroundStyle(room),
|
||||
filter: 'brightness(1.06) saturate(0.9)',
|
||||
backgroundColor: room.hubColor,
|
||||
}}
|
||||
/>
|
||||
<div aria-hidden className="absolute inset-0 bg-slate-900/26" />
|
||||
<div aria-hidden className="absolute inset-0 bg-[linear-gradient(to_top,rgba(2,6,23,0.62),rgba(2,6,23,0.22))]" />
|
||||
<div aria-hidden className="absolute inset-0 bg-[radial-gradient(120%_80%_at_50%_0%,rgba(255,255,255,0.18),rgba(255,255,255,0)_58%)]" />
|
||||
|
||||
<div className="relative space-y-3 rounded-xl border border-white/18 bg-slate-950/24 p-3 backdrop-blur-[1.5px]">
|
||||
<div className="relative space-y-3 rounded-xl border border-brand-dark/10 bg-white/42 p-3 backdrop-blur-[1px]">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-white">{room.name}</h3>
|
||||
<p className="mt-1 text-xs text-white/82">{room.description}</p>
|
||||
<h3 className="text-base font-semibold text-brand-dark">{room.name}</h3>
|
||||
<p className="mt-1 text-xs text-brand-dark/72">{room.description}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{room.tags.map((tag) => (
|
||||
<span
|
||||
key={tag}
|
||||
className="inline-flex items-center gap-1 rounded-full bg-white/14 px-3 py-1.5 text-xs font-medium text-white/92 ring-1 ring-white/24"
|
||||
className="inline-flex items-center gap-1 rounded-full bg-white/62 px-3 py-1.5 text-xs font-medium text-brand-dark/86 ring-1 ring-brand-dark/12"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
@@ -54,14 +49,14 @@ export const RoomPreviewCard = ({
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs text-white/84">
|
||||
추천 사운드: <span className="font-medium text-white">{room.recommendedSound}</span>
|
||||
<p className="text-xs text-brand-dark/78">
|
||||
추천 사운드: <span className="font-medium text-brand-dark">{room.recommendedSound}</span>
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-sky-300/22 px-3 py-1.5 text-xs font-medium text-sky-100 ring-1 ring-sky-200/48">
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-white/58 px-3 py-1.5 text-xs font-medium text-brand-dark/84 ring-1 ring-brand-dark/12">
|
||||
추천 시간 · {room.recommendedTime}
|
||||
</span>
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-white/13 px-3 py-1.5 text-xs font-medium text-white/92 ring-1 ring-white/22">
|
||||
<span className="inline-flex items-center gap-1 rounded-full bg-white/58 px-3 py-1.5 text-xs font-medium text-brand-dark/84 ring-1 ring-brand-dark/12">
|
||||
지금 분위기 · {room.vibeLabel}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { getRoomBackgroundStyle, ROOM_THEMES } from '@/entities/room';
|
||||
import { ROOM_THEMES } from '@/entities/room';
|
||||
import {
|
||||
GOAL_CHIPS,
|
||||
SOUND_PRESETS,
|
||||
@@ -93,23 +93,21 @@ export const AppHubWidget = () => {
|
||||
<div className="relative min-h-screen overflow-hidden text-white">
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-0 scale-[1.03] blur-[3px]"
|
||||
className="absolute inset-0 transition-colors duration-300"
|
||||
style={{
|
||||
...getRoomBackgroundStyle(selectedRoom),
|
||||
filter: 'brightness(1.12) saturate(0.82)',
|
||||
backgroundColor: selectedRoom.hubColor,
|
||||
}}
|
||||
/>
|
||||
<div aria-hidden className="absolute inset-0 bg-slate-900/14" />
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-0 bg-[radial-gradient(circle_at_14%_0%,rgba(255,255,255,0.5),transparent_45%),radial-gradient(circle_at_86%_18%,rgba(191,219,254,0.3),transparent_44%),linear-gradient(165deg,rgba(248,250,252,0.26)_0%,rgba(226,232,240,0.24)_52%,rgba(203,213,225,0.3)_100%)]"
|
||||
className="absolute inset-0 bg-[radial-gradient(circle_at_14%_0%,rgba(255,255,255,0.52),transparent_48%),radial-gradient(circle_at_86%_18%,rgba(255,255,255,0.34),transparent_46%),linear-gradient(165deg,rgba(248,250,252,0.24)_0%,rgba(226,232,240,0.2)_52%,rgba(203,213,225,0.28)_100%)]"
|
||||
/>
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-0 opacity-[0.18]"
|
||||
className="absolute inset-0 opacity-[0.12]"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url('/textures/grain.png'), repeating-linear-gradient(0deg, rgba(255,255,255,0.024) 0 1px, transparent 1px 2px)",
|
||||
"url('/textures/grain.png'), repeating-linear-gradient(0deg, rgba(255,255,255,0.02) 0 1px, transparent 1px 2px)",
|
||||
mixBlendMode: 'soft-light',
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user