diff --git a/docs/conventions/wds-component-usage.md b/docs/conventions/wds-component-usage.md
index a27dd77..16f817c 100644
--- a/docs/conventions/wds-component-usage.md
+++ b/docs/conventions/wds-component-usage.md
@@ -378,6 +378,39 @@ WDS는 `useToast` 훅 + `Toast` 컴포넌트로 토스트 시스템을 완비하
- **`PaginationDots`는 부모 flex 컨테이너에 `items-center`가 없으면 왼쪽으로 붙는다**: 이 컴포넌트의 실제 루트(`tabindex` wrapper div)는 `className`/`sx` prop이 그 div까지 전달되지 않아 직접 센터링을 줄 수 없다(내부 tablist는 `width: fit-content`). `flex-col` 부모에 `items-center`를 주고, 형제 요소(캐러셀 스크롤 행)에는 `w-full`을 명시해서 폭을 유지해야 정확히 중앙에 온다 — `/figma-check`로 실측하다 발견된 버그.
- **`bg-background-alternative`(`#f7f7f8`)는 흰 배경과 3/255밖에 차이가 안 나서 화면에 따라 거의 안 보일 수 있다**: Q&A 카드 배경·8px 섹션 구분선 둘 다 이 값인데, 개별 레이어 단위로 `get_variable_defs`를 다시 떼어봐도 이 값 하나만 바인딩돼 있고 다른 색·테두리는 없었다 — 코드가 Figma 값을 정확히 따르고 있는 게 확인됐다. 그럼에도 시각적 구분이 약하다고 느껴지면, Figma 스펙을 벗어나 더 진한 톤(예: `Line/Normal/Neutral` `#70737c29`)으로 의도적으로 조정할지는 별도 논의 필요 — 이번 PR에서는 Figma 값 그대로 두었다.
+## 사물함 신청 전 유의사항 바텀시트(`1737:218213`) 구현 중 확정된 매핑
+
+이 시트에서 WDS는 `ActionArea`/`ActionAreaButton`/`Typography`뿐이다. 제목·유의사항 3줄은 전부 Stream 로컬이다.
+
+- **`Notice Item`(`1417:56435` 계열)은 Stream 로컬**: `get_design_context`의 Component descriptions에 아예 잡히지 않았다. 42px 일러스트 + `[라벨 Label 1/Normal - Regular / 값 Body 2/Normal - Medium]` 두 줄 조합이며, 사물함 전용이 아닐 수 있어 보이지만 재사용처가 아직 없어서 `component-convention.md` §1대로 `features/lockers/`에 뒀다. 두 번째 화면에서 실제로 쓰이면 `components/ui/`로 옮긴다.
+- **유의사항 일러스트 3개(시계 `1417:56488`, 사람 `1417:56599`, 달력 `1417:56600`)도 WDS 아이콘이 아니다**: `download_assets`의 `export`로 받으면 셋 다 42×42 단일 SVG로 떨어진다. 특히 달력은 `get_design_context` 응답에서 배경 SVG + 도형 6개(`#e7f1ff`/`#2c88fe`/`#b3d0f7` 하드코딩) 조합으로 나와서 손으로 그려야 하나 싶지만, **노드 단위 `export`를 쓰면 한 장으로 받아진다** — 도형을 다시 그리지 말 것. `src/assets/icons/lockers/`에 커밋했다.
+- **`download_assets`의 `export`는 캔버스 배경까지 같이 굽는다**: 받은 SVG 맨 앞에 ``(Figma 캔버스 회색)와 뷰박스 밖으로 뻗는 페이지·섹션 배경 path(``, ``)가 들어 있었다. 그대로 쓰면 동그란 아이콘 뒤에 **회색 네모**가 깔린다. 실제 아이콘은 `` 하위(배경 원 `Ellipse 11` + 글리프)뿐이라 그 그룹만 남기고 걷어냈다(2.7KB → 1.0KB). **다시 export하면 같은 정리가 필요하다.**
+- **타이포 실측**: 제목은 `heading2`+`bold`(20px/28), 항목 라벨은 `label1`+`regular`(14px/20), 항목 값은 `body2`+`medium`(15px/22)로 Figma와 정확히 일치한다(`typography/style.js` 확인). `heading2`(20px)와 `headline2`(17px)를 혼동하지 않는다.
+
+### 시트 상단 간격은 Figma가 시트마다 다르다 — `BottomSheet`의 `contentGap`
+
+드래그 핸들(24px) 다음 내용이 시작하는 위치가 시트마다 다르다.
+
+| Figma | 내용 시작 y | 간격 |
+|---|---|---|
+| 빌릴게 대여 `1422:57178` | 32 | 8px |
+| 빌릴게 대여(시간 외) `1422:57209` | 32 | 8px |
+| 사물함 유의사항 `1737:218308` | 36 | **12px** |
+
+`BottomSheet`가 빌릴게 기준 8px을 하드코딩하고 있어서 사물함 시트가 4px 짧게 나왔다(시트 상단→제목 실측 37px, Figma 41px). 공용 컴포넌트를 한쪽 값으로 고정할 수 없어 `contentGap?: 8 | 12` prop으로 빼고 기본값을 8(빌릴게 기존 동작)로 뒀다. 사물함 시트만 `contentGap={12}`를 넘긴다 — 수정 후 실측 41px로 일치.
+
+**새 시트를 만들 때 이 값을 Figma에서 먼저 확인한다.** 8/12 외 값이 나오면 `BottomSheetContentGap` 유니온에 추가한다.
+
+### Action Area 메인 버튼 높이 보정은 `paddingBlock`으로 통일한다
+
+같은 56px 보정이 코드에 두 형태로 섞여 있었다 — 행사 화면 3곳은 `sx={{ paddingBlock: "16px" }}`, `BililgeRentalSheet.tsx:176`은 `sx={{ height: "56px" }}`다.
+
+**`paddingBlock` 쪽이 맞다.** Figma 스펙이 `padding: 16px 28px`이라 그대로 옮기는 형태이고, 높이를 고정하면 버튼 문구가 길어져 줄바꿈될 때 잘린다. 이 시트는 신청 기간이 아닐 때 문구가 `신청 기간이 아니에요`로 길어져서 실제로 걸릴 수 있는 자리다. `BililgeRentalSheet`도 정리 대상이다(이번 범위 밖).
+
+### 신청 기간이 아닐 때의 상태는 Figma에 없다
+
+하단 `확인했어요` 버튼을 `disabled`로 두고 문구를 `신청 기간이 아니에요`로 바꾸기로 코드에서 정했다. 유의사항 3줄은 그대로 둔다. 디자인에 없는 상태를 만든 것이라 디자이너 확인이 필요하다 — `docs/plans/#68-lockers-notice-sheet.md` 참고.
+
## 열린피드백 상세페이지 · 모아보기(`1410:49988`) 구현 중 확정된 매핑
같은 회차(round)의 답변된 피드백들을 가로로 스와이프해서 넘겨보는 화면. Figma는 정적 예시 한 장만 있어서(신청 폼·행사 상세처럼 스크롤 스냅 캐러셀은 화면에 안 잡힌다), 구조는 공지·행사 상세의 가로 스크롤 스냅 패턴을 그대로 가져오고, "스와이프하는 동안 진행 바가 같이 움직인다"는 요구사항은 스크롤 위치를 0~1 연속값으로 추적해서 반영했다.
diff --git a/src/app/router.tsx b/src/app/router.tsx
index ecd7f58..db1d4cd 100644
--- a/src/app/router.tsx
+++ b/src/app/router.tsx
@@ -16,6 +16,7 @@ import FeedbacksDetailScreen from "@/features/feedbacks/FeedbacksDetailScreen";
import FeedbacksListScreen from "@/features/feedbacks/FeedbacksListScreen";
import FeedbacksNewScreen from "@/features/feedbacks/FeedbacksNewScreen";
import HomeScreen from "@/features/home/HomeScreen";
+import LockersApplyScreen from "@/features/lockers/LockersApplyScreen";
import NoticesDetailScreen from "@/features/notices/NoticesDetailScreen";
import NoticesListScreen from "@/features/notices/NoticesListScreen";
@@ -105,6 +106,11 @@ const routes = [
} satisfies ScreenRouteHandle,
path: "/notices/:noticeId",
},
+ {
+ element: ,
+ // 사물함 유의사항 시트 확인용 임시 라우트 — 실제 진입점이 붙으면 화면과 함께 지운다
+ path: "/lockers/apply",
+ },
{
element: ,
// Figma 챗봇 진입 화면에는 Bottom Nav가 없다(뒤로가기로 홈에 복귀). 흰 배경 위에
diff --git a/src/assets/icons/lockers/apply-period.svg b/src/assets/icons/lockers/apply-period.svg
new file mode 100644
index 0000000..c8a787a
--- /dev/null
+++ b/src/assets/icons/lockers/apply-period.svg
@@ -0,0 +1,24 @@
+
diff --git a/src/assets/icons/lockers/one-per-person.svg b/src/assets/icons/lockers/one-per-person.svg
new file mode 100644
index 0000000..be0297d
--- /dev/null
+++ b/src/assets/icons/lockers/one-per-person.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/assets/icons/lockers/usage-period.svg b/src/assets/icons/lockers/usage-period.svg
new file mode 100644
index 0000000..ceb0355
--- /dev/null
+++ b/src/assets/icons/lockers/usage-period.svg
@@ -0,0 +1,14 @@
+
diff --git a/src/components/ui/BottomSheet.tsx b/src/components/ui/BottomSheet.tsx
index bff3859..f976512 100644
--- a/src/components/ui/BottomSheet.tsx
+++ b/src/components/ui/BottomSheet.tsx
@@ -3,16 +3,31 @@ import { createPortal } from "react-dom";
import { useScreenSheetPortal } from "@/components/ui/useScreenSheetPortal";
+// 드래그 핸들(24px)과 내용 사이 간격. Figma가 시트마다 다르게 잡아둬서 화면이 고른다 —
+// 빌릴게 대여(`1422:57178`, `1422:57209`)는 8px, 사물함 유의사항(`1737:218308`)은 12px이다.
+type BottomSheetContentGap = 8 | 12;
+
+const CONTENT_GAP_CLASS_NAMES: Record = {
+ 8: "mb-2",
+ 12: "mb-3",
+};
+
interface BottomSheetProps {
open: boolean;
onClose: () => void;
+ contentGap?: BottomSheetContentGap;
children: ReactNode;
}
// Figma: Views / Bottom Sheets (nodeId 1422:57176) — WDS에는 대응하는 코드 컴포넌트가 없다
// (component-convention.md 참고: Native / Bottom Sheet Indicator는 Stream/iOS 목업 전용 로컬 요소).
// 딤+시트를 ScreenLayout의 포털 슬롯(useScreenSheetPortal)에 그려서 화면 컬럼 전체를 덮는다.
-function BottomSheet({ open, onClose, children }: BottomSheetProps) {
+function BottomSheet({
+ open,
+ onClose,
+ contentGap = 8,
+ children,
+}: BottomSheetProps) {
const portalEl = useScreenSheetPortal();
if (!portalEl) {
@@ -38,7 +53,9 @@ function BottomSheet({ open, onClose, children }: BottomSheetProps) {
open ? "translate-y-0" : "translate-y-full"
}`}
>
-
+
{children}
diff --git a/src/features/lockers/LockersApplyScreen.tsx b/src/features/lockers/LockersApplyScreen.tsx
new file mode 100644
index 0000000..5147c13
--- /dev/null
+++ b/src/features/lockers/LockersApplyScreen.tsx
@@ -0,0 +1,45 @@
+import { Button, Typography } from "@wanteddev/wds";
+import { useState } from "react";
+
+import LockersNoticeSheet from "@/features/lockers/components/LockersNoticeSheet";
+
+// 임시 확인용 화면 — 시트를 띄울 진입점이 아직 없어서 둔 자리다.
+// 실제 진입점(홈 "사물함 상태" 퀵링크 `1737:218284` 또는 공지 상세 CTA)이 붙으면
+// 이 화면과 /lockers/apply 라우트는 지운다. docs/plans/#68-lockers-notice-sheet.md 참고.
+function LockersApplyScreen() {
+ const [isOpen, setIsOpen] = useState(false);
+ // 시트는 닫아도 380ms 동안 미끄러져 내려간다. 기간 여부를 open과 같은 state에서 파생시키면
+ // 그 사이 버튼이 비활성 문구로 바뀌는 게 보이므로, 닫을 때는 open만 끄고 이 값은 유지한다.
+ const [isApplyPeriod, setIsApplyPeriod] = useState(true);
+
+ const openSheet = (applyPeriod: boolean) => {
+ setIsApplyPeriod(applyPeriod);
+ setIsOpen(true);
+ };
+
+ return (
+
+
+ 사물함 유의사항 시트 확인용 임시 화면
+
+
+
+
+ setIsOpen(false)}
+ // 확인 후 이동할 사물함 구역 선택 화면(1737:218452)은 다음 이슈라 지금은 닫기만 한다
+ onConfirm={() => setIsOpen(false)}
+ open={isOpen}
+ />
+
+ );
+}
+
+export default LockersApplyScreen;
diff --git a/src/features/lockers/components/LockersNoticeSheet.tsx b/src/features/lockers/components/LockersNoticeSheet.tsx
new file mode 100644
index 0000000..ba1e3ba
--- /dev/null
+++ b/src/features/lockers/components/LockersNoticeSheet.tsx
@@ -0,0 +1,83 @@
+import { ActionArea, ActionAreaButton, Typography } from "@wanteddev/wds";
+
+import BottomSheet from "@/components/ui/BottomSheet";
+import { LOCKERS_NOTICE_ITEMS } from "@/features/lockers/constants/lockersNotice";
+
+interface LockersNoticeSheetProps {
+ open: boolean;
+ /** 지금이 사물함 신청 기간인지. 아니면 하단 버튼이 잠기고 문구가 바뀐다. */
+ isApplyPeriod: boolean;
+ onClose: () => void;
+ onConfirm: () => void;
+}
+
+// Figma: 사물함 신청 전 유의사항 Sheet Body (nodeId 1737:218310)
+//
+// 신청 기간이 아닐 때의 모습은 Figma에 없다 — 유의사항 3줄은 그대로 두고 하단 버튼만 잠가
+// "신청 기간이 아니에요"를 보여주기로 정했다(docs/plans/#68-lockers-notice-sheet.md 참고).
+function LockersNoticeSheet({
+ open,
+ isApplyPeriod,
+ onClose,
+ onConfirm,
+}: LockersNoticeSheetProps) {
+ return (
+
+ {/* pb-7: Figma Sheet Body의 Notice Section ↔ Action Area 간격(28px).
+ BottomSheet는 자식 사이에 간격을 두지 않아서 여기서 낸다. */}
+
+
+ {/* Figma가 두 줄로 끊어둔 자리라 줄바꿈을 폭에 맡기지 않고 그대로 옮긴다 */}
+ 신청 전 아래 내용을
+
+ 확인해 주세요
+
+
+
+ {LOCKERS_NOTICE_ITEMS.map((item) => (
+
+
+
+
+ {item.label}
+
+
+ {item.value}
+
+
+
+ ))}
+
+
+
+
+ {/* Figma Main Action은 56px인데 ActionAreaButton은 48px이다. 높이를 고정하면 비활성
+ 문구가 길어져 줄바꿈될 때 잘려서 padding으로 맞춘다(wds-component-usage.md 참고). */}
+
+ {isApplyPeriod ? "확인했어요" : "신청 기간이 아니에요"}
+
+
+
+ );
+}
+
+export default LockersNoticeSheet;
diff --git a/src/features/lockers/constants/lockersNotice.ts b/src/features/lockers/constants/lockersNotice.ts
new file mode 100644
index 0000000..3dd7046
--- /dev/null
+++ b/src/features/lockers/constants/lockersNotice.ts
@@ -0,0 +1,31 @@
+import applyPeriodIcon from "@/assets/icons/lockers/apply-period.svg";
+import onePerPersonIcon from "@/assets/icons/lockers/one-per-person.svg";
+import usagePeriodIcon from "@/assets/icons/lockers/usage-period.svg";
+
+export interface LockersNoticeItem {
+ icon: string;
+ label: string;
+ value: string;
+}
+
+// Figma: 사물함 신청 전 유의사항 Notice Items (nodeId 1737:218314)의 내용을 그대로 옮긴 목데이터.
+// 이용 기간·신청 기간 API가 붙으면 그 값으로 바뀔 자리다.
+// 위 일러스트 3개는 Figma export가 캔버스·섹션 배경까지 같이 구워 넣어서(42px 회색 네모)
+// 아이콘 그룹만 남기고 걷어낸 SVG다 — 다시 받으면 같은 정리가 필요하다.
+export const LOCKERS_NOTICE_ITEMS: LockersNoticeItem[] = [
+ {
+ icon: usagePeriodIcon,
+ label: "사물함 이용 기간",
+ value: "2026.09.01(화) - 2026.12.15(금)",
+ },
+ {
+ icon: onePerPersonIcon,
+ label: "중복 신청 불가",
+ value: "1인당 1개의 사물함만 신청 가능해요.",
+ },
+ {
+ icon: applyPeriodIcon,
+ label: "신청기간",
+ value: "2026.09.01(화) - 2026.12.15(금)",
+ },
+];