| name | good-responsive |
| description | Use when writing or modifying mobile UI layout - screen height/width variance, fixed positioning, spacing between elements - before finalizing layout |
Mobile Layout ์์ ์ฑ
udumeoli-web์ ๋ชจ๋ฐ์ผ ๋ทฐ(MobileLayout, max-w-md) ๋จ์ผ ํ๊ฒ์ด๋ค. ์ค์ ๊ธฐ๊ธฐ๋ง๋ค ํ๋ฉด ๋์ดยท๋๋น๊ฐ ๋ค๋ฅด๊ณ , ๋ธ๋ผ์ฐ์ UI(์ฃผ์์ฐฝ)๊ฐ ์ ํ๊ณ ํผ์ณ์ง๋ฉฐ ๋ทฐํฌํธ๊ฐ ์ค์๊ฐ์ผ๋ก ๋ณํ๋ค. ๋ ์ด์์์ด "๋ด ํ๋ฉด์์๋ง ๋ง๋" ๋งค์ง ๋๋ฒ์ ๊ธฐ๋๋ฉด ๊นจ์ง๋ค.
1. ๋ทฐํฌํธ ๋์ด๋ dvh, vh ์๋
๋ชจ๋ฐ์ผ ๋ธ๋ผ์ฐ์ ๋ ์ฃผ์์ฐฝ์ด ์ ํ๊ณ ํผ์ณ์ง ๋ 100vh๊ฐ ์ค์ ๋ณด์ด๋ ์์ญ๋ณด๋ค ์ปค์ ธ ํ๋จ์ด ์๋ฆฐ๋ค.
<div className="h-screen">
<div className="h-dvh">
// ๋๋
<div className="min-h-dvh">
ํ๋ก์ ํธ ๋ด ๊ธฐ์กด ์ปจ๋ฒค์
: mobile-layout.tsx min-h-dvh, bottom-sheet.tsx h-[calc(100dvh-54px)]. ์ ์ ์ฒดํ๋ฉด/์ํธ ๋ ์ด์์๋ ์ด ํจํด์ ๋ฐ๋ฅธ๋ค.
2. ํ๋ฉด ๋์ด๊ฐ ์ค์ด๋ ์์๋ผ๋ฆฌ ๊ฒน์น๋ฉด ์ ๋๋ค
top/bottom ์ ๋ ์์น๋ฅผ ๊ฐ๊ฐ ๊ณ ์ px๋ก ๋ฐ๋ก ๋ฐฐ์นํ๋ฉด, ํ๋ฉด์ด ๋ฎ์ ๊ธฐ๊ธฐ์์ ๋ ์์๊ฐ ๊ฒน์น๋ค. ํ๋์ flex ์ปจํ
์ด๋๋ก ๋ฌถ์ด ํ๋ฆ(flow)์ ๋งก๊ธฐ๋ฉด ํ๋ฉด์ด ์ค์ด๋ ์ต์ ๊ฐ๊ฒฉ์ด ๋ณด์ฅ๋๋ค.
<span className="absolute top-[320px] left-1/2 -translate-x-1/2">
์๋ด ๋ฌธ๊ตฌ
</span>
<span className="absolute bottom-[246px] left-1/2 -translate-x-1/2">
ํ์ธ ๋ฒํผ
</span>
<span className="absolute inset-x-0 top-[320px] bottom-[246px] flex flex-col items-center justify-center gap-6">
<span>์๋ด ๋ฌธ๊ตฌ</span>
<span>ํ์ธ ๋ฒํผ</span>
</span>
์ค์ ์ฌ๋ก: ์จ๋ณด๋ฉ ์คํ
2์์ ์๋ด ๋ฌธ๊ตฌยทํ์ธ ๋ฒํผ์ด ๋ฎ์ ํ๋ฉด์์ ๊ฒน์น๋ ๋ฒ๊ทธ, flex ์ปจํ
์ด๋๋ก ๋ฌถ์ด ํด๊ฒฐ (openOnboardingOverlay.tsx, PR #84).
3. ๊ณ ์ ํญ ๋์ ๊ท ๋ฑ ๋ถ๋ฐฐ, ์ฐ์ฐํ ๋ง์ ๊ฐ ์์ฌ
gap์ผ๋ก ๊ณ ์ ํญ์ ๋์ดํ๋ฉด ์ปจํ
์ด๋ ๋๋น๊ฐ ๋ฐ๋ ๋ ํ์ชฝ์ผ๋ก ์ ๋ฆฐ๋ค. justify-between์ฒ๋ผ ์ปจํ
์ด๋ ๊ธฐ์ค ๊ท ๋ฑ ๋ถ๋ฐฐ๋ฅผ ์ฐ๋ฉด ๋๋น๊ฐ ๋ฌ๋ผ์ ธ๋ ์ ์ง๋๋ค.
<div className="flex gap-2">
{days.map((d) => <span key={d}>{d}</span>)}
</div>
<div className="flex justify-between">
{days.map((d) => <span key={d}>{d}</span>)}
</div>
className="w-full [&>*]:mx-auto"์ฒ๋ผ ์์ ์
๋ ํฐ๋ก ์ต์ง๋ก ์ค์ ์ ๋ ฌ ๋ง์ถ๋ ๋ฐฉ์์ ํน์ ํ๋ฉด ๋๋น(์: 375px)์์๋ง ์ฐ์ฐํ ๋ง์ ๋ณด์ผ ๋ฟ์ด๋ค โ ๊ทผ๋ณธ ์์ธ(๋ถ๋ฐฐ ๋ฐฉ์)์ ๊ณ ์น๋ค. ์ค์ ์ฌ๋ก: ์บ๋ฆฐ๋ ์์ผ ํ์ด ๋์ ์ปจํ
์ด๋์์ ์ ๋ฆฌ๋ ๋ฒ๊ทธ, gap-2 โ justify-between์ผ๋ก ํด๊ฒฐ (PR #75).
4. ์ฌ์ฌ์ฉ ์ปดํฌ๋ํธ๋ classNames ๋ถ๋ถ ์ค๋ฒ๋ผ์ด๋๋ฅผ cn()์ผ๋ก ๋ณํฉ
๊ณตํต ์ปดํฌ๋ํธ๊ฐ ๋ด๋ถ ์ฌ๋กฏ ํด๋์ค๋ฅผ ํธ์ถ๋ถ classNames๋ก ํต์งธ๋ก ๋ฎ์ด์ฐ๊ฒ ๋ง๋ค๋ฉด, ํธ์ถ๋ถ๋ ๋ ์ด์์ ํต์ฌ ํด๋์ค(w-full ๋ฑ)๊น์ง ์ค์๋ก ๋ ๋ฆด ์ ์๋ค. cn()์ผ๋ก ๊ธฐ๋ณธ๊ฐ๊ณผ ๋ณํฉํด ์์ ํ๊ฒ ๋ถ๋ถ ์ค๋ฒ๋ผ์ด๋๋ง ๊ฐ๋ฅํ๊ฒ ํ๋ค.
weekdays: classNames?.weekdays ?? "flex gap-2",
weekdays: cn("flex gap-2", classNames?.weekdays),
5. ์๋จ/ํ๋จ ์์ ์์ญ์ env(safe-area-inset-*) ๋ฐ์
๋
ธ์น, ํ ์ธ๋์ผ์ดํฐ, ์ค์นํ PWA ์ํ๋ฐ์ ๊ฒน์น์ง ์๋๋ก ํ๋ฉด ์ต์๋จ/์ตํ๋จ์ ๋ถ๋ ์์๋ safe-area๋ฅผ padding์ ๋ฐ์ํ๋ค.
className = "pt-[calc(env(safe-area-inset-top)_+_0.75rem)]"
์ฒดํฌ๋ฆฌ์คํธ