From 4831e2d25d83c7f5ed23d889d273078fa47a4f5a Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Wed, 30 Sep 2026 15:30:30 +0900 Subject: [PATCH 1/6] =?UTF-8?q?[fix]=20solution/site:=20=EC=82=AC=EC=A7=84?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=EB=A5=BC=20PhotoCard=20=ED=95=98=EB=82=98?= =?UTF-8?q?=EB=A1=9C=20=ED=86=B5=EC=9D=BC=20=E2=80=94=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=EB=A7=88=EB=8B=A4=20=EC=A0=9C=EA=B0=81=EA=B0=81?= =?UTF-8?q?=EC=9D=B4=EB=8D=98=20=EC=B6=95=EC=A0=9C=C2=B7=EB=AA=85=EC=86=8C?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 같은 템플릿 안에서도 축제 카드(흰 바탕·글 안쪽)와 명소 카드(바탕 없음·글 아래)가 따로 놀았다. 실측(9종 전수): 제목 굵기 400/500/700/900, 사진 모서리 0/12/18/22px 가 한 화면에 섞여 있었다. - kit/Card.tsx·card.css: 사진 3:2 + 제목 1줄 + 거리 1줄 + 설명 2줄. 템플릿 차이는 --kc-* 변수만 - 9종 Around·Festival, 고택 인물: 사진 카드를 PhotoCard 로 교체. 맛집·홈 목록 행은 그대로 - 템플릿 CSS: 모서리·글꼴·강조색 변수와 그리드 간격. 일러스트는 상자형, 빅타이포는 선 격자 - 모바일 캐러셀 화살표가 카드를 가려 1024px 미만에서 숨김 - docs/TEMPLATE_DESIGN.md: 사진 카드 규칙 tsc·eslint 통과 · vitest 123 passed · 12개 사이트 굽기 · 카드 모양 템플릿당 1종 확인 Co-Authored-By: Claude Opus 5.5 --- docs/TEMPLATE_DESIGN.md | 8 +++ solution/site/src/layouts/bigtype/Around.tsx | 18 +++++-- .../site/src/layouts/bigtype/Festival.tsx | 18 +++---- solution/site/src/layouts/bigtype/bigtype.css | 4 ++ solution/site/src/layouts/boutique/Around.tsx | 18 +++++-- .../site/src/layouts/boutique/Festival.tsx | 17 +++---- .../site/src/layouts/boutique/boutique.css | 6 +++ solution/site/src/layouts/cinema/Around.tsx | 28 +++++++--- solution/site/src/layouts/cinema/Festival.tsx | 17 +++---- solution/site/src/layouts/cinema/cinema.css | 6 +++ solution/site/src/layouts/coral/Around.tsx | 37 ++++++-------- solution/site/src/layouts/coral/coral.css | 2 + solution/site/src/layouts/graphic/Around.tsx | 17 ++++++- .../site/src/layouts/graphic/Festival.tsx | 17 +++---- solution/site/src/layouts/graphic/graphic.css | 4 ++ solution/site/src/layouts/kit/Card.tsx | 31 +++++++++++ solution/site/src/layouts/kit/card.css | 13 +++++ solution/site/src/layouts/minimal/Around.tsx | 37 ++++++-------- solution/site/src/layouts/minimal/minimal.css | 2 + solution/site/src/layouts/paper/Around.tsx | 26 ++++------ solution/site/src/layouts/paper/Festival.tsx | 20 +++----- solution/site/src/layouts/paper/Story.tsx | 51 +++++++++++-------- solution/site/src/layouts/paper/paper.css | 1 + solution/site/src/layouts/pine/Around.tsx | 21 ++++---- solution/site/src/layouts/pine/pine.css | 2 + solution/site/src/layouts/round/Around.tsx | 37 ++++++-------- solution/site/src/layouts/round/round.css | 2 + 27 files changed, 282 insertions(+), 178 deletions(-) create mode 100644 solution/site/src/layouts/kit/Card.tsx create mode 100644 solution/site/src/layouts/kit/card.css diff --git a/docs/TEMPLATE_DESIGN.md b/docs/TEMPLATE_DESIGN.md index b722e69..198ea3c 100644 --- a/docs/TEMPLATE_DESIGN.md +++ b/docs/TEMPLATE_DESIGN.md @@ -49,6 +49,14 @@ - 같은 목록의 카드는 같은 크기: 사진은 고정 비율 + `object-fit:cover`, 글은 줄 수 말줄임 - 칸 수는 항목 수에 맞춘다(`repeat(auto-fit, minmax(…))`). 3개인데 4칸을 잡아 빈칸을 남기지 않는다 +### 사진 카드는 하나다 — `layouts/kit/Card.tsx` `PhotoCard` + +- 주변 안내 · 축제 · 명소 · 인물(사진 있을 때)은 모두 `PhotoCard` 를 쓴다. 템플릿마다 카드를 새로 짓지 않는다 +- 모양: 사진(3:2) 아래에 제목 1줄 · 거리나 날짜 1줄 · 설명 2줄. 템플릿별로 다른 것은 `--kc-*` 변수만 + (`--kc-r` 사진 모서리, `--kc-tf`·`--kc-tw` 제목 글꼴·굵기, `--kc-mc` 거리 색, 상자형은 `--kc-bg`·`--kc-box-r`) +- 사진 없는 목록(맛집 · 홈 가까운 곳 목록)은 행(row)으로 쓴다. 한 섹션 안에서 카드와 행을 섞지 않는다 +- 모바일 캐러셀 화살표는 숨긴다(카드 위를 가린다). 1024px 이상에서만 사진 가운데 높이에 둔다 + ## 4. 섹션 머리 - **제목은 위, 내용은 아래.** 참고한 펜션 사이트들이 모두 이 방식이다 diff --git a/solution/site/src/layouts/bigtype/Around.tsx b/solution/site/src/layouts/bigtype/Around.tsx index 7d80daf..8058d69 100644 --- a/solution/site/src/layouts/bigtype/Around.tsx +++ b/solution/site/src/layouts/bigtype/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {Idx} from './SectionHead'; import {Tabs} from './Tabs'; @@ -66,6 +67,17 @@ export function Around() { ); + const spot = (place: LocalPlace) => ( + setOpen(place)} + /> + ); + return ( <> {rail.length > 0 && ( @@ -86,16 +98,14 @@ export function Around() {
-
    {shownSpots.slice(0, firstSpots).map((place, i) => item(place, i))}
