UI Structure¶
Purpose¶
This file is the compact UI contract for new or migrated application screens.
Reference¶
- Core reference page:
frontend/pages/platform/ui/pilot.php. - Runtime helpers:
app/shared/ui/structure.phpapp/shared/ui/shell.phpapp/shared/ui/runtime.php- Default MK modal/table runtime:
KJModalkjTable- Do not use new
POPUP.createDialog,$.fn.kjtable,KJTABLE.buildOption, or directwindow.KJTABLEoption-builder paths on new or migrated screens. - Use
KJTableUtilitiesfor remaining shared upload, file viewer, HTML escaping, and bulk-closing helpers while the legacyKJTABLEglobal is being retired.
Product UI Direction¶
- Dense operations UI, not marketing UI.
- Stable surface language across pages.
- Fast scanning, visible state, compact controls.
- Minimize user clicks and manual input: when the next action is unambiguous, open the required editor or workflow directly instead of inserting an intermediate screen or confirmation button. Keep explicit confirmation only for irreversible, security-sensitive, or concrete data-integrity-risk actions.
- Use tokens and shared components before page-specific CSS.
Page Pattern¶
app shell
header / context chips
section shell
summary / primary controls
table or workspace
modal
form
state snapshot
Density¶
| Mode | Use |
|---|---|
comfy |
overview, admin, onboarding |
compact |
default operations screen |
dense |
tables, grids, high-frequency data entry |
Defaults:
- Operational pages: compact.
- Tables: dense.
- Modal forms: compact, with dense rows only for repetitive line items.
Layout Tokens¶
| Token | Value |
|---|---|
| Section radius | 20px |
| Sub-card radius | 16px |
| Field/button radius | 12px |
| Modal radius | 22px |
| Page title | 24px |
| Section title | 16px |
| Body text | 13px |
| Micro label | 11px |
| Table text | 12px |
| Dense row height | 32-36px |
| Compact field height | 34-36px |
| Dense field height | 30-32px |
Typography Standard¶
- Application sans:
Montserrat, "Helvetica Neue", sans-serif. - Code and identifiers:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace. - Supported weights are
400,500,600, and700. Use heavier legacy values only while preserving an existing screen. - Page title:
24px / 600 / 1.2; section title:16px / 600 / 1.2; body:13px / 400 / 1.5; field label and table:12px / 500 / 1.35; micro label:11px / 500 / 1.2. - Strong text uses slate
900, normal text slate700, secondary text slate500, and disabled text slate400.
Spacing Standard¶
- Use a
4pxbase unit and the supported scale4, 8, 12, 16, 20, 24, 32px. - Prefer parent
gapfor spacing between sibling controls. Do not add ad-hoc margins to every field. - Modal header, body, and footer own their internal padding. Modal action groups use an
8pxgap and the footer keeps at least14px 18pxpadding. - Compact form grids use
12-16pxgaps. Related fields share one section; unrelated sections use a16pxgap. - A long field may span the full grid. Short fields should share a row when their labels and values remain readable.
Surface Rules¶
- Page background uses
bg. - Main content uses
panel. - Secondary/read-only areas use
panelAlt. - Sidebar uses the dark shell.
- Semantic colors are for status chips, validation, and alerts only.
- Do not nest card inside card unless the inner area is a distinct interactive workspace.
- Avoid decorative section header bars on MK operations pages.
Component Rules¶
Form System¶
KJFormis the common field contract for Pilot, newly migrated KJModal screens, and explicitly migrated standalone forms. It owns control, label, Tom Select, validation, and field-state styling.KJModalowns only the modal shell (header, body, footer, action placement, and shared spacing). Modal-specific field CSS must not replace KJForm defaults.- Reuse KJForm classes and enhancers before adding a screen-local field/select style. Promote a repeated, justified exception to KJForm rather than copying it between screens.
- Legacy pages and legacy popups remain unchanged by this rule. Convert only a screen explicitly requested by the user, validate its actual workflow, then proceed to the next screen.
- Screen-specific field grids may vary by business purpose, importance, and expected value length; the underlying field formatting remains KJForm unless a documented exception is required.
App Shell¶
- Fixed navigation shell where applicable.
- Content width should support dense operational tables.
- Mobile must remain usable, even if table actions degrade to horizontal scroll.
Section Shell¶
- Use for grouping an operational unit.
- Prefer summary text and controls over decorative titles.
- Do not add explanatory subtext, captions, or subtitles that merely restate the section title or obvious current state. Add one only when it changes the operator's next action or communicates a real constraint.
- Keep one main purpose per section.
Toolbar / Filter Bar¶
- Put primary filters before secondary actions.
- Keep filter height compact.
- Use chips for active filters or selected rows.
Button¶
- Primary action: one per local context.
- Secondary actions: neutral.
- Destructive actions: explicit confirmation.
- Disabled state must explain itself through visible copy or context.
Field¶
- Label must remain visible.
- Validation message must be visible.
- Use dense controls only when repeated rows require it.
Status Chip¶
- Chip text must use domain status names.
- Color reinforces state but cannot be the only signal.
Data Table¶
- Header stays clear and compact.
- Empty state must say what the user can do next.
- Row actions must be predictable and aligned.
- Loading/error states must be visible.
- Active list schemas use the KJTable
api-v2adapter with an explicit/api/...endpoint. The adapter requiresdata.itemsand a non-negative numericdata.total; malformed success payloads must surface as visible errors rather than empty tables.
Timeline / Operational Board¶
- Timeline boards are read-only unless the user explicitly requests editing controls.
- Keep the left identity/status column stable and use horizontal scrolling for time ranges on narrow viewports.
- Use semantic block styles for job type, idle time, active work, and issue states.
- Detail drawers should show source record context and correction guidance without creating a second editing path.
- For loader timeline screens,
T_STAFF_TIME_EVENTis the display source for clock/job events.T_LOADING_PLANNERcan be joined for job context, but corrections should happen on the source event or job/planner record that produced the event.
Staff Time Controls¶
- Inbound-loader staff clock controls use compact status plus one primary action: Clock In when clocked out, Clock Out when working. When the logged-in loader is working and has an office-created scheduled break/lunch queue row for today as the primary assigned loader, show a secondary Start Break/Start Lunch button beside Clock Out.
- Loader self-service Break In/Out controls must not be shown as always-available actions. Loader break/lunch start is only available for an existing office-created break queue row where that loader is the primary assigned loader; managers may still use correction flows.
- Telegram staff time must not show persistent Clock In/Clock Out reply keyboards. Existing typed clock commands or old reply-keyboard text should only remove the keyboard and direct users to the inbound-loader page.
- Telegram break queue messages must not show inline
Start 10MIN BREAK/Start LUNCH BREAKbuttons. They should include the inbound-loader link, and old break callback buttons should only direct users to the inbound-loader page. Break/lunch starts are recorded from the inbound-loader assigned break queue start flow. - Loader Timeline remains read-only by default. Manager/Admin users may enable Manage Time mode to add, edit, or delete clock in/out events and add break/lunch corrections with a required correction reason.
- Loader Timeline renders break/lunch blocks from paired
BREAK_IN/BREAK_OUTstaff-time events and is manager-only. Manager-created or inbound-loader queue-started10MIN BREAKandLUNCH BREAKrows createBREAK_IN; the protected Telegram cron closes expired breaks withBREAK_OUTand sends the next queued job Telegram when one is ready. - Loader Timeline time range defaults to 7 AM-6 PM, supports Auto expansion for out-of-range events, and may expose wider selectable ranges with horizontal scrolling.
Modal¶
- Modal title describes the operation.
- Do not repeat the operation as a status badge beside the close button. Header status is reserved for an actual business state such as Hold, Failed, or Completed.
- Include context snapshot when editing operational records.
- Keep submit/cancel placement consistent.
- Group fields by business meaning and size the grid by expected value length instead of rendering one vertical list.
- Escape closes the topmost modal unless a destructive or incomplete action explicitly requires a confirmation step.
- Do not hide API errors.
Prohibitions¶
- Do not create page-specific design systems.
- Do not add decorative gradients or large marketing blocks to operations pages.
- Do not hide key state in tooltips only.
- Do not create silent empty states.
- Do not use new legacy popup/table APIs on newly migrated screens.
Implementation Order¶
- Use existing UI helpers/tokens.
- Build shell and section layout.
- Add table/workspace.
- Add modal/form.
- Verify dense and mobile layouts.
- Check visible loading, empty, validation, and error states.
Telegram-Origin UI Requests¶
- Treat any UI work requested through Telegram as requiring browser runtime verification before reporting completion.
- Treat any user-facing logic change requested through Telegram as requiring the same browser runtime workflow verification, even when the visible UI code did not change.
- The browser run must use the relevant page, role/session, inputs, buttons, and modal/page transitions that a real user would use. Confirm the final visible state, such as modal closed, row moved, refreshed status, success message, or visible validation error.
- Do not count server logs, database rows, or HTTP 200 responses alone as UI/workflow verification. JSON APIs must also return parseable JSON without PHP warnings/notices/deprecations injected into the response body.
- Capture at least one screenshot showing the affected UI after the change. Include additional screenshots for modal, mobile, or error states when those states are part of the requested work.
- Include screenshots directly in the Telegram message body/attachment for the response. Do not send only a local file path or textual screenshot reference.
- Local DB writes needed for login, setup, reversible smoke records, or runtime verification are pre-approved for Telegram-origin UI work. Use the local DB target rules in
.agents/rules/DEV_ENV.md, keep writes scoped to verification, and document what was written or why no write was needed. - Production DB writes and schema changes still require explicit separate confirmation.
Acceptance Criteria¶
Local Assignment Board candidate¶
- Inbound Planning keeps compact
Assign Work,Clock Out, andAdd Breakheader actions with page-local modal/card patterns. - Assigned JSON work is concealed on Loader as
NEXT ASSIGNMENT; Start reveals server-backed detail/timer. Batch results remain per Loader and expose Telegram retry. -
Started Clock Out hides the general Clock Out button and presents only the workflow action. A Final Break Clock Out shows cleaning first when required, then
Start Final 10-Minute Break, a server-offset remaining timer, and workflow Clock Out only after the server threshold; it never shows Clock Back In. -
Page matches shared density and surface rules.
- Primary user action is obvious.
- Table and modal errors are visible.
- Keyboard/mouse interactions do not dead-end.
- No console errors on load.
- No new one-off UI helper unless repetition threshold is met.
- Telegram-origin UI work includes runtime test evidence and directly attached screenshot evidence.
---¶
Source:
.agents/rules/UI_STRUCTURE.md— ctc repository · This page is an English translation of the source document. Identifiers, file paths and code symbols are unchanged.