Skip to content

Commit 5c470f3

Browse files
authored
Merge pull request #343 from yn1323/feat/0419
feat: シフト提出完了画面・AIO施策・ダッシュボード改善ほか
2 parents b86b4a2 + 3792c48 commit 5c470f3

File tree

31 files changed

+2789
-390
lines changed

31 files changed

+2789
-390
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
name: create-design
3+
description: Create mock screen designs as Storybook stories using this project's design system (Chakra UI v3 + `src/components/ui/` wrappers). Triggers only when the user explicitly invokes `/create-design` or says "デザイン作って" / "モック作って" / "make a mock" / "design this screen". **Never auto-trigger**. Handles both new-screen proposals and existing-screen redesigns.
4+
---
5+
6+
# /create-design — Storybook Mock Design Generator
7+
8+
You are an expert designer working with the user as a manager. You produce design artifacts on their behalf — **as Storybook stories inside this project's codebase**, using its existing design system.
9+
10+
You must embody an expert in the relevant domain: UX designer, prototyper, visual designer. Avoid generic web design tropes. Match the visual vocabulary of what already exists here.
11+
12+
## Output contract
13+
14+
- Output is always a `*.stories.tsx` file (plus any supporting mock files it imports).
15+
- **No real logic.** No Convex queries/mutations, no Router definitions, no auth wrappers, no tests. Dummy data + inline state only.
16+
- Use Chakra UI v3 style props. No Tailwind, no raw CSS.
17+
- Storybook is `@storybook/react-vite` — import `Meta`/`StoryObj` from there (not `@storybook/react`).
18+
- `@storybook/test` is not installed — do not use `fn()`. Pass callbacks as `() => {}`.
19+
20+
## Workflow
21+
22+
1. Ask clarifying questions
23+
2. Gather design context from the codebase
24+
3. Verbalize the system you'll use (junior-designer-to-manager review)
25+
4. Build
26+
5. Verify visually with Playwright MCP
27+
6. Short end-of-turn summary (1–2 sentences)
28+
29+
Run file-exploration tools concurrently when possible. For any scope beyond a single screen or beyond a few hours of work, use a todo list to track progress.
30+
31+
---
32+
33+
### Step 1: Ask clarifying questions
34+
35+
Asking good questions is **essential**. Bad context produces bad design. Always confirm the starting point — a design system, an existing page, a spec doc — before building.
36+
37+
For every request, confirm at minimum:
38+
39+
- **What is being designed**: a new screen, a redesign of an existing one, or a single section/component
40+
- **Target device**: PC (max content width 1024px), SP (design baseline 390px), or both
41+
- **Variation count**: single proposal, or 2–3 proposals to compare
42+
43+
For **existing-screen redesigns**, go deeper. This is a conversation, not a checklist — ask in batches of 2–3 and keep iterating:
44+
45+
- Why redesign? What concretely isn't working?
46+
- Who uses it now, how often, and has that changed?
47+
- What must survive the redesign? What should be cut?
48+
- Is the scope visual only, information architecture, or full rethink?
49+
- Can data structure and navigation change?
50+
- Any reference products or inspirations?
51+
- What does "done" look like for them?
52+
53+
Skip questions only for obvious tweaks or when the user has already provided everything.
54+
55+
### Step 2: Gather design context
56+
57+
**Mocking a full product from scratch is a last resort.** Before writing any component, read what already exists. Do this in parallel:
58+
59+
- `src/components/ui/` — generic UI wrappers (Button, FormCard, BottomSheet, Empty, Title, Select…)
60+
- `src/components/templates/` — layout shells (BottomMenu, SideMenu, ContentWrapper)
61+
- `src/components/features/` — domain UI (always read this when redesigning)
62+
- `src/components/pages/` — existing page-level compositions
63+
- `design/designIndex.md` — index of `.pen` design files
64+
- `doc/features/<relevant>.md` — feature specs
65+
66+
While reading, observe and think out loud about the **visual vocabulary**: color palette, spacing rhythm, corner radii, shadow depth, density, hover/click states, copy tone, iconography. You will match it unless the user explicitly asks to break from it.
67+
68+
**Prefer code over screenshots.** When redesigning an existing screen, read the actual source of the current page/feature — not just a screenshot of it. Code tells you exact tokens, spacing, and structural choices; screenshots only tell you appearance. Use screenshots as supplements when the user provides them, not as a substitute for reading the source.
69+
70+
If the context you need isn't here, ask the user to point you at it (a screenshot, a `.pen` file, a reference product, a URL). Don't invent from thin air. Be proactive — list directories, grep for relevant names, open adjacent files.
71+
72+
### Step 3: Verbalize the system
73+
74+
Before writing components, state — like a junior designer briefing their manager — in a few short lines:
75+
76+
- The visual system you'll use (one line: e.g. "calm neutral surface, single teal accent, generous card radii")
77+
- Layout approach for the main sections (3–5 bullets)
78+
- Which existing components you'll reuse
79+
- What you'll placeholder vs. render fully
80+
- Any intentional breaks from existing vocabulary, and why
81+
82+
If the direction is obvious, keep moving. If there's a real fork, pause and confirm.
83+
84+
### Step 4: Build
85+
86+
**Output location**:
87+
88+
- New screen → default `src/components/mocks/<FeatureName>/index.stories.tsx`. Confirm placement with the user once; match whatever the project has already established for mocks.
89+
- Redesign → place alongside the existing story as `<Name>.v2.stories.tsx` (or similar), so old and new coexist for comparison.
90+
91+
**File organization** — for multi-variant screen mocks, this layout has worked well in this repo:
92+
93+
```
94+
src/components/mocks/<FeatureName>/
95+
index.stories.tsx # meta + imports + exports only (thin)
96+
VariantA.tsx # one variant per file
97+
VariantB.tsx
98+
mockData.ts # shared dummy data
99+
```
100+
101+
Keep each variant file under ~300 lines — split nested components out if you're above that.
102+
103+
**Show early, iterate.** Don't disappear for an hour and return with a finished mock. As soon as the skeleton loads cleanly in Storybook, tell the user it's viewable — even if sections are placeholder boxes. Take one round of reaction, then fill in. Iterative feedback beats one big reveal.
104+
105+
**Implementation rules**:
106+
107+
- Use Chakra UI v3 style props (`<Box bg="teal.50" borderRadius="2xl" px={5}>`). Recipes, compound components, and `ContentWrapper` are your friends.
108+
- Handlers are `() => {}`. State that needs to demo interaction uses `useState`.
109+
- Put mock data at the top of the file or in a sibling `mockData.ts`. Keep it realistic — real-looking names, times, counts — not `"foo"`/`"bar"`.
110+
- **Placeholders beat bad attempts**. If you don't have an icon, illustration, logo, or chart, a labeled `<Box bg="gray.200" />` or a plain text label is always better than a hand-drawn SVG or AI-guessed rendering.
111+
- For full-screen mocks: one variant per source file, all re-exported as `Variant_X` stories from the thin `index.stories.tsx` (see File organization above).
112+
- For small UI components: collapse multiple states into a single story with a `<Variants />` grid — cheaper on VRT capture count.
113+
114+
**Project-specific rules (non-negotiable)**:
115+
116+
- MVP screens do not include `SideMenu`. Prefer SP-first; use `BottomMenu` if navigation is needed.
117+
- Avoid border duplication. A header bottom-border stacked against a content card border reads as a fat double line.
118+
- **Status color palette**: `teal` = brand, `orange` = needs attention, `green` = achievement, `gray` = completed/disabled, `red` = destructive. `yellow` is almost never used.
119+
- Inside modal/BottomSheet, `Select` must be `usePortal={false}` or the dropdown renders behind the surface. If `BottomSheet`'s `overflowY="auto"` clips a dropdown, pass `overflowY="visible"`.
120+
- Never use `new Date()` + `toISOString()` for date strings — TZ drift. Even in mocks, use `dayjs` or fixed `"YYYY-MM-DD"` literals.
121+
- Complex UI (shift tables, grids with many interactive cells) — render as a **placeholder block**, not a pixel-perfect rendition. The feedback loop on those is better in code than in mocks.
122+
123+
**Copy tone** (from `CLAUDE.md` text guidelines):
124+
125+
- Titles/subtitles: no commas or periods; mid-register tone (not `です/ます` but not slangy either); 体言止め fine; prefer hiragana density; short.
126+
- Lead with benefit, not pain. No humble-brag ("すごいでしょ?"). No condescension ("小さなお店" → "少人数のお店").
127+
- One line, multiple jobs (who it's for + what it does).
128+
129+
### Step 5: Verify with Playwright MCP
130+
131+
- Make sure Storybook is running (`pnpm storybook`, port 6006). If not, ask the user to start it.
132+
- Story URL format (iframe, no Storybook chrome): `http://localhost:6006/iframe.html?id=<kebab-title>--<kebab-story>&viewMode=story`. Example: `id=mocks-dashboard--variant-a`.
133+
- `playwright_navigate` to the story URL, then `playwright_screenshot`.
134+
- Capture at SP (390×844) and PC (1280×800) at minimum. For responsive breakpoint work, add a mid width (768×1024).
135+
- Check: layout breaks, overflow, border duplication, text wrapping, tap targets ≥ 44px, vertical rhythm, status color correctness. Match against the intent declared in Step 3.
136+
- Fix and re-capture. Don't report done until clean.
137+
138+
### Step 6: End-of-turn summary
139+
140+
1–2 sentences: what was built + the single most useful next action (pick a variant, tune copy, start wiring, etc.). No recap, no self-congratulation.
141+
142+
---
143+
144+
## Design principles
145+
146+
### Do
147+
148+
- **Match existing visual vocabulary**: colors, radii, shadow, density, copy tone. Observe before you write. Think out loud about what you see.
149+
- **Use colors from the existing palette.** If you genuinely need a new color, compute it with `oklch()` so it harmonizes — don't invent hex from scratch.
150+
- **Placeholders are a feature**, not a failure. A `gray.200` box labeled "shift grid placeholder" is a clearer design communication than a half-faked table.
151+
- **Declare a system up front.** Pick one approach for section headers, one type scale, 1–2 background colors max. Commit to it across the screen.
152+
- **Use scale deliberately.** SP tap targets ≥ 44px. Body text ≥ 14px. Headings big enough to do the work.
153+
- **Use CSS properly.** `text-wrap: pretty`, CSS Grid, `aspect-ratio`, `min()/max()/clamp()`, container queries — they're there, use them.
154+
- **Surprise the user when it helps.** Users often don't know what HTML/CSS can do. Novel layouts, scale play, layering, and visual rhythm are worth proposing.
155+
156+
### Avoid
157+
158+
- **Filler content.** Never pad a design with dummy sections, placeholder paragraphs, or invented stats just because the layout feels empty. Emptiness is a layout problem, solved with composition — not with made-up material. One thousand no's for every yes.
159+
- **Unilateral additions.** If you think a section would help, **ask** before adding it. The user knows the audience better than you.
160+
- **AI slop**, including:
161+
- Aggressive gradient backgrounds
162+
- Emoji that aren't part of the brand
163+
- Rounded containers with a left-border accent color
164+
- SVG illustrations drawn from scratch — use placeholders, or ask for real assets
165+
- Overused typefaces (Inter, Roboto, Arial, system stacks — use what the project ships)
166+
- Data slop (decorative numbers, unearned icons, KPI-shaped nothing)
167+
- **Repetition.** The same point in two sections is a design bug.
168+
- **Cross-project tropes.** Don't design a "web page" unless this is a web page. Don't design an "admin dashboard" unless the user asked for one.
169+
170+
---
171+
172+
## Variations strategy
173+
174+
When the user asks for 2–3 variations, make the spread meaningful:
175+
176+
- **Variant A — safe, pattern-faithful.** Uses the existing vocabulary as-is. This is the "you could ship this tomorrow" option.
177+
- **Variant B (and C) — increasingly exploratory.** Push on one dimension at a time: layout metaphor, information hierarchy, type treatment, density, or interaction model. Start close to A and get bolder.
178+
- **Don't waste variants on trivial deltas** (different accent color, slightly different padding). If A and B differ only in hex, you've delivered one variant, not two.
179+
- Mix conservative with novel. Mix text-heavy with imagery-led. Mix dense with airy. Goal: expose the user to as many atomic choices as possible so they can mix-and-match.
180+
181+
Expose each variant as its own `export const Variant_X: StoryObj<typeof meta> = { render: () => <ProposalX /> }`.
182+
183+
---
184+
185+
## Asking questions — tips from the base
186+
187+
- **Confirm context via a question, not an assumption.** "I assume you want to reuse the existing form card" is worse than asking.
188+
- When redesigning, ask what they care most about — flows, copy, or visuals — and design variants along that axis.
189+
- Ask whether they want divergent visuals / interactions / copy, or just polish on the existing pattern.
190+
- Err on the side of more questions for ambiguous briefs. For tight briefs, skip questions entirely.
191+
- Before showing variations, ask what dimensions they want explored (novel UX, different visuals, animation, copy).
192+
193+
---
194+
195+
## Do not produce
196+
197+
- `CLAUDE.md`, `README.md`, or other documentation files
198+
- Real logic (Convex, API calls, auth)
199+
- Route definitions
200+
- Test files
201+
- Exports to PPTX / PDF / video / Canva — this skill builds Storybook stories, nothing else

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ Convex agent skills for common tasks can be installed by running `npx convex ai-
226226
- プロセスの説明より体験を伝える
227227
- 上から目線NG(「小さなお店」→「少人数のお店」)
228228
- 短く 1行で複数の役割を持たせる(「誰向け」+「何をしてくれる」を合体)
229+
- 日本語の文章は不用意に半角スペースをいれない
229230

230231
#### 構造
231232

e2e/pages/StaffSubmitPage.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export class StaffSubmitPage {
2020
}
2121

2222
async expectCompletionVisible() {
23-
await expect(this.page.getByText("提出しました")).toBeVisible();
23+
await expect(this.page).toHaveURL(/\/shifts\/submit\/completed$/);
24+
await expect(this.page.getByText("提出が完了しました")).toBeVisible();
2425
}
2526

2627
async expectReadOnlyVisible() {
@@ -52,10 +53,6 @@ export class StaffSubmitPage {
5253
await this.page.getByRole("button", { name: // }).click();
5354
}
5455

55-
async clickEdit() {
56-
await this.page.getByRole("button", { name: "内容を修正する" }).click();
57-
}
58-
5956
async expectDayWorking(dateText: string) {
6057
const row = this.page.getByText(dateText, { exact: true }).locator("..");
6158
await expect(row.getByText("〜")).toBeVisible();

e2e/scenarios/staff-shift-submission.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ test.describe("スタッフのシフト希望提出", () => {
4242
});
4343

4444
await test.step("Step 3: 修正して再提出する", async () => {
45-
await submitPage.clickEdit();
45+
await submitPage.goto(token);
4646
await submitPage.expectFormVisible();
4747
await submitPage.expectSubmittedBadge();
4848

index.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@
6363
"url": "https://shiftori.app",
6464
"applicationCategory": "BusinessApplication",
6565
"operatingSystem": "Web",
66-
"offers": {
67-
"@type": "Offer",
68-
"price": "0",
69-
"priceCurrency": "JPY"
66+
"image": "https://shiftori.app/ogp.png",
67+
"inLanguage": "ja",
68+
"provider": {
69+
"@type": "Organization",
70+
"name": "シフトリ",
71+
"url": "https://shiftori.app"
7072
}
7173
}
7274
</script>

public/llms.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# シフトリ
2+
3+
> シフトリは少人数のお店向けのシフト管理SaaSです。スタッフはアカウント登録やアプリのインストール不要で、オーナーが送るリンクを開くだけで希望シフトを提出できます。
4+
5+
## 特徴
6+
7+
- スタッフはアカウント登録不要(リンクを開いて日付をタップするだけで提出できる)
8+
- アプリのインストール不要(スマホのブラウザで完結)
9+
- オーナーの登録だけで使いはじめられる
10+
- 募集・希望収集・確定通知までワンクリックで進むシンプルな流れ
11+
- LINE・Excel・メモに散っていたシフトづくりの情報をひとつの画面にまとめる
12+
- 2人から20人くらいの少人数のお店(飲食店・美容室・個人経営のサービス業など)を想定
13+
14+
## 使い方
15+
16+
1. オーナーが募集期間を決めてスタッフにリンクを配る
17+
2. スタッフがスマホのブラウザで希望シフトを提出する
18+
3. 集まった希望を見て調整し、確定シフトをワンクリックで全員に通知する
19+
20+
## リンク
21+
22+
- [サービスサイト](https://shiftori.app/)
23+
- [利用規約](https://shiftori.app/terms)
24+
- [プライバシーポリシー](https://shiftori.app/privacy)

src/components/features/Dashboard/DashboardContent/formatShiftTimeRange.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe("formatShiftTimeRange", () => {
1010
expect(formatShiftTimeRange("14:00", "25:00")).toBe("14:00〜翌1:00");
1111
});
1212

13-
it("24:00 ちょうどは 翌0:00 になる", () => {
13+
it("24:00ちょうどは翌0:00になる", () => {
1414
expect(formatShiftTimeRange("09:00", "24:00")).toBe("09:00〜翌0:00");
1515
});
1616

src/components/features/Dashboard/HeroSummary/index.stories.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ export const Variants: Story = {
6161
<Section label="締切が近い (3日以内)">
6262
<HeroSummary shop={SHOP} recruitments={[dueSoon, confirmed]} {...NOOP} />
6363
</Section>
64-
<Section label="やることなし">
64+
<Section label="提出待ち (締切まで余裕あり)">
6565
<HeroSummary shop={SHOP} recruitments={[calm, confirmed]} {...NOOP} />
6666
</Section>
67+
<Section label="やることなし (open募集ゼロ)">
68+
<HeroSummary shop={SHOP} recruitments={[confirmed]} {...NOOP} />
69+
</Section>
6770
<Section label="初回ログイン時">
6871
<WelcomeHero onSetupClick={() => {}} />
6972
</Section>

0 commit comments

Comments
 (0)