+
{shownSpots.slice(0, firstSpots).map(spot)}
{shownSpots.length > firstSpots && (
{shownSpots.length - firstSpots}곳 더 보기 + -
    - {shownSpots.slice(firstSpots).map((place, i) => item(place, i + firstSpots))} -
+
{shownSpots.slice(firstSpots).map(spot)}
)}
diff --git a/solution/site/src/layouts/bigtype/Festival.tsx b/solution/site/src/layouts/bigtype/Festival.tsx index 30c33ef..365d1c3 100644 --- a/solution/site/src/layouts/bigtype/Festival.tsx +++ b/solution/site/src/layouts/bigtype/Festival.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {FestivalEntry} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Car} from '../paper/Car'; import {Sheet} from '../paper/Sheet'; import {Idx} from './SectionHead'; @@ -34,17 +35,12 @@ export function Festival() { arrows label="계절별 축제" slides={shown.map((f) => ( - + setOpen(f)} + /> ))} /> diff --git a/solution/site/src/layouts/bigtype/bigtype.css b/solution/site/src/layouts/bigtype/bigtype.css index ec22dfe..622673a 100644 --- a/solution/site/src/layouts/bigtype/bigtype.css +++ b/solution/site/src/layouts/bigtype/bigtype.css @@ -284,3 +284,7 @@ .w4-bigtype .ppl{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))} .w4-bigtype .amen{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}} .w4-bigtype .lead+:is(.chips,.tabrow){margin-top:20px} +.w4-bigtype{--kc-r:0;--kc-tw:500;--kc-ts:17px;--kc-mc:var(--sub);--kc-sub:var(--sub);--kc-px:12px;--kc-pb:14px} +.w4-bigtype .kgrid{gap:0;margin-top:0;border-top:1px solid var(--line);width:calc(100% + 1px);clip-path:inset(0 1px 0 0)} +.w4-bigtype .kgrid>.kcard{border-right:1px solid var(--line);border-bottom:1px solid var(--line)} +@media (min-width:1024px){.w4-bigtype .kgrid{grid-template-columns:repeat(4,minmax(0,1fr));gap:0}} diff --git a/solution/site/src/layouts/boutique/Around.tsx b/solution/site/src/layouts/boutique/Around.tsx index 7992599..62b7af1 100644 --- a/solution/site/src/layouts/boutique/Around.tsx +++ b/solution/site/src/layouts/boutique/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; const WALK = 80; @@ -70,6 +71,17 @@ export function Around() { ); + const spot = (item: LocalPlace) => ( + setOpen(item)} + /> + ); + return ( <> {rail.length > 0 && ( @@ -78,7 +90,7 @@ export function Around() {

AROUND

주변 안내

걸어서 닿는 명소와 맛집입니다.

-
{rail.slice(0, HOME_ROWS).map((item) => place(item))}
+
{rail.slice(0, HOME_ROWS).map(spot)}
지역 소개에서 모두 보기 @@ -95,11 +107,11 @@ export function Around() {

걸어서 닿는 곳부터 차로 가는 곳까지 묶었습니다.

-
{shownSpots.slice(0, firstSpots).map((item) => place(item))}
+
{shownSpots.slice(0, firstSpots).map(spot)}
{shownSpots.length > firstSpots && (
{shownSpots.length - firstSpots}곳 더 보기 -
{shownSpots.slice(firstSpots).map((item) => place(item))}
+
{shownSpots.slice(firstSpots).map(spot)}
)} diff --git a/solution/site/src/layouts/boutique/Festival.tsx b/solution/site/src/layouts/boutique/Festival.tsx index 5be93e8..0a65f39 100644 --- a/solution/site/src/layouts/boutique/Festival.tsx +++ b/solution/site/src/layouts/boutique/Festival.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {FestivalEntry} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; const SEASONS = ['봄', '여름', '가을', '겨울']; @@ -40,15 +41,13 @@ export function Festival() { )}
{shown.map((f) => ( - + setOpen(f)} + /> ))}
diff --git a/solution/site/src/layouts/boutique/boutique.css b/solution/site/src/layouts/boutique/boutique.css index 0d39ca5..2c98893 100644 --- a/solution/site/src/layouts/boutique/boutique.css +++ b/solution/site/src/layouts/boutique/boutique.css @@ -345,3 +345,9 @@ .w4-boutique[data-page=story] main .b-rule{margin-left:0;margin-right:0} .w4-boutique[data-page=story] main .shell{padding-inline:24px} .w4-boutique[data-page=story] main #reviews{margin-top:var(--sec)}} +.w4-boutique{--kc-r:999px 999px 0 0;--kc-ar:4/3;--kc-tf:var(--mj);--kc-tw:400;--kc-ts:17px;--kc-mc:var(--rose);--kc-sub:var(--sub);--kc-soft:var(--bg2)} +.w4-boutique .rail>.kcard{flex:0 0 62%;height:auto} +.w4-boutique .guide--card{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:28px 14px} +.w4-boutique #around .guide--card{grid-template-columns:repeat(3,minmax(0,1fr));gap:20px 10px} +.w4-boutique #around .kcard-t{font-size:15px} +@media (min-width:1024px){.w4-boutique .rail>.kcard{flex-basis:calc((100% - 48px) / 3)}.w4-boutique .guide--card{grid-template-columns:repeat(3,minmax(0,1fr));gap:36px 24px}} diff --git a/solution/site/src/layouts/cinema/Around.tsx b/solution/site/src/layouts/cinema/Around.tsx index c94da73..aab7044 100644 --- a/solution/site/src/layouts/cinema/Around.tsx +++ b/solution/site/src/layouts/cinema/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {useWide} from './useWide'; @@ -71,6 +72,17 @@ export function Around() { ); + const spot = (item: LocalPlace) => ( + setOpen(item)} + /> + ); + return ( <> {rail.length > 0 && ( @@ -81,11 +93,13 @@ export function Around() {

걸어서 닿는 명소와 맛집입니다.

{rail.slice(0, HOME_ROWS).map((item) => ( - + setOpen(item)} + /> ))}
@@ -104,11 +118,11 @@ export function Around() {

걸어서 닿는 곳부터 차로 가는 곳까지 묶었습니다.

-
{shownSpots.slice(0, firstSpots).map((item) => place(item))}
+
{shownSpots.slice(0, firstSpots).map(spot)}
{shownSpots.length > firstSpots && (
{shownSpots.length - firstSpots}곳 더 보기 -
{shownSpots.slice(firstSpots).map((item) => place(item))}
+
{shownSpots.slice(firstSpots).map(spot)}
)} diff --git a/solution/site/src/layouts/cinema/Festival.tsx b/solution/site/src/layouts/cinema/Festival.tsx index 5be93e8..0a65f39 100644 --- a/solution/site/src/layouts/cinema/Festival.tsx +++ b/solution/site/src/layouts/cinema/Festival.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {FestivalEntry} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; const SEASONS = ['봄', '여름', '가을', '겨울']; @@ -40,15 +41,13 @@ export function Festival() { )}
{shown.map((f) => ( - + setOpen(f)} + /> ))}
diff --git a/solution/site/src/layouts/cinema/cinema.css b/solution/site/src/layouts/cinema/cinema.css index fd9b827..5dabe93 100644 --- a/solution/site/src/layouts/cinema/cinema.css +++ b/solution/site/src/layouts/cinema/cinema.css @@ -296,3 +296,9 @@ .w4-cinema .unit .btns{grid-template-columns:1fr 1fr}} .w4-cinema .wrap>.label:has(+h2),.w4-cinema .book .label,.w4-cinema .rhead>.kicker{display:none} .w4-cinema :is(h1,h2,.big,.hl){font-family:var(--tpl-font-heading)} +.w4-cinema{--kc-r:14px;--kc-tw:600;--kc-mc:var(--accent);--kc-sub:var(--sub);--kc-soft:rgba(244,239,230,.06)} +.w4-cinema .rail>.kcard{flex:0 0 72%;height:auto} +.w4-cinema .guide--card{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 14px;border-top:0} +.w4-cinema .grid3:has(>.kcard){gap:20px 10px} +.w4-cinema .grid3>.kcard .kcard-t{font-size:15px} +@media (min-width:1024px){.w4-cinema .rail>.kcard{flex:0 0 calc((100% - 30px) / 4)}.w4-cinema .guide--card,.w4-cinema #walk .guide{grid-template-columns:repeat(4,minmax(0,1fr));gap:32px 16px}.w4-cinema #around .grid3:has(>.kcard){grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}} diff --git a/solution/site/src/layouts/coral/Around.tsx b/solution/site/src/layouts/coral/Around.tsx index 138f8c2..24e58a2 100644 --- a/solution/site/src/layouts/coral/Around.tsx +++ b/solution/site/src/layouts/coral/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {useWide} from './useWide'; @@ -66,18 +67,14 @@ export function Around() { ); const card = (place: LocalPlace) => ( - + setOpen(place)} + /> ); return ( @@ -94,15 +91,13 @@ export function Around() {
{rail.slice(0, railMax).map((place) => ( - + setOpen(place)} + /> ))}
diff --git a/solution/site/src/layouts/coral/coral.css b/solution/site/src/layouts/coral/coral.css index 12779d8..6772fee 100644 --- a/solution/site/src/layouts/coral/coral.css +++ b/solution/site/src/layouts/coral/coral.css @@ -447,3 +447,5 @@ .w4-coral #about .amen li.off .ic{color:#c2410c} .w4-coral #about .amen li.off{color:var(--sub)} .w4-coral :is(h1,h2,h3){font-family:var(--tpl-font-heading)} +.w4-coral{--kc-r:0;--kc-tw:500;--kc-mc:var(--accent);--kc-sub:var(--sub);--kc-soft:var(--alt)} +.w4-coral .cards2,.w4-coral .guide--3{row-gap:24px} diff --git a/solution/site/src/layouts/graphic/Around.tsx b/solution/site/src/layouts/graphic/Around.tsx index d13a8a2..a4c4d5e 100644 --- a/solution/site/src/layouts/graphic/Around.tsx +++ b/solution/site/src/layouts/graphic/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {SpotIcon} from './Art'; import {useWide} from './useWide'; @@ -70,6 +71,18 @@ export function Around() { ); + const spot = (place: LocalPlace) => ( + } + onClick={() => setOpen(place)} + /> + ); + return ( <>
@@ -103,11 +116,11 @@ export function Around() { const shown = spots.filter((p) => inRange(spotRange)(meters(p))); return ( <> -
{shown.slice(0, firstSpots).map((p, i) => row(p, i))}
+
{shown.slice(0, firstSpots).map(spot)}
{shown.length > firstSpots && (
{shown.length - firstSpots}곳 더 보기 -
{shown.slice(firstSpots).map((p, i) => row(p, i + firstSpots))}
+
{shown.slice(firstSpots).map(spot)}
)} diff --git a/solution/site/src/layouts/graphic/Festival.tsx b/solution/site/src/layouts/graphic/Festival.tsx index 5be93e8..0a65f39 100644 --- a/solution/site/src/layouts/graphic/Festival.tsx +++ b/solution/site/src/layouts/graphic/Festival.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {FestivalEntry} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; const SEASONS = ['봄', '여름', '가을', '겨울']; @@ -40,15 +41,13 @@ export function Festival() { )}
{shown.map((f) => ( - + setOpen(f)} + /> ))}
diff --git a/solution/site/src/layouts/graphic/graphic.css b/solution/site/src/layouts/graphic/graphic.css index 265bffd..e6a5d4c 100644 --- a/solution/site/src/layouts/graphic/graphic.css +++ b/solution/site/src/layouts/graphic/graphic.css @@ -334,3 +334,7 @@ @media(max-width:1023px){.w4-graphic #location .btns{display:grid;grid-template-columns:1fr 1fr;gap:8px} .w4-graphic #location .btns>:first-child{grid-column:1/-1} .w4-graphic #location .btns>*{white-space:nowrap;min-width:0}} +.w4-graphic{--kc-r:0;--kc-box-r:22px;--kc-bg:var(--card);--kc-shadow:0 2px 0 rgba(29,43,36,.08);--kc-px:12px;--kc-pb:14px;--kc-tf:var(--k-head);--kc-tw:400;--kc-ts:17px;--kc-mc:var(--accent);--kc-sub:var(--sub);--kc-soft:#fff1c9} +.w4-graphic .rail>.kcard{flex:0 0 72%;height:auto} +.w4-graphic .guide--card{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 14px} +@media (min-width:1024px){.w4-graphic .rail>.kcard{flex:0 0 calc((100% - 48px) / 4)}.w4-graphic .guide--card{grid-template-columns:repeat(4,minmax(0,1fr));gap:32px 16px}} diff --git a/solution/site/src/layouts/kit/Card.tsx b/solution/site/src/layouts/kit/Card.tsx new file mode 100644 index 0000000..d2e4b56 --- /dev/null +++ b/solution/site/src/layouts/kit/Card.tsx @@ -0,0 +1,31 @@ +import type {ReactNode} from 'react'; +import './card.css'; + +export function PhotoCard({ + image, + title, + meta, + desc, + fallback, + ratio, + onClick, +}: { + image?: string | null; + title: string; + meta?: string | null; + desc?: string | null; + fallback?: ReactNode; + ratio?: string; + onClick: () => void; +}) { + return ( + + ); +} diff --git a/solution/site/src/layouts/kit/card.css b/solution/site/src/layouts/kit/card.css new file mode 100644 index 0000000..ec7e615 --- /dev/null +++ b/solution/site/src/layouts/kit/card.css @@ -0,0 +1,13 @@ +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard{display:flex;flex-direction:column;width:100%;height:100%;min-width:0;margin:0;padding:0 0 var(--kc-pb,0);border:0;border-radius:var(--kc-box-r,0);overflow:hidden;background:var(--kc-bg,none);box-shadow:var(--kc-shadow,none);color:inherit;font:inherit;text-align:left;cursor:pointer;-webkit-appearance:none;appearance:none} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-ph{position:relative;display:block;width:100%;aspect-ratio:var(--kc-ar,3/2);border-radius:var(--kc-r,14px);overflow:hidden;background:var(--kc-soft,rgba(127,127,127,.1))} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-ph img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .5s ease} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard:hover .kcard-ph img{transform:scale(1.03)} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-no{display:grid;place-items:center;width:100%;height:100%;padding:0 16px;font-family:var(--kc-tf,inherit);font-size:17px;line-height:1.4;text-align:center;color:var(--kc-sub,inherit)} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-no svg{width:40px;height:40px} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-t{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;margin-top:12px;padding:0 var(--kc-px,2px);font-family:var(--kc-tf,inherit);font-size:var(--kc-ts,16px);font-weight:var(--kc-tw,600);line-height:1.45;letter-spacing:-.01em} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-m{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;margin-top:4px;padding:0 var(--kc-px,2px);font-size:14px;font-weight:500;line-height:1.5;color:var(--kc-mc,inherit)} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kcard-d{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:6px;padding:0 var(--kc-px,2px);font-size:15px;line-height:1.6;color:var(--kc-sub,inherit)} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 14px} +@media (min-width:1024px){:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .kgrid{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:32px 20px}} +:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .car--multi:has(.kcard) .arrow{top:calc(50% - 30px)} +@media (max-width:1023px){:is(.w4p,.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .car--multi:has(.kcard) .arrow{display:none}} diff --git a/solution/site/src/layouts/minimal/Around.tsx b/solution/site/src/layouts/minimal/Around.tsx index 138f8c2..24e58a2 100644 --- a/solution/site/src/layouts/minimal/Around.tsx +++ b/solution/site/src/layouts/minimal/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {useWide} from './useWide'; @@ -66,18 +67,14 @@ export function Around() { ); const card = (place: LocalPlace) => ( - + setOpen(place)} + /> ); return ( @@ -94,15 +91,13 @@ export function Around() {
{rail.slice(0, railMax).map((place) => ( - + setOpen(place)} + /> ))}
diff --git a/solution/site/src/layouts/minimal/minimal.css b/solution/site/src/layouts/minimal/minimal.css index 60891cb..bee17a2 100644 --- a/solution/site/src/layouts/minimal/minimal.css +++ b/solution/site/src/layouts/minimal/minimal.css @@ -450,3 +450,5 @@ .w4-minimal #about .amen li.off .ic{color:#c2410c} .w4-minimal #about .amen li.off{color:var(--sub)} .w4-minimal :is(h1,h2,.hl){font-family:var(--tpl-font-heading)} +.w4-minimal{--kc-r:0;--kc-tw:400;--kc-mc:var(--sub);--kc-sub:var(--sub);--kc-soft:var(--alt)} +.w4-minimal .cards2,.w4-minimal .guide--3{row-gap:28px} diff --git a/solution/site/src/layouts/paper/Around.tsx b/solution/site/src/layouts/paper/Around.tsx index f59acde..32435f9 100644 --- a/solution/site/src/layouts/paper/Around.tsx +++ b/solution/site/src/layouts/paper/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Car} from './Car'; import {Sheet} from './Sheet'; @@ -80,11 +81,7 @@ export function Around() { arrows label="주변 안내" slides={rail.map((place) => ( - + setOpen(place)} /> ))} /> @@ -104,17 +101,16 @@ export function Around() { 걸어서 닿는 곳부터 차로 가는 곳까지 묶었습니다.

