VAI-CLIP Desktop UI Design System
Status: Active project-level standard
Applies to: all desktop clinical and operational workspaces
Last updated: 2026-10-27
Canonical language: English. desktop_ui_design_system.zh-CN.md is the complete Chinese translation. Update both files in the same pull request.
This is the shared standard for VAI-CLIP desktop UI. It defines how pages look and behave; domain PRDs define business fields, permissions and workflow rules.
Reception and Registration Queue
(PatientIntakeWorkflowApp) is the main presentation
reference: compact filters, a full-width el-table,
patient-first rows, a clear next action, AppDialog and
Element Plus loading. Reuse its UI approach, not its Registration
workflow.
1. Scope and required rules
Use this guide in this order: choose components in §3, arrange the page with §4, then verify with §5.
Mandatory adoption
- All new or renamed desktop pages comply from their first merge.
- Existing Vue components are renovated only when the page/component UI work is explicitly requested. Once requested, migrate the whole affected component; do not add or keep old native controls beside Element Plus controls.
- Keep existing Element Plus form controls that already meet this standard; do not replace them solely because a UI renovation is underway. When migrating a native form control to Element Plus, remove the original control and its control-specific markup, classes and CSS rules in the same change. Do not leave obsolete styles, hidden legacy controls or parallel styling paths behind.
- Use existing shared components when they fit:
AppWindowfor the app shell,AppDialogfor task dialogs,IconActionButtonfor eligible icon-only controls,PatientEmrLinkfor patient navigation,PatientIdentityHeaderfor the linked clinical identity block andWorkspaceSectionHeaderfor section headers. - Use Element Plus for buttons, forms, inputs, selects, date/time pickers, checkboxes, radios, switches, tables, pagination, tooltips and feedback. Tailwind is for layout and spacing, not a second control system.
- Native
inputis allowed only for browserfileandcolorselection. A static document table is allowed only when it is not interactive and hasdata-ui-static-table-reason. - A specialised canvas, editor or calendar may use custom semantic controls only when Element Plus cannot provide that interaction. Record the reason and accessibility approach in the owning component documentation.
Legacy pages and existing local styles are migration candidates, not examples for new pages. This standard does not automatically start their renovation; a delivery deadline or existing code is not an exception once renovation has been explicitly requested.
Existing-module compatibility
Do not change an existing module's control height, spacing or layout solely to match this standard when its current presentation has no evident clipping, overlap, display defect or alignment problem. Preserve a working established layout unless the requested work needs that area to change.
Apply the current standard to new, replaced or materially restyled controls, and to controls changed to resolve a visible usability or alignment defect. When an existing action group is changed, make the changed group internally consistent rather than introducing a new mixed-height result.
Responsive resizing preserves an approved toolbar’s row grouping, action order and record/action relationship. Shrink flexible search/content widths and truncate nonessential long text before moving actions onto separate rows. The Consultation attachment toolbar keeps search/upload/more together and count/filter/sort together; catalogue results keep their actions beside the item. Existing explicitly approved alternate layouts for navigation, forms and galleries remain separate contracts.
UI renovation boundary
| Work | Required boundary |
|---|---|
| New desktop page | Follow this standard in full from the first merge. |
| Existing page UI renovation | Start only with an explicit page/component renovation request. Apply this standard to the requested and changed area while keeping its business behaviour; preserve stable unaffected legacy layout under Existing-module compatibility. |
| UI-only change | Do not change fields, validation rules, permissions, state transitions, API contracts, audit behaviour or authorised workflow steps. |
| Business change needed | Define and approve it in the domain PRD before implementation; it is not part of a visual renovation. |
Before renovating an existing page, identify its current key actions and states. After the UI change, verify the same authorised workflow still works, including success, validation failure, permission denial and recoverable server error where applicable.
Renovation request template
Use this instruction when requesting an existing desktop page or component renovation:
Redesign the desktop UI of [module/page/component] according to agent_docs/product/desktop_ui_design_system.md. Use Element Plus and shared components to standardise forms, tables, buttons, dialogs and feedback. Change UI only; do not change existing fields, permissions, state transitions, API contracts, audit behaviour or business workflows.
2. Common look and feel
- Keep the interface compact, clear and task-focused. Use white content surfaces, a pale workspace background and light dividers. Do not add repeated titles, decorative KPI cards, large hero areas or unnecessary nested cards.
- Use the same size, colour, radius and interaction for the same kind of control across modules. Reuse shared CSS variables and components; do not copy page-local hex colours or invent a local visual system.
- State must include text. Colour and icons support meaning but never carry clinical, operational or financial meaning alone.
- Show one active UI language on each screen through the project translation mechanism. Do not mix English and Chinese labels, validation messages or date formats in one workflow, apart from established codes and identifiers.
Style ownership
- Default to Tailwind utility classes for layout and spacing, and to
the owning Vue component's
<style scoped>block for module- or page-specific visual rules. Keep selectors narrow and tied to the component's markup. - Do not add module- or page-specific rules, bespoke control variants,
or feature-named selectors to
varclip_vue/src/assets/main.css. main.cssis reserved for Tailwind layer setup, shared design tokens, application-wide base rules, and global Element Plus theme adjustments that apply consistently across the application. It must not become a collection of page implementations.- If a visual rule is genuinely needed by two or more independent pages, first reuse or extract a shared component. Add a shared token or global rule only when a scoped component implementation cannot express the cross-application requirement; document why it is global in the CSS comment.
| Item | Standard |
|---|---|
| Radius | 6px controls; 8px cards, tables and rows; 12px dialogs/drawers; pill shape only for badges |
| Height | Use 32px by default. Controls in the same filter row, form row or action group must use the same height. Use 36px only when a documented usability requirement needs a larger target; use 40px only for a deliberately prominent main workflow or confirmation action. |
| Type | Page title 18–20px; section title 16px; body, fields and table values 14px; supporting text at least 12px |
| Spacing | 4px rhythm; 16px normal section spacing; 12–16px field groups; 8px button groups |
Do not use text-xs as the only readable label for a
clinical, financial or destructive action.
2.1. Colour system and semantic tokens
User correction, 14 October 2026: primary actions, active navigation, selection and focus follow the colour theme selected in Personal Settings. Do not hardcode purple in an individual workspace. The palette below remains the semantic/category reference adopted on 8 October; its purple primary values are reference examples, not an override of the selected system theme. Existing-page renovation boundaries in §1 still apply.
The supplied clickup_inspired_color_system.md is the
source proposal. The four gradient endpoints are published in ClickUp's brand guidelines, checked
on 8 October 2026. The UI tokens and 60 tag colours are our adopted
ClickUp-inspired specification, not a claim about ClickUp's internal UI
tokens. Use VAI-CLIP identity and the existing typography, spacing,
radius and component standards.
Separate three purposes: brand accents express identity; semantic colours express actions and states; category colours distinguish labels. A module's icon or header may have an identity accent, but must not recolour its primary buttons, selections, warnings or clinical risks.
| Shared token | HEX | Purpose |
|---|---|---|
--ui-primary |
#6647F0 |
Primary action, active navigation and selection accent |
--ui-purple |
#7B68EE |
Secondary decorative accent |
--ui-pink |
#FD71AF |
Decorative accent |
--ui-blue |
#0091FF |
Information accent; readable links use the stronger variant below |
--ui-cyan |
#49CCF9 |
Decorative accent |
--ui-yellow |
#FFC800 |
Decorative accent, not a new warning state |
--ui-success |
#00B884 |
Success/completion accent |
--ui-warning |
#FFB800 |
Warning/pending-review accent |
--ui-error |
#F7685B |
Error/risk accent |
--ui-background |
#FFFFFF |
Page and task surfaces, inputs and tables |
--ui-surface |
#F7F8FA |
Workspace canvas and supporting panels |
--ui-border |
#E4E7EC |
Decorative dividers and surface boundaries |
--ui-text-muted |
#64748B |
Supporting text on white |
--ui-text |
#292D34 |
Body text, headings and dark foreground |
The warm brand gradient is
linear-gradient(90deg, #FF02F0, #FC6D2D); the cool brand
gradient is linear-gradient(90deg, #6647F0, #0091FF).
Reserve them for small identity/decorative areas. Routine commands,
tables, status badges and clinical alerts use solid or pastel semantic
colours. Place text on a solid readable surface rather than assuming
every gradient stop has adequate contrast.
2.2. Readable variants and interaction states
The following VAI-CLIP variants complement the supplied accent colours. Use them consistently rather than selecting a different shade per page.
| Role | Background token / HEX | Foreground token / HEX |
|---|---|---|
| Primary button | --ui-primary / #6647F0 |
--ui-on-primary / #FFFFFF |
| Primary hover / pressed | --ui-primary-strong / #5B21B6 |
--ui-on-primary / #FFFFFF |
| Selected row, tab or option | --ui-primary-soft / #EDE9FE |
--ui-primary-strong / #5B21B6 |
| Information badge / alert | --ui-info-soft / #DBEAFE |
--ui-info-strong / #1E40AF |
| Success badge / alert | --ui-success-soft / #DCFCE7 |
--ui-success-strong / #166534 |
| Warning badge / alert | --ui-warning-soft / #FEF3C7 |
--ui-warning-strong / #92400E |
| Error / risk badge / alert | --ui-error-soft / #FFE4E6 |
--ui-error-strong / #9F1239 |
| Destructive filled button | --ui-error-strong / #9F1239 |
--ui-on-primary / #FFFFFF |
| Muted text on a supporting panel | --ui-surface / #F7F8FA |
--ui-text-muted-on-surface / #475569 |
- Primary actions and selection use the current system theme through shared primary tokens. Purple is used only when selected by that theme. Links remain recognisable; success, warning and error colours retain their domain meaning independently of the selected accent.
- Secondary and Cancel buttons use white, neutral text and a neutral
border; tertiary actions are ghost. Neutral hover uses
--ui-surface. Use the stronger semantic colour for meaningful icons or text on white; keep the vivid accent for decorative details or a separately verified foreground/background pair. - Focus uses a visible
--ui-primaryoutline with separation from the control fill. Selection includes a check, indicator,aria-selectedoraria-pressedas appropriate. Disabled controls use neutral styling and the component's actual disabled behaviour; do not depict them as success or error. Loading keeps the action's role and shows progress without permitting a duplicate command. - Normal text needs at least 4.5:1 contrast against its actual background; essential control boundaries and focus/selection indicators need at least 3:1 against adjacent colours. Follow WCAG text contrast and non-text contrast. A decorative light divider is not a sufficient boundary when that boundary is needed to identify an input.
- Calculated solid-colour examples: white on primary purple is
approximately 5.64:1. White on the proposed success, warning and error
accents is approximately 2.56:1, 1.73:1 and 2.96:1, so those are not
white-text button defaults. Bright blue on white is approximately
3.23:1, so ordinary link text uses the darker variant. Muted
#64748Bon#F7F8FAis approximately 4.48:1; use--ui-text-muted-on-surfacethere. Check actual composited colours when opacity, images or gradients are involved. - Status badges use the shared Element Plus tag treatment: at least
24px high, 12px text, 18px line height, 2px/8px padding and a pill
radius. Use the semantic foreground/soft-background pairs above with a
matching light border; neutral states use
--ui-text-muted-on-surfaceon--ui-surfacewith--ui-border. Keep these colours stable when the action theme changes. - Clinical, operational and financial state always includes a readable label; colour is supporting information. Category colours cannot override a recall, allergy, validation failure, payment blocker or other domain-defined risk/status.
2.3. Category and tag palette
Use this shared 60-colour palette for an existing or separately requested category/tag colour capability. Ten families each have six fixed shades. It does not introduce a colour picker, custom-field feature, priority model or new workflow state by itself.
| Family | 1 (Lightest) | 2 | 3 | 4 | 5 | 6 (Darkest) |
|---|---|---|---|---|---|---|
| Red | #FFE4E6 |
#FDA4AF |
#FB7185 |
#F43F5E |
#E11D48 |
#9F1239 |
| Orange | #FFEDD5 |
#FDBA74 |
#FB923C |
#F97316 |
#EA580C |
#9A3412 |
| Amber | #FEF3C7 |
#FCD34D |
#FBBF24 |
#F59E0B |
#D97706 |
#92400E |
| Yellow | #FEF9C3 |
#FDE047 |
#FACC15 |
#EAB308 |
#CA8A04 |
#854D0E |
| Green | #DCFCE7 |
#86EFAC |
#4ADE80 |
#22C55E |
#16A34A |
#166534 |
| Teal | #CCFBF1 |
#5EEAD4 |
#2DD4BF |
#14B8A6 |
#0D9488 |
#115E59 |
| Cyan | #CFFAFE |
#67E8F9 |
#22D3EE |
#06B6D4 |
#0891B2 |
#155E75 |
| Blue | #DBEAFE |
#93C5FD |
#60A5FA |
#3B82F6 |
#2563EB |
#1E40AF |
| Purple | #EDE9FE |
#C4B5FD |
#A78BFA |
#8B5CF6 |
#7C3AED |
#5B21B6 |
| Pink | #FCE7F3 |
#F9A8D4 |
#F472B6 |
#EC4899 |
#DB2777 |
#9D174D |
The default category badge pairs shade 1 as background with shade 6 as text. A selected shade is not automatically its text colour; choose a separately contrast-verified foreground. When a colour picker is in scope, show a label/tooltip, keyboard-visible focus, a non-colour selection indicator and the selected colour value. Persist the normalised HEX value through the owning feature's existing contract rather than a palette position; no database change is implied by this specification.
| Illustrative label | Background | Text |
|---|---|---|
| Development | #EDE9FE |
#5B21B6 |
| Design | #FCE7F3 |
#9D174D |
| Bug | #FFE4E6 |
#9F1239 |
| Documentation | #DBEAFE |
#1E40AF |
| Research | #CCFBF1 |
#115E59 |
| Planning | #CFFAFE |
#155E75 |
These are examples, not new required labels. The source's In Review and Approved examples use the warning and success pairs in §2.2 when they represent an actual workflow state; such states do not receive freely chosen category colours.
2.4. Vue / Element Plus implementation and adoption
- Define the shared tokens once in
varclip_vue/src/assets/main.css. The tables above provide reference palette values; active primary values come from Personal Settings. Define theme variables at document level so body-mounted dialogs and popovers inherit them. Switching themes updates already-open workspaces, and reloading restores the saved choice. Map--el-color-primaryand its derived variants to the current system theme; map semantic text/button colours to the readable information/success/warning/error variants, with corresponding soft fills. Update all Element Plus light/dark state variants together so hover, plain, link, tag and alert styles do not retain old colours. - Map
--workspace-surfaceto--ui-background,--workspace-surface-mutedand--workspace-canvasto--ui-surface, and the shared text/border tokens to their corresponding UI tokens. Meaningful control boundaries use a stronger contrast-verified border when necessary. Preserve existing layout and clinical identity-header semantics within the renovation boundary. - A touched primary action must use the shared primary token. Remove
module-gradient overrides for that action, including inheritance through
--app-primary-button-background; do not leave a competing theme path. Keep launcher/icon identity gradients separate from command styling. - Use Vue, Element Plus, shared components and Iconify under §1 and §3. The source's React picker/tag components and standalone button CSS are illustrations, not project implementation templates. They do not replace the existing 6px control radius, control heights, component resolver or accessibility contracts.
- Apply this palette to new or materially restyled controls going forward. A site-wide migration is separate implementation work; record migrated scope, focused checks, deployment and acceptance separately. Do not change domain fields, permissions, transitions or audit behaviour to adopt colours.
2.5. Desktop icon gradient palette
The separate desktop
icon gradient library, supplied as
clickup_60_ui_gradients.md and adopted on 8 October 2026,
contains the 60 numbered variants with their names, exact stops, angles
and CSS variables. Use it for desktop app icon backgrounds. The library
owns gradient values; this design system owns shared control and
interaction styling. It is distinct from the solid category/tag palette
in §2.3.
Keep icon identity gradients separate from command buttons, selections, clinical alerts and status colours. Apply the existing Iconify, readable-label and actual-gradient contrast rules. App-to-gradient assignments and application migration are separate implementation work; this saved palette does not establish either.
3. Common components and interactions
| Need | Use | Do not use |
|---|---|---|
| Command or submit | el-button or a compatible shared wrapper |
Native button styling system |
| Data entry and validation | el-form, el-form-item and the suitable
Element Plus control |
Raw inputs or toast-only validation |
| Interactive records | el-table and Element table controls |
Hand-built interactive HTML table |
| Dialog with fields, review or async work | AppDialog |
Feature-local dialog shell |
| Short confirmation without input | ElMessageBox.confirm |
Custom confirmation dialog |
| Result, warning or error | ElMessage, el-alert,
ElNotification |
Page-local toast/banner system |
| Loading or empty state | v-loading, el-skeleton,
el-empty |
Full-page spinner for a bounded task |
| Paging or clipped supporting text | el-pagination, el-tooltip or the shared
ellipsis tooltip |
Hand-built paging, native title tooltip or silent clipping |
Actions and icons
- Every command button uses a meaningful Iconify icon, preferably
mdi:. Primary, clinical and financial actions also keep visible text. Render the named official glyph with its native viewBox and SVG geometry; do not substitute a related symbol or collapse show/hide, enabled/disabled, locked/unlocked or clinical instrument variants into the same image. Bundle used glyphs locally so command icons do not depend on an external icon API; an unknown name must be detectable and corrected before release. - Approved Reception row treatment: keep 28px commands visible with a readable base row height. Primary actions, Print label and Edit/Adjust retain text and meaningful icons; Previous, attachments and injection-record entry may use labelled icon controls with hover/focus tooltips and visible keyboard focus. Preserve existing permission/state conditions; this exception does not change clinical submission controls or command styling elsewhere.
- Use one primary action in each task area. Secondary actions are neutral/bordered, tertiary actions are ghost, Cancel is secondary and red is destructive only.
- Icon-only controls are limited to familiar utilities such as Close,
Back, Refresh and Overflow. They need an
aria-label, hover/focus tooltip, keyboard-visible focus and correct disabled/loading behaviour. - Tabs, filters, calendar cells, option groups, pagination and selectable rows are already controls. Do not add decorative icons to them.
- Keep row, section and editor actions near their object. In
administration headers, use
Refresh → Bulk import → New. Imports, exports and reporting are secondary work: state their scope, permission, validation, duplicate handling and result.
Forms and tables
Every editable field has a visible label, required/optional meaning and field-level validation. A placeholder is only an example or format hint.
Use the correct Element date, range or date-time control. Define display format, submitted format, timezone, clearing behaviour and start/end validation. Do not treat a date-only value as a timezone-aware event time.
Keep recoverable input after a server error. Focus the first actionable error after submit. Show loading on the submit button and prevent duplicate submission.
Tables are white, full-width, lightly bordered and 8px rounded. Use a muted 12px header, 14px rows, clear horizontal dividers and a stable rightmost Action column. Amounts are right aligned with an explicit unit/currency.
Monetary displays use exactly two decimal places, including zero; missing prices use an em dash or an explicit unavailable label. Preserve original input and calculation precision. Use the shared
formatUiAmount/formatUiCurrencyformatters; quantity and clinical measurement formats remain independent. Canonical contract: Platform monetary display.Make the current clinic, filter scope, result count and pagination visible for lists that can cross patients, visits or financial records. Keep the table structured on narrow desktop windows with an inner scroll or an approved alternate view.
Make loading, empty, no-match, error and permission states distinct. A failed search clears stale actionable selection; creating a patient after no match must follow the authorised duplicate-check workflow.
Organization tree tables use a separate narrow column for expand controls. Keep names and codes in one content column and indent only child groups. Headers, cells and Action buttons share the same content edge. Empty Labs keep the table structure. Verify 1920, 1366, 1280 and narrow desktop widths.
Shared record-list presentation (2026-10-27)
The confirmed reference for comparable record lists is Reception and Registration Queue. Apply the same presentation to front-desk, Consultation, Cashier, Lab, pharmacy, catalogue and administrative record lists. Keep each list's columns, permissions, filters, sorting and business actions.
- Use a 16px semibold page heading, 32px filter controls, a white table with 8px corners, a 40px base header with 12px semibold text, and 72px base record rows with 14px text. Allow taller rows for necessary wrapped content; do not hide patient identity, status or amounts to force a fixed height.
- Keep row commands in the rightmost Action column at 28px minimum
height with 6px gaps. Open and financial/clinical commands retain text
and icons. Familiar attachment/utility entries may use the shared 28px
IconActionButton, with a label, hover/focus tooltip and visible keyboard focus. A narrow window may wrap commands inside the cell; it must not clip or overlap them. - Filters and pagination wrap within the available width. Wide data stays horizontally scrollable while fixed Action columns remain usable. Long identifiers wrap or use the established tooltip; they must not push controls outside their cells.
- Reuse the explicitly applied
workspace-list-*classes inworkspace-lists.css. A shared stylesheet is needed because these independently owned record-list components cannot share one table wrapper without changing their column slots and interactions. Do not apply the rules globally to all tables. Existing native record grids receive the common presentation; this visual alignment does not claim a completed migration of their controls to Element Plus. - Editable invoice lines, clinical editors, report aggregates, permission matrices and calendar canvases retain the geometry required for their tasks. Their distinct data structures do not exempt comparable record lists inside them from the shared list presentation.
Choice groups
- Use
AppChoiceGroupfor small mutually exclusive bordered choices. Available options share equal-width columns and equal height; the group owns spacing, and labels wrap in full. When its content area is too narrow, stack options vertically. Retain Element Plus radio semantics, keyboard selection and the original values/permissions. - Command buttons keep content-based widths; icon-only utilities use
IconActionButton. Do not apply equal-width option styling to every command group.
Dialog, feedback and loading
AppDialogowns the dialog structure and scrolling body. Backdrop close is disabled. Escape may close only a read-only or clean dialog; it must never lose entered data, a pending command or a required review.Compare edited fields with the loaded baseline. Escape, close, Cancel, object changes and window close share one leave check. Clean forms leave directly; edited forms offer Continue editing and Discard changes. Cancelling keeps input and restores the field focus. Validation failures remain dirty; confirmed saves reset the baseline. Pending or unknown writes block leaving. Concurrent close attempts and changes of identity, object or write state invalidate an earlier confirmation.
Patient search results expose native focusable selection buttons with patient identification, Enter/Space activation, selected semantics and visible focus. Button activation does not also trigger row selection; existing patient-context and unsaved-work checks still apply.
Use
DialogFooterfor standard action footers: 20px horizontal and 12px vertical padding, an 8px gap, right alignment, a top divider and wrapping without clipped labels/focus rings. The footer stays outside the scrolling body. Do not place bare buttons directly in#footer; do not add a second padded wrapper to an existing complete footer. Preserve explicit custom editor footers.Use
ElMessageBox.confirmonly for a short choice without extra input. UseAppDialogwhen a reason, record summary, checklist, review or async result is needed.Use
ElMessageonce after an action completes: success after server confirmation, warning for an actionable non-blocking issue and error for failure. Useel-alertfor persistent local context.When a page or dialog has a scrollbar and feedback refers to a specific field, record, alert or blocker, scroll that item into view. Focus the field when it needs correction; a toast alone must not leave the user to find the relevant information.
On first load, use a skeleton or clear loading state. While refreshing a list, keep the table frame and mark it busy; do not present stale rows as current results.
4. Page layout and common patterns
| Page area | Rule |
|---|---|
| App shell | Reuse AppWindow; keep business actions and state out of
the window bar |
| Page header | One compact title, primary navigation and global tools; Settings is at the far right only when it is a real permitted capability |
| Filters | Keep search, date, doctor, clinic and status filters above or beside the list they change. Separate editing submissions from filters; Reception may group Refresh and Add appointment at the toolbar end to preserve list height |
| Object context | Put patient, visit, invoice or prescription identity above single-object work; show actions on the right |
| Content | Use white task surfaces, neutral section headings and one main scroll area |
| Decision | Keep current amount or blocker with Cancel and one primary action; use a fixed footer only in a long workflow that owns it |
Catalogue selection searches (confirmed 2026-11-06): A blank or whitespace-only search must not populate an entire catalogue by default. Show a brief instruction to enter a name/code, select a specific category/vendor/account, or open an explicit history/browse source. Clear old candidates immediately when the query is cleared; invalidate in-flight responses so they cannot repopulate the list. Keep selected values and their labels visible while filtering. Apply this to service/Lab/Imaging, medication, package, vaccine and related procurement, stock-count, recall, pricing and clinic-request pickers. Minimum query lengths already required by a domain remain in effect. Operational queues, management tables and small finite configuration choices retain their normal list behavior; an explicit category or history action may show its scoped options.
List pages normally follow header → filters → content. Object work follows header → context → content → decision. Keep Settings return context, filters and pagination. Put search above its list, table next-step actions at the right, and pagination at the bottom.
Show patient/object name first, identifier/source second and state/actions on the right. Do not hide identity, amount, risk or current blockers. A patient link must have a stable ID and return context, and must not activate its selectable row.
Taskbar window selectors distinguish the active, non-minimized window with a solid shared-primary-strong background, readable on-primary text and a persistent underline. Keep the app identity icon/strip, neutral inactive buttons and reduced icon emphasis for minimized windows. Hover must not erase selection; keyboard focus remains visible on both selected and inactive buttons in Bottom and Left layouts.
The linked eMR, Consultation and Cashier family retains each app’s
original icon gradient in its title bar (eMR blue/cyan, Consultation
pink/coral, Cashier orange/red), with the original white title text and
app/link icons, shared solid primary controls, neutral content surfaces
and one PatientIdentityHeader: 36px initials avatar, 18px
semibold primary name, optional 14px Chinese name, and at least 12px
identity details. Use the same name fallback, date format and sex
wording; recorded PN and MRN remain distinctly labelled.
Consultation/Cashier add the current Chit; historical eMR browsing
remains patient-scoped. Semantic risks and financial gates keep their
existing meaning and colours. Compact Consultation uses a bounded
Patients drawer instead of an initials/minute rail; opening or closing
this presentation retains the editor, and actual visit selection uses
the existing guard.
| Pattern | Use | Required shape |
|---|---|---|
| Appointment | Time and resource scheduling | Date and view controls above the calendar; detail follows Time → Patient → Details → Actions; editor groups Patient → Appointment → Payment arrangement → Resources/plan → Notes |
| Registration | State queue with a next step | State/count and search/doctor/date toolbar; full-height queue; patient link opens eMR while the row action handles the visit; dialog keeps patient context and the current next action |
| Cashier | List to full-width object work | Compact list filters, full-width list/detail, patient/invoice identity, aligned charge/payment table and a fixed decision footer when needed |
| Drug Dispensing | Queue plus staged task | Narrow selection queue; right side shows context → progress → blocker → current stage → next action; keep prescription, medicine details and remarks separate |
These patterns define layout only. Fields, permissions, state changes and completion rules remain in the domain PRD.
4.1. Confirmed cross-workspace refinement (27 October 2026)
- App icon/title-bar identity colours are independent of ordinary commands. AppWindow content, teleported dialogs and popovers inherit Personal Settings primary tokens; a clinical workspace must not override them with fixed purple or an icon gradient. Existing success, warning and destructive actions retain their semantics.
- Packages uses one content heading and one section-navigation group. Patient Wallet, Sell and Consume share one patient-search/context area; search controls align in one row where space permits. The unselected state gives one clear next step, without a second empty card repeating the same instruction. Package Setup stays independent of patient selection; sales, reservations and identity checks keep their existing guards.
- Clinical Documents has one primary patient/encounter binding entry when unbound, with concise context guidance. Template management remains reachable under its existing permission and draft protections.
- Calendar and Consultation show a compact summary of practitioner selection; expanded filters remain accessible and retain their meaning. Doctor category colours remain separate from action-theme and appointment-status colours; the versioned doctor palette contract is maintained in Frontoffice.
- Tasks and record-access lists reserve sufficient width for complete action labels and icons. Never break an action word across lines; use a safe table scroller or wrap complete buttons when necessary.
- ICD Mapping and eMMS prioritise their input/review work over large decorative headers or repeated instructional cards. Advisory-only, unmapped-result and clinical-confirmation cautions remain visible next to the relevant work. Copilot presents a compact initial suggestion set with an explicit expansion control and displays the actual unavailable/quota reason next to its disabled input.
- Insurance keeps useful card images while consolidating repeated names and lengthy context explanations. Package types and fulfilment triggers use readable translated labels without changing stored enum values. Price presentation uses two decimal places without changing calculation precision or inventory quantities.
5. Development and acceptance
- Check desktop UI at 1920×1080 in the configured official Chrome local-service workflow, then at 1280px, 1366×768 and a narrow App window. Check visual layout together with browser console, network and API errors.
- Keep keyboard order aligned with the task order. Use
focus-visible, hover/focus tooltips, adequate contrast andprefers-reduced-motion. Wrap lower-priority controls before shrinking critical text or clipping labels. - If a second page needs the same control, extract or reuse a shared
component. Use the configured Element Plus resolver; do not add global
app.use(ElementPlus)or the global Element Plus stylesheet. - Run component-contract/UI compliance verification only when it is
explicitly requested. When requested, new, renamed, migrated or
UI-touched components need the full
--filescheck, relevant browser evidence and documented safety/business exceptions. - For an existing-page renovation, test the unchanged key workflow before handoff: the same fields, permissions, state changes, API requests and audit result must remain available unless an approved domain change says otherwise.
- When an existing-page renovation is explicitly requested, prioritise active patient, clinical and financial workflows. A migration fixes the full changed component instead of placing a new design system beside legacy controls.
Before handoff, check: page and action placement; shared tokens; Element Plus controls; icon accessibility; form/table/dialog/feedback states; search and bulk-action scope; meaningful text without clipping; loading, empty, error, permission and disabled states; and desktop visual evidence. See component compliance verification for executable checks.