@godxjp/ui 33.7.1 → 33.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/START-HERE.md +1 -1
- package/agent/index.json +2 -2
- package/agent/llms.txt +3 -3
- package/dist/contracts/measurement.json +1 -1
- package/dist/styles/layers.json +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -2
- package/scripts/ui-audit.mjs +45 -5
- package/skills/godxjp-ui-design/SKILL.md +37 -0
- package/skills/godxjp-ui-form/SKILL.md +82 -0
- package/skills/godxjp-ui-navigation/SKILL.md +122 -0
- package/skills/godxjp-ui-navigation/references/principles.md +263 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "33.
|
|
4
|
-
"godxUiMcp": "33.
|
|
3
|
+
"version": "33.8.0",
|
|
4
|
+
"godxUiMcp": "33.8.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"LICENSE",
|
|
31
31
|
"DESIGN.md",
|
|
32
32
|
"agent",
|
|
33
|
+
"skills",
|
|
33
34
|
"dist",
|
|
34
35
|
"scripts/ui-audit.mjs",
|
|
35
36
|
"scripts/prune-css.mjs",
|
package/scripts/ui-audit.mjs
CHANGED
|
@@ -235,7 +235,8 @@ const PALETTE =
|
|
|
235
235
|
* Followed by U+FE0F they are asking for emoji presentation on purpose, and then they ARE emoji —
|
|
236
236
|
* so that spelling is still caught.
|
|
237
237
|
*/
|
|
238
|
-
const EMOJI =
|
|
238
|
+
const EMOJI =
|
|
239
|
+
/\p{Extended_Pictographic}\uFE0F|(?=\p{Extended_Pictographic})\p{Emoji_Presentation}/u;
|
|
239
240
|
/** Regional-indicator pairs = emoji flags (🇯🇵) — broken on Win/Linux; use Intl.DisplayNames. */
|
|
240
241
|
const EMOJI_FLAG = /\p{Regional_Indicator}/u;
|
|
241
242
|
|
|
@@ -995,7 +996,9 @@ const RULES = [
|
|
|
995
996
|
scope: "consumer",
|
|
996
997
|
severity: "warn",
|
|
997
998
|
spansElement: true,
|
|
998
|
-
|
|
999
|
+
// A dashboard's tiles ARE its surfaces — the same path test kpi-row-off-dashboard uses.
|
|
1000
|
+
matches: (source, rel = "") =>
|
|
1001
|
+
/dashboard/i.test(rel) ? [] : densityMatches(source, ["Card"], CARD_LIMIT),
|
|
999
1002
|
message: `${CARD_LIMIT}+ Cards in one file — a Card per section. Mark sections with a Heading and section spacing (PageContainer children, Flex gap="lg"); keep Card for a real boundary (a table surface, a selectable item).`,
|
|
1000
1003
|
},
|
|
1001
1004
|
{
|
|
@@ -1055,7 +1058,8 @@ const RULES = [
|
|
|
1055
1058
|
scope: "consumer",
|
|
1056
1059
|
severity: "warn",
|
|
1057
1060
|
spansElement: true,
|
|
1058
|
-
|
|
1061
|
+
// An Alert behind a condition IS a state (what the message asks Alerts to be); count the standing ones.
|
|
1062
|
+
matches: (source) => densityMatches(source, ["Alert"], ALERT_LIMIT, { skipConditional: true }),
|
|
1059
1063
|
message: `${ALERT_LIMIT}+ Alerts in one file. An Alert is for a state that blocks or changes the task; field errors belong in FormField, results in a toast, and standing info in plain text.`,
|
|
1060
1064
|
},
|
|
1061
1065
|
];
|
|
@@ -1810,9 +1814,45 @@ function* mixedButtonSizeMatches(source) {
|
|
|
1810
1814
|
}
|
|
1811
1815
|
|
|
1812
1816
|
/** One finding per file, at the `limit`-th occurrence of any tag in `tags`, naming the count. */
|
|
1813
|
-
|
|
1817
|
+
/**
|
|
1818
|
+
* The JS token before a JSX element, as the expression that places it: `?` / `:` (a ternary
|
|
1819
|
+
* branch), `&&` / `||` (a guard), `=>` (a callback, e.g. `.map`), `return`, or "" when the element
|
|
1820
|
+
* is a plain JSX child. An opening `(` is skipped — `cond ? (\n <Alert` reads as `?`.
|
|
1821
|
+
*/
|
|
1822
|
+
function placementBefore(source, index) {
|
|
1823
|
+
let i = index - 1;
|
|
1824
|
+
while (i >= 0 && (/\s/.test(source[i]) || source[i] === "(")) i -= 1;
|
|
1825
|
+
if (source[i] === "?" || source[i] === ":") return source[i];
|
|
1826
|
+
if (source.slice(i - 1, i + 1) === "&&" || source.slice(i - 1, i + 1) === "||") return "&&";
|
|
1827
|
+
if (source.slice(i - 1, i + 1) === "=>") return "=>";
|
|
1828
|
+
if (/\breturn$/.test(source.slice(Math.max(0, i - 5), i + 1))) return "return";
|
|
1829
|
+
return "";
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* ≥limit elements of `tags` that can be on screen TOGETHER. Mutually exclusive branches of one state
|
|
1834
|
+
* count once: the else branch of a ternary (`a ? <X/> : <X/>`) is the same slot as its `?` branch,
|
|
1835
|
+
* and a function that returns the element from several `if`s returns ONE of them — gino-cloud's
|
|
1836
|
+
* 実習生詳細 had 6 Badge tags and showed at most 3. `skipConditional` drops elements behind a
|
|
1837
|
+
* condition altogether (a guard, a ternary, a `.map`).
|
|
1838
|
+
*/
|
|
1839
|
+
function* densityMatches(source, tags, limit, { skipConditional = false } = {}) {
|
|
1814
1840
|
const hits = [];
|
|
1815
|
-
|
|
1841
|
+
const returnedIn = new Set(); // function starts that already returned one of `tags`
|
|
1842
|
+
for (const { tag, index } of jsxElements(source)) {
|
|
1843
|
+
if (!tags.includes(tag)) continue;
|
|
1844
|
+
const how = placementBefore(source, index);
|
|
1845
|
+
if (skipConditional && (how === "?" || how === ":" || how === "&&" || how === "=>")) continue;
|
|
1846
|
+
if (how === ":") continue;
|
|
1847
|
+
if (how === "return" || how === "?") {
|
|
1848
|
+
const head = source.slice(0, index);
|
|
1849
|
+
const arrows = [...head.matchAll(/=>\s*\{/g)];
|
|
1850
|
+
const fn = Math.max(head.lastIndexOf("function "), arrows.at(-1)?.index ?? -1);
|
|
1851
|
+
if (returnedIn.has(fn)) continue;
|
|
1852
|
+
returnedIn.add(fn);
|
|
1853
|
+
}
|
|
1854
|
+
hits.push(index);
|
|
1855
|
+
}
|
|
1816
1856
|
if (hits.length >= limit) yield { 0: `${hits.length} in this file`, index: hits[limit - 1] };
|
|
1817
1857
|
}
|
|
1818
1858
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: godxjp-ui-design
|
|
3
|
+
description: Design do/don't rules for @godxjp/ui interfaces, learned from real review feedback. Use when designing, redesigning, or reviewing any web UI built with @godxjp/ui — pages, app shells, topbars, status chips. Grows as reviewers flag issues.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @godxjp/ui — Design Do / Don't
|
|
7
|
+
|
|
8
|
+
Concrete rules for interfaces built with `@godxjp/ui`, accumulated from actual reviewer feedback —
|
|
9
|
+
treat each as a hard rule. Combine them with the `@godxjp/ui` MCP authority (`search_components`,
|
|
10
|
+
`get_component`, `list_anti_ai_tells`, `list_redesign_checks`) and industry patterns for the
|
|
11
|
+
surface being designed.
|
|
12
|
+
|
|
13
|
+
Sibling skills: `godxjp-ui-form` (forms and inputs), `godxjp-ui-navigation`.
|
|
14
|
+
|
|
15
|
+
## DO
|
|
16
|
+
|
|
17
|
+
- **Status chips / labels never wrap to a second line.** A `Badge` must stay on ONE line — icon +
|
|
18
|
+
text inline, never the icon stacked above the text. Pass a leading icon through the Badge `icon`
|
|
19
|
+
prop as a *component reference* (`icon={BadgeCheck}`), NEVER as an inline child
|
|
20
|
+
(`<Badge><BadgeCheck/> 確認済み</Badge>` column-stacks and wraps). This is `@godxjp/ui` cardinal
|
|
21
|
+
rule #35 ("Status chips never wrap"). It applies to every verified/pending/active-style chip on
|
|
22
|
+
every surface.
|
|
23
|
+
|
|
24
|
+
## DON'T
|
|
25
|
+
|
|
26
|
+
- **Don't give a sticky top bar a semi-transparent background + `backdrop-filter`.** A
|
|
27
|
+
`position: sticky` topbar with `background: hsl(var(--background) / 0.96)` +
|
|
28
|
+
`backdrop-filter: blur/saturate` samples and tints from whatever renders behind it — colourful
|
|
29
|
+
content scrolling underneath, or the browser's red automation/debug banner — so the bar picks up
|
|
30
|
+
a stray pink/red wash. Use a FULLY OPAQUE background (`hsl(var(--background))`, no alpha, no
|
|
31
|
+
`backdrop-filter`) so the bar is always clean whatever is behind it.
|
|
32
|
+
|
|
33
|
+
- **Don't strip the signed-in user's profile (avatar + name) from the global topbar / header.** It
|
|
34
|
+
is the orientation anchor — the user must always see *who they are signed in as* in the top
|
|
35
|
+
right, even when the page body already has its own identity hero. Leaving only a locale switcher
|
|
36
|
+
+ "Sign out" makes the topbar look empty or broken. Keep the profile chip (avatar + name) in the
|
|
37
|
+
`Topbar` `end` slot; the page hero is additive, not a replacement.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: godxjp-ui-form
|
|
3
|
+
description: Rules for building forms with @godxjp/ui. Use when creating or changing any form, create/edit screen, or labelled input in an app that installs the @godxjp/ui npm package. Covers page-not-modal, mandatory Form + FormField, content-sized input widths (GOV.UK Design System), and the escape hatch (open an issue on the library instead of hand-rolling). Not for apps that vendored their own copy of the components and have their own form rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Form rules (@godxjp/ui)
|
|
7
|
+
|
|
8
|
+
> Applies only to apps that install the `@godxjp/ui` npm package. **Out of scope:** apps that
|
|
9
|
+
> vendored their own copy of the components into their source tree — they have no MCP server and
|
|
10
|
+
> no `node_modules/@godxjp/ui`, and follow their own form and input-width rules.
|
|
11
|
+
|
|
12
|
+
Seven rules, each distilled from defects MEASURED in a production app and approved one by one by
|
|
13
|
+
its owner. A violation is a bug, not a style preference.
|
|
14
|
+
|
|
15
|
+
Sibling skills: `godxjp-ui-design` (visual do/don't rules), `godxjp-ui-navigation`.
|
|
16
|
+
|
|
17
|
+
## 1. A form with 3 or more fields is its own PAGE, not a modal
|
|
18
|
+
|
|
19
|
+
Give it its own route (for example a TanStack file route with a trailing `_` so it does not nest:
|
|
20
|
+
`accounts_.new.tsx`; in an Inertia app, a shell route `Inertia::render('<page>')` that passes NO
|
|
21
|
+
data, with the page fetching from the API itself).
|
|
22
|
+
A `Sheet`/drawer is also an overlay and does NOT replace a page — even though `dialog-form-too-big`
|
|
23
|
+
does not catch a `Sheet`.
|
|
24
|
+
Inlining a create form as a `Card` **above the list** is also forbidden (one app had seven screens
|
|
25
|
+
rejected for it). The "Create" button in the page header `extra` leads to a `…/new` route; after
|
|
26
|
+
saving, return to the detail page or the list.
|
|
27
|
+
A `Dialog` is ONLY for: confirmations (delete…), very short 1–2 field forms (editing a signature),
|
|
28
|
+
and quick pickers. As the owner put it: "I really hate opening things in a modal — a page with a
|
|
29
|
+
lot of content must be created as its own page."
|
|
30
|
+
|
|
31
|
+
## 2. ALWAYS wrap in `<Form>` — no orphan FormField, no bare control
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<Form layout="horizontal" labelWidth="11rem" controlWidth="28rem" asChild>
|
|
35
|
+
<Flex direction="col" gap="md">
|
|
36
|
+
<FormField id="…" label={…} required>…</FormField>
|
|
37
|
+
</Flex>
|
|
38
|
+
</Form>
|
|
39
|
+
```
|
|
40
|
+
- Desktop default is `layout="horizontal"` (label on the left — the antd convention); the kit
|
|
41
|
+
collapses to vertical below a breakpoint on its own (`collapseBelow`). Do NOT write your own
|
|
42
|
+
media query.
|
|
43
|
+
- Use `asChild` when the form element is owned by another library, or when submitting through a
|
|
44
|
+
button `onClick`.
|
|
45
|
+
- `required` on `FormField` adds the `*` itself — do not draw your own.
|
|
46
|
+
|
|
47
|
+
## 3. Size inputs to their CONTENT (GOV.UK Design System)
|
|
48
|
+
|
|
49
|
+
"Make text inputs the right size for the content they're intended for" —
|
|
50
|
+
https://design-system.service.gov.uk/components/text-input/
|
|
51
|
+
- Cap for the whole form: `controlWidth="28rem"` on `<Form>` (about 45 Latin characters).
|
|
52
|
+
- Override per field (`controlWidth` on `FormField`) when the length is KNOWN: a port `7rem`, an
|
|
53
|
+
enum of 2–3 options `10rem`, a short name / preset `14rem`, a textarea for a Japanese letter
|
|
54
|
+
`36rem`.
|
|
55
|
+
- Never let a 2-option select stretch to full width — the owner caught this one by hand.
|
|
56
|
+
|
|
57
|
+
## 4. Do NOT lay out fields yourself
|
|
58
|
+
|
|
59
|
+
Do not wrap `FormField`s in a hand-rolled horizontal `Flex` row (labels misalign at the top — a
|
|
60
|
+
measured bug). To weld several controls into ONE row under ONE label, use `<Flex attached>` (the
|
|
61
|
+
former `SpaceCompact`) inside a single `FormField`, with each control keeping its own
|
|
62
|
+
`aria-label`. For a grid of fields, use `<Form columns={2}>` (a `ResponsiveGrid`), not your own grid.
|
|
63
|
+
|
|
64
|
+
## 5. Discovery before writing JSX
|
|
65
|
+
|
|
66
|
+
Call `search_components` (MCP) or read `node_modules/@godxjp/ui/docs/` FIRST.
|
|
67
|
+
Neighbouring code is not the standard — it may be a bug nobody has caught yet.
|
|
68
|
+
|
|
69
|
+
## 6. Gates after writing
|
|
70
|
+
|
|
71
|
+
`node node_modules/@godxjp/ui/scripts/ui-audit.mjs <files>` must report 0 errors, together with
|
|
72
|
+
the repository's own type-check, tests and build. The audit enforces these rules through
|
|
73
|
+
`bare-control-needs-formfield`, `formfield-needs-form`, `dialog-form-too-big` and
|
|
74
|
+
`select-width-hint`; when the kit ships further rules, the audit takes over more of this list.
|
|
75
|
+
|
|
76
|
+
## 7. Escape hatch = OPEN AN ISSUE, do not hand-roll
|
|
77
|
+
|
|
78
|
+
When `Form` / `FormField` / `<Flex attached>` cannot cover a case (a layout the kit does not
|
|
79
|
+
support, a missing prop, an audit rule that blocks wrongly), do NOT hand-roll a workaround. Open an
|
|
80
|
+
issue on the @godxjp/ui repository (`godx-jp/godxjp-ui`) describing the use case and the proposed
|
|
81
|
+
API, then either wait or use the closest kit-valid approach with a `// TODO(godxjp-ui#<n>)`
|
|
82
|
+
comment. Fix it upstream, not at the call site.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: godxjp-ui-navigation
|
|
3
|
+
description: Navigation design rules (sidebar menu, per-role landing page, phone bottom bar, links between pages, breadcrumbs, in-page tabs) for multi-role business apps built with @godxjp/ui. Use BEFORE adding or changing a menu item, adding a page, or changing a role's landing page, and whenever navigation is criticised as confusing ("I can't tell what anything in this menu is for"). Covers the procedure (tasks → menu tree → walkthrough → measure), 28 sourced rules (NN/g, Material 3, Apple HIG, GOV.UK, SAP Fiori, Shopify Polaris and others) and an illustrative pattern for inspection and compliance apps.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Navigation for multi-role business apps (@godxjp/ui)
|
|
7
|
+
|
|
8
|
+
One question: **for a person in this role, doing this task, where does the first click go — and are
|
|
9
|
+
they sure it is right?** A menu is not a database diagram. A menu is each role's list of *tasks*,
|
|
10
|
+
ordered by frequency.
|
|
11
|
+
|
|
12
|
+
Distilled from measured failures in a real multi-role app: 17 menu items grouped by data type
|
|
13
|
+
("Records / Standards / Supplies / Master data"), three overlapping entries for one task ("Log an
|
|
14
|
+
inspection / Inspections / Checklists"), a Settings area that was a dead end, every role seeing every
|
|
15
|
+
item, and a phone layout with nothing but a drawer. The owner's verdict: *"I can't tell what anything
|
|
16
|
+
in this menu is for."* Full sources: [references/principles.md](references/principles.md) (28 rules,
|
|
17
|
+
with the URL behind each one). An app may keep its own industry benchmark notes (competitor
|
|
18
|
+
comparisons, domain vocabulary) in its own repository; they do not belong in this package.
|
|
19
|
+
|
|
20
|
+
## 1. Procedure — the order is the rule
|
|
21
|
+
|
|
22
|
+
1. **Tasks first, screens second.** For each role (e.g. frontline staff, branch manager, head-office
|
|
23
|
+
reviewer), list their 5–10 *most frequent tasks* in their own words ("log this morning's opening
|
|
24
|
+
checklist", "is this batch still within its expiry date", "which branches are late on their
|
|
25
|
+
checklists"). Sort by frequency. This is the only input to the menu.
|
|
26
|
+
2. **Split into 3 zones: Do · Set up · Review.** Daily work goes at the top; setup (templates,
|
|
27
|
+
recipes, configuration) goes in its own group or at the end; settings/admin go at the bottom.
|
|
28
|
+
3. **Write the menu tree as text for each role** (level 1 → level 2 → page). For each item: label,
|
|
29
|
+
destination page, which roles see it.
|
|
30
|
+
4. **Walk through the tree (no users needed)** — 8–10 tasks per role, written WITHOUT the words used
|
|
31
|
+
in the menu. At each level answer the 4 cognitive-walkthrough questions: will the user try to do
|
|
32
|
+
the right thing · will they *notice* the right item · does the label *match* their goal · after
|
|
33
|
+
clicking, can they tell they arrived. Record the expected first click and any **competing label**
|
|
34
|
+
(two labels pulling at the same task = a defect). Critical tasks must be "certainly right" on the
|
|
35
|
+
first click.
|
|
36
|
+
5. **Measure on the real app after building it** (a manual or agent-driven test pass): inventory
|
|
37
|
+
every page → its entries and exits, which menu item is highlighted, dead ends, orphan pages. If
|
|
38
|
+
you have users, run a tree test: critical tasks need >90% success.
|
|
39
|
+
6. Changing the menu structure is a **redesign** → bring a proposal (tree per role + old → new table +
|
|
40
|
+
walkthrough results) to the project owner for approval before writing code.
|
|
41
|
+
|
|
42
|
+
## 2. Hard rules
|
|
43
|
+
|
|
44
|
+
**Count and form**
|
|
45
|
+
- Phone: **bottom bar with 3–5 items** (the middle one may be a + quick-log button); everything else
|
|
46
|
+
goes under "More". Never put setup on the bottom bar. Desktop: **an always-visible sidebar**, not
|
|
47
|
+
only a ☰ button. Choose by window width, not by device. (@godxjp/ui's `MobileShell` has a bottom
|
|
48
|
+
bar — use it; don't rely on a drawer alone.)
|
|
49
|
+
- Sidebar at most **2 levels**, groups with short headings; each role sees **≤ ~7 primary items**.
|
|
50
|
+
Anything deeper → list → detail inside the page.
|
|
51
|
+
|
|
52
|
+
**Grouping and labels**
|
|
53
|
+
- Group by **task / work area**. Never group by data table, org chart or developer vocabulary
|
|
54
|
+
("Master data", generic "Records").
|
|
55
|
+
- A label is a short noun of 1–3 words, **in the words users say**, always with text (an icon only
|
|
56
|
+
supports it). The page title (H1 and `<title>`) **matches** the menu label. One concept = one name
|
|
57
|
+
everywhere, in every language (check every locale: e.g. not five strings sharing the root "記録"
|
|
58
|
+
split across two groups).
|
|
59
|
+
- **Each destination appears once** in the menu. Two items leading to the same kind of record = a
|
|
60
|
+
defect.
|
|
61
|
+
- Action buttons (Log/Create) are **not menu items**: one prominent primary button (top of the menu,
|
|
62
|
+
or the + in the middle of the bottom bar) for the #1 task; child objects are created right inside
|
|
63
|
+
their parent's page.
|
|
64
|
+
|
|
65
|
+
**Per role**
|
|
66
|
+
- Each role has its **own fixed landing page**: frontline staff → "Today" (due, overdue, my tasks);
|
|
67
|
+
managers/head office → "Overview" (completion rate, exceptions by branch).
|
|
68
|
+
- **Hide** items a role will never use (filter the menu by the current user's permissions); **dim it
|
|
69
|
+
and say why** when it is only temporarily blocked. The menu never changes with data state.
|
|
70
|
+
- Branch scope is a single control (All / Group / Branch); a person who belongs to only one branch
|
|
71
|
+
doesn't see it. Standards authored by head office carry a "From head office" label.
|
|
72
|
+
|
|
73
|
+
**Between pages**
|
|
74
|
+
- Lists are for finding; a detail page is for one object (top: key facts + actions; below: sections or
|
|
75
|
+
tabs). Scanning a code opens the detail page directly.
|
|
76
|
+
- **No dead ends:** a detail page lists its related objects with a **count**, a few preview rows, a
|
|
77
|
+
pre-filtered "View all" and an in-place "Create" — **both directions** (inspection → batch, and
|
|
78
|
+
batch → its inspections).
|
|
79
|
+
- From a dashboard or notification, link **straight to the record**, or to a list that is *already
|
|
80
|
+
filtered correctly* — never to an unfiltered list.
|
|
81
|
+
- Breadcrumbs show **hierarchy** (not history), from level 3 down; every crumb is a real page; the last
|
|
82
|
+
crumb is the parent when the H1 already names the object; use the record's **real name**, not
|
|
83
|
+
"Batch"/"Item". The breadcrumb and the highlighted menu item must name **the same parent**.
|
|
84
|
+
- In-page tabs: 1–2 words, the most-used tab first, with a count; tab state + filters + scope live **in
|
|
85
|
+
the URL**; Back restores scroll position, page and filters. "All" sits in the same place on every
|
|
86
|
+
page.
|
|
87
|
+
- Deep links rebuild the normal parent path (Back goes to the parent list). Every child page has a
|
|
88
|
+
highlighted menu item — no page leaves the menu "with the lights off".
|
|
89
|
+
|
|
90
|
+
## 3. Illustrative pattern: inspection and compliance operations
|
|
91
|
+
|
|
92
|
+
An example only, for apps that run recurring checks across many sites:
|
|
93
|
+
|
|
94
|
+
- **Do / Set up / Review** are kept apart; templates are authored on desktop only.
|
|
95
|
+
- Typical set: Home · Inspections (records) · Templates · Schedule · **Actions** · Incidents · Assets ·
|
|
96
|
+
Analytics · (Branches/Users in organization settings).
|
|
97
|
+
- A failed item is handled right **inside the flow** (a required step; 3 or more fields means a page or
|
|
98
|
+
step, not a popup) → an "Open nonconformity" button right under the item; nonconformities/actions
|
|
99
|
+
stay **permanently linked** to their source record.
|
|
100
|
+
- Staff land on "Today" plus a separate place for "Overdue/Missed"; managers land on a rate table plus
|
|
101
|
+
exceptions.
|
|
102
|
+
- Phone bottom bar: 4–5 task items (e.g. Today · Inspections · +Log · Nonconformities · More).
|
|
103
|
+
- Vocabulary: avoid "Reports"/"レポート" as the label for *records* (in English "Reports" means
|
|
104
|
+
analytics; in Japanese "レポート" often means an individual record).
|
|
105
|
+
|
|
106
|
+
## 4. Self-check gate (before asking for approval / before merging)
|
|
107
|
+
|
|
108
|
+
- [ ] A task table per role and a text menu tree per role exist; each role ≤ ~7 primary items; phone
|
|
109
|
+
3–5 items.
|
|
110
|
+
- [ ] Walkthrough of 8–10 tasks per role: no step answered "no"; no pair of competing labels.
|
|
111
|
+
- [ ] No duplicate destinations; no grouping by data table; label = H1 = `<title>`, consistent across
|
|
112
|
+
every locale.
|
|
113
|
+
- [ ] Menu filtered by permission; landing page per role; bottom bar present on phones.
|
|
114
|
+
- [ ] Page inventory: 0 dead ends, 0 orphan pages, every child page has a highlighted menu item that
|
|
115
|
+
matches its breadcrumb.
|
|
116
|
+
- [ ] Every detail page links both ways to related objects, with counts and a pre-filtered "View all".
|
|
117
|
+
- [ ] Tabs/filters/scope live in the URL; Back keeps the position.
|
|
118
|
+
- [ ] Structural change → the project owner has approved the proposal.
|
|
119
|
+
|
|
120
|
+
When @godxjp/ui can't do something you need (bottom bar, menu filtering, scope switcher), open an issue
|
|
121
|
+
on the @godxjp/ui repository with the use case instead of hand-rolling it (the same rule as the
|
|
122
|
+
`godxjp-ui-form` skill).
|