-
+
{shownSpots.map((place) => ( - + setOpen(place)} + /> ))}
diff --git a/solution/site/src/layouts/paper/Festival.tsx b/solution/site/src/layouts/paper/Festival.tsx index ae618d5..31b2b28 100644 --- a/solution/site/src/layouts/paper/Festival.tsx +++ b/solution/site/src/layouts/paper/Festival.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {FestivalEntry} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Car} from './Car'; import {Sheet} from './Sheet'; @@ -48,19 +49,12 @@ export function Festival() { arrows label="계절별 축제" slides={shown.map((f) => ( - + setOpen(f)} + /> ))} /> diff --git a/solution/site/src/layouts/paper/Story.tsx b/solution/site/src/layouts/paper/Story.tsx index 914b2a9..0e75343 100644 --- a/solution/site/src/layouts/paper/Story.tsx +++ b/solution/site/src/layouts/paper/Story.tsx @@ -2,6 +2,7 @@ import {useState, type ReactNode} from 'react'; import type {ChronicleItem, PeopleItem, ReadingItem, SongItem} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {sectionItems, sectionName} from '@site/lib/derive'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from './Sheet'; const COUNT_WORD: Record = {1: '한', 2: '두', 3: '세', 4: '네'}; @@ -60,27 +61,35 @@ export function Story() { {item.year && {item.year}} ); - const person = (item: PeopleItem) => ( - - ); + const person = (item: PeopleItem) => { + const show = () => + setOpen({ + title: item.name, + meta: [item.role, item.years].filter(Boolean).join(' · '), + body: item.oneLine, + image: item.imageUrl, + }); + if (item.imageUrl) + return ( + + ); + return ( + + ); + }; const event = (item: ChronicleItem) => ( + setOpen(place)} + /> ); return ( diff --git a/solution/site/src/layouts/pine/pine.css b/solution/site/src/layouts/pine/pine.css index c87e496..43b77be 100644 --- a/solution/site/src/layouts/pine/pine.css +++ b/solution/site/src/layouts/pine/pine.css @@ -450,3 +450,5 @@ .w4-pine #location .loc .map{aspect-ratio:auto;height:100%;min-height:320px} .w4-pine #location .loc .bd{align-self:center;padding:28px} .w4-pine #festival .car--multi .slide{flex:0 0 260px}} +.w4-pine{--kc-r:14px;--kc-tw:600;--kc-mc:var(--pine);--kc-sub:var(--sub);--kc-soft:var(--alt)} +.w4-pine .cards2{row-gap:24px} diff --git a/solution/site/src/layouts/round/Around.tsx b/solution/site/src/layouts/round/Around.tsx index 0fd2043..0b8db50 100644 --- a/solution/site/src/layouts/round/Around.tsx +++ b/solution/site/src/layouts/round/Around.tsx @@ -2,6 +2,7 @@ import {useState} from 'react'; import type {LocalPlace} from '@o2o/shared'; import {useSite} from '@site/lib/site-context'; import {naverMapSearchUrl} from '@site/lib/format'; +import {PhotoCard} from '../kit/Card'; import {Sheet} from '../paper/Sheet'; import {useWide} from './useWide'; @@ -66,18 +67,14 @@ export function Around() { ); const card = (place: LocalPlace) => ( - + setOpen(place)} + /> ); return ( @@ -94,15 +91,13 @@ export function Around() {
{rail.slice(0, railMax).map((place) => ( - + setOpen(place)} + /> ))}
diff --git a/solution/site/src/layouts/round/round.css b/solution/site/src/layouts/round/round.css index 5e11270..f585c11 100644 --- a/solution/site/src/layouts/round/round.css +++ b/solution/site/src/layouts/round/round.css @@ -337,3 +337,5 @@ .w4-round #about .amen li.on .ic{color:#15803d} .w4-round #about .amen li.off .ic{color:#c2410c} .w4-round #about .amen li.off{color:var(--sub)} +.w4-round{--kc-r:var(--r-card);--kc-tw:700;--kc-mc:var(--accent);--kc-sub:var(--sub);--kc-soft:var(--alt)} +.w4-round .cards2,.w4-round .guide--3{row-gap:24px} From 865eb0cc778581d18aca7752d405b2f582ed5a0a Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Wed, 30 Sep 2026 15:40:03 +0900 Subject: [PATCH 2/6] =?UTF-8?q?[fix]=20solution/site:=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=C2=B7=EC=98=88=EC=95=BD=20=EC=B0=BD=EC=9D=84=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EA=B0=80=EC=9A=B4=EB=8D=B0=EB=A1=9C=20=E2=80=94=20?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=ED=8F=AD=EC=97=90=EC=84=9C=20=EB=B0=94?= =?UTF-8?q?=EB=8B=A5=EC=97=90=20=EB=B6=99=EB=8D=98=20=EC=8B=9C=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 9종이 함께 쓰는 Sheet 가 stay2 모바일 시안의 하단 시트를 그대로 옮긴 것이라 데스크톱에서도 640px 판이 화면 바닥에 붙어 떴다. - kit.css·paper.css: .sheet 를 가운데 정렬, .sbox 폭 560px·높이 100svh-48px, 모서리는 템플릿 --k-r - kit.css: 라운드·코랄·미니멀·솔숲 예약 창(.sheetbody)에 여백이 없어 글자가 창 끝에 붙던 것 - docs/TEMPLATE_DESIGN.md: 창 위치 규칙 eslint 통과 · vitest 123 passed · 9종 모바일·1440px 에서 위아래·좌우 여백 같음 확인 Co-Authored-By: Claude Opus 5.5 --- docs/TEMPLATE_DESIGN.md | 1 + solution/site/src/layouts/kit/kit.css | 10 +++++----- solution/site/src/layouts/paper/paper.css | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/TEMPLATE_DESIGN.md b/docs/TEMPLATE_DESIGN.md index 198ea3c..570ec78 100644 --- a/docs/TEMPLATE_DESIGN.md +++ b/docs/TEMPLATE_DESIGN.md @@ -99,6 +99,7 @@ - 같은 동작은 한 이름: 예약 시트를 여는 버튼은 모두 **‘예약하기’**, 이용안내 탭으로 가는 버튼은 **‘이용안내 보기’** - 버튼 글자가 두 줄로 접히면 안 된다. 모바일에서 버튼이 3개 이상이면 2열 격자로, 남는 하나는 한 줄 전체 - 키보드 포커스와 글자 선택색은 템플릿 색으로(`kit/kit.css`) +- 상세·예약 창(`paper/Sheet.tsx`)은 모든 폭에서 **화면 가운데** 뜬다. 폭 560px 이하, 모서리는 템플릿의 `--k-r` ## 8. 하지 않는 것 diff --git a/solution/site/src/layouts/kit/kit.css b/solution/site/src/layouts/kit/kit.css index 4561a61..b778c90 100644 --- a/solution/site/src/layouts/kit/kit.css +++ b/solution/site/src/layouts/kit/kit.css @@ -1,8 +1,8 @@ :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine){--k-pad:20px;--k-wide:640px;--k-r:12px;--k-soft:rgba(127,127,127,.08);--k-line:rgba(127,127,127,.22);--k-head:inherit} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) *{box-sizing:border-box} -:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sbox{border-radius:20px 20px 0 0} -:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sform{padding:22px var(--k-pad) 8px} -:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sform h3{margin:0 0 16px;font-family:var(--k-head);font-size:21px;font-weight:600} +:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sbox{border-radius:var(--k-r)} +:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) :is(.sform,.sheetbody){padding:22px var(--k-pad) 8px} +:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) :is(.sform,.sheetbody) h3{margin:0 0 16px;font-family:var(--k-head);font-size:21px;font-weight:600} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sheet .cta,:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sform button.cta{display:flex;align-items:center;justify-content:center;width:100%;height:52px;border:0;border-radius:var(--k-r);background:var(--k-ink);color:var(--k-bg);font:inherit;font-size:16px;font-weight:700;cursor:pointer} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sform input,:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sform textarea{width:100%;padding:12px 14px;border:1px solid var(--k-line);border-radius:var(--k-r);background:transparent;color:var(--k-ink);font:inherit;font-size:16px} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .car{position:relative} @@ -48,10 +48,10 @@ :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .car .dots button.on{width:18px;border-radius:999px;background:var(--k-ink)} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) details>summary{list-style:none;cursor:pointer} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) details>summary::-webkit-details-marker{display:none} -:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sheet{position:fixed;inset:0;z-index:40} +:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sheet{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:24px 16px} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sheet[hidden]{display:none} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sbg{position:absolute;inset:0;background:rgba(14,13,10,.52)} -:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sbox{position:absolute;left:0;right:0;bottom:0;max-width:var(--k-wide);margin:0 auto; max-height:88svh;overflow:auto;background:var(--k-bg);padding:0 0 32px; -webkit-overflow-scrolling:touch} +:is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sbox{position:relative;width:100%;max-width:560px;margin:0 auto; max-height:calc(100svh - 48px);overflow:auto;background:var(--k-bg);padding:0 0 32px; -webkit-overflow-scrolling:touch} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sx{position:sticky;top:0;float:right;width:48px;height:48px;border:0;background:none; font-size:22px;line-height:1;color:var(--k-ink);cursor:pointer;z-index:1} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sin{padding-top:16px} :is(.w4-round,.w4-cinema,.w4-bigtype,.w4-boutique,.w4-graphic,.w4-coral,.w4-minimal,.w4-pine) .sin img{margin:0 0 18px} diff --git a/solution/site/src/layouts/paper/paper.css b/solution/site/src/layouts/paper/paper.css index 084f5f3..973bc55 100644 --- a/solution/site/src/layouts/paper/paper.css +++ b/solution/site/src/layouts/paper/paper.css @@ -255,10 +255,10 @@ @supports(padding:max(0px)){ .w4p .bar{height:calc(var(--bar) + env(safe-area-inset-bottom)); padding-bottom:calc(9px + env(safe-area-inset-bottom))} } -.w4p .sheet{position:fixed;inset:0;z-index:40} +.w4p .sheet{position:fixed;inset:0;z-index:40;display:flex;align-items:center;justify-content:center;padding:24px 16px} .w4p .sheet[hidden]{display:none} .w4p .sbg{position:absolute;inset:0;background:rgba(14,13,10,.52)} -.w4p .sbox{position:absolute;left:0;right:0;bottom:0;max-width:var(--wide);margin:0 auto; max-height:88svh;overflow:auto;background:var(--paper);padding:0 0 32px; -webkit-overflow-scrolling:touch} +.w4p .sbox{position:relative;width:100%;max-width:560px;margin:0 auto; max-height:calc(100svh - 48px);border-radius:8px;overflow:auto;background:var(--paper);padding:0 0 32px; -webkit-overflow-scrolling:touch} .w4p .sx{position:sticky;top:0;float:right;width:48px;height:48px;border:0;background:none; font-size:22px;line-height:1;color:var(--ink);cursor:pointer;z-index:1} .w4p .sin{padding-top:16px} .w4p .sin img{margin:0 0 18px} From 7a7f00dd15eae8f4c029f0298080b620ce88954e Mon Sep 17 00:00:00 2001 From: Mina Choi Date: Wed, 30 Sep 2026 15:47:57 +0900 Subject: [PATCH 3/6] =?UTF-8?q?[fix]=20solution/site:=20=EC=B2=AB=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=ED=83=9C=EA=B7=B8=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=C2=B7=EC=86=8C=EB=AC=B8=EA=B5=AC=20=EA=B3=B5=ED=86=B5=ED=99=94?= =?UTF-8?q?=20=E2=80=94=20=EB=B6=80=ED=8B=B0=ED=81=AC=20=EB=AA=A8=EB=B0=94?= =?UTF-8?q?=EC=9D=BC=EB=8F=84=20=EB=AC=B8=20=EB=AA=A8=EC=96=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 라운드·코랄·미니멀·솔숲: 히어로의 ‘주차 가능’ 칩 삭제. 일러스트: 지역 말풍선 삭제 - kit/heroSub.ts: 소문구 = 사장님 문구, 없으면 가장 가까운 명소까지 거리. 솔숲에만 있던 규칙을 9종 공통으로 - 고택·부티크: 캐치프레이즈 아래로 소문구 순서 변경 - 부티크 모바일: 전체화면 사진(664px)을 데스크톱과 같은 아치로 — 첫 화면 593px - docs/TEMPLATE_DESIGN.md: 첫 화면 규칙 tsc·eslint 통과 · vitest 123 passed · 9종 모바일·1440px 첫 화면 캡처 확인 Co-Authored-By: Claude Opus 5.5 --- docs/TEMPLATE_DESIGN.md | 4 ++++ solution/site/src/layouts/bigtype/Hero.tsx | 4 +++- solution/site/src/layouts/boutique/Hero.tsx | 5 +++-- .../site/src/layouts/boutique/boutique.css | 13 +++++++++++++ solution/site/src/layouts/cinema/Hero.tsx | 3 ++- solution/site/src/layouts/coral/Hero.tsx | 16 ++++------------ solution/site/src/layouts/graphic/Hero.tsx | 6 +++--- solution/site/src/layouts/kit/heroSub.ts | 10 ++++++++++ solution/site/src/layouts/minimal/Hero.tsx | 16 ++++------------ solution/site/src/layouts/paper/Hero.tsx | 5 +++-- solution/site/src/layouts/pine/Hero.tsx | 18 +++--------------- solution/site/src/layouts/round/Hero.tsx | 16 ++++------------ 12 files changed, 56 insertions(+), 60 deletions(-) create mode 100644 solution/site/src/layouts/kit/heroSub.ts diff --git a/docs/TEMPLATE_DESIGN.md b/docs/TEMPLATE_DESIGN.md index 570ec78..6125d3d 100644 --- a/docs/TEMPLATE_DESIGN.md +++ b/docs/TEMPLATE_DESIGN.md @@ -85,6 +85,10 @@ ## 6. 값 보여주기 +- **첫 화면은 캐치프레이즈 → 그 아래 소문구.** 소문구는 사장님 문구, 없으면 가장 가까운 명소까지 거리(`kit/heroSub.ts`) +- 첫 화면에 태그·칩(‘주차 가능’, 지역 말풍선)을 두지 않는다 +- 부티크 첫 화면은 모바일도 문(아치) 모양이다. 전체화면 사진으로 되돌리지 않는다 + - **‘가능 · 있음’은 ✓, ‘불가 · 없음’은 ✕ 목록으로 쓴다.** `주차 / 가능` 같은 표로 쓰지 않는다 - 마크업: `
  • ✓주차 가능
  • ` - 색: ✓ `#15803d`, ✕ `#c2410c`. 가능한 것을 먼저 놓는다 diff --git a/solution/site/src/layouts/bigtype/Hero.tsx b/solution/site/src/layouts/bigtype/Hero.tsx index fda639b..2fb7df6 100644 --- a/solution/site/src/layouts/bigtype/Hero.tsx +++ b/solution/site/src/layouts/bigtype/Hero.tsx @@ -2,6 +2,7 @@ import {PlaceCategory} from '@o2o/shared'; import {HeroCatchphrase} from '@site/sections/HeroCatchphrase'; import {useSite} from '@site/lib/site-context'; import {bookingActionLabel, bookingLinks, isSectionEnabled, stayBookingView} from '@site/lib/derive'; +import {heroSub} from '../kit/heroSub'; import {BOOK_EVENT} from '../paper/Rooms'; import {Weather} from './Weather'; @@ -12,6 +13,7 @@ export function Hero() { .filter((image) => image.alt?.trim()) .sort((a, b) => Number(b.isPrimary) - Number(a.isPrimary)); const fixed = narrative.tagline ?? narrative.heroSubline; + const sub = heroSub(payload); const lodging = place.category === PlaceCategory.LODGING; const stay = lodging ? stayBookingView(payload) : null; const link = bookingLinks(payload)[0]; @@ -29,7 +31,7 @@ export function Hero() { 오늘의 문장

    {(lodging || fixed) &&

    {lodging ? : fixed}

    } - {lodging && fixed &&

    {fixed}

    } + {lodging && sub &&

    {sub}

    }
    {stay ? (
    {isSectionEnabled(payload, 'weather') && ( diff --git a/solution/site/src/layouts/pine/Hero.tsx b/solution/site/src/layouts/pine/Hero.tsx index f66360a..6c749f5 100644 --- a/solution/site/src/layouts/pine/Hero.tsx +++ b/solution/site/src/layouts/pine/Hero.tsx @@ -1,7 +1,8 @@ import {PlaceCategory} from '@o2o/shared'; import {HeroCatchphrase} from '@site/sections/HeroCatchphrase'; import {useSite} from '@site/lib/site-context'; -import {bookingActionLabel, bookingLinks, heroFacts, isSectionEnabled, stayBookingView} from '@site/lib/derive'; +import {bookingActionLabel, bookingLinks, isSectionEnabled, stayBookingView} from '@site/lib/derive'; +import {heroSub} from '../kit/heroSub'; import {Car} from '../paper/Car'; import {BOOK_EVENT} from '../paper/Rooms'; import {Weather} from './Weather'; @@ -18,13 +19,9 @@ export function Hero() { const fixed = narrative.tagline ?? narrative.heroSubline; const lodging = place.category === PlaceCategory.LODGING; const region = place.addressLocality ?? place.addressRegion; - const nearest = [...payload.local.attractions] - .filter((spot) => spot.distanceText) - .sort((a, b) => (a.distanceMeters ?? Infinity) - (b.distanceMeters ?? Infinity))[0]; - const sub = fixed ?? (nearest ? `${nearest.name}까지 ${nearest.distanceText}` : undefined); + const sub = heroSub(payload); const booking = bookingLinks(payload)[0]; const stay = lodging ? stayBookingView(payload) : null; - const chips = heroFacts(payload).map((row) => `${row.label} ${row.value}`); return ( <> @@ -61,15 +58,6 @@ export function Hero() { fixed &&

    {fixed}

    )} {lodging && sub &&

    {sub}

    } - {chips.length > 0 && ( -
    - {chips.map((chip) => ( - - {chip} - - ))} -
    - )}
    {stay ? (
    {isSectionEnabled(payload, 'weather') && ( diff --git a/solution/site/src/layouts/pine/Hero.tsx b/solution/site/src/layouts/pine/Hero.tsx index 6c749f5..900616f 100644 --- a/solution/site/src/layouts/pine/Hero.tsx +++ b/solution/site/src/layouts/pine/Hero.tsx @@ -1,8 +1,7 @@ import {PlaceCategory} from '@o2o/shared'; -import {HeroCatchphrase} from '@site/sections/HeroCatchphrase'; +import {HeroCatchphrase, HeroRotator} from '@site/sections/HeroCatchphrase'; import {useSite} from '@site/lib/site-context'; import {bookingActionLabel, bookingLinks, isSectionEnabled, stayBookingView} from '@site/lib/derive'; -import {heroSub} from '../kit/heroSub'; import {Car} from '../paper/Car'; import {BOOK_EVENT} from '../paper/Rooms'; import {Weather} from './Weather'; @@ -19,7 +18,6 @@ export function Hero() { const fixed = narrative.tagline ?? narrative.heroSubline; const lodging = place.category === PlaceCategory.LODGING; const region = place.addressLocality ?? place.addressRegion; - const sub = heroSub(payload); const booking = bookingLinks(payload)[0]; const stay = lodging ? stayBookingView(payload) : null; @@ -57,7 +55,7 @@ export function Hero() { ) : ( fixed &&

    {fixed}

    )} - {lodging && sub &&

    {sub}

    } +
    {stay ? (