diff --git a/.github/instructions/ui.instructions.md b/.github/instructions/ui.instructions.md index 709ad03..c72749d 100644 --- a/.github/instructions/ui.instructions.md +++ b/.github/instructions/ui.instructions.md @@ -1,6 +1,53 @@ --- -description: Copilot rules for modifying the UI +description: "Use when modifying the NiceGUI application under src/transcription/ui. Defines ownership and dependency boundaries for UI registration, pages, components, services, persistence, state, and static assets." applyTo: 'src/transcription/ui/**/*.py' --- -The UI is forbidden from directly touching the database. All interactions should be done using the [services](../../src/transcription/services/) +# UI Conceptual Boundaries + +Keep dependencies flowing in this direction: + +`ui/__init__.py` -> `pages` -> `components` + +Pages may depend on application services and framework-provided dependencies. Components may depend on smaller components and shared presentation helpers. Services and domain modules must never depend on the UI. + +## Package Root + +- Keep `ui/__init__.py` as the UI composition root: register global assets, register pages, and mount NiceGUI on FastAPI. +- Do not put feature rendering, service calls, persistence, or route-specific state in the package root. + +## Pages + +- Pages own route registration and route-level orchestration. +- Resolve request or application dependencies, call [services](../../src/transcription/services/), adapt returned data for presentation when needed, and coordinate refresh, navigation, and notifications here. +- Do not query, mutate, commit, or roll back the database from a page. Do not import database engines, sessions, operations, or query-building APIs. Persistence belongs to services or workflow functions. +- Framework dependency types may cross into page handlers only to construct or invoke services; do not pass sessions or session factories into components. +- Keep business rules, lifecycle transitions, transaction boundaries, and cross-service workflows out of page callbacks. + +## Components + +- Components own reusable rendering, widget-local state, input normalization, and presentation-only formatting. +- Expose user actions through typed callback parameters. The calling page decides which service or workflow runs and what refresh or navigation follows. +- Do not register routes, resolve request/app state, instantiate services, or access persistence from components. +- Components may accept ORM models returned by services as read-only snapshots. Only use fields and relationships that the service loaded eagerly; never mutate models, trigger lazy loading, or expose session behavior. +- A component may compose lower-level components, but it must not import from `pages`. + +## Shared UI Infrastructure + +- Keep app-wide navigation and layout primitives in `components/app_shell.py`. +- Keep generic table/event adaptation in `components/table/common.py`; feature-specific columns, row read models, and formatting belong in the feature table module. +- Keep exception normalization and user-facing error display in `components/error_presenter.py`; preserve `AppError` details and operation identifiers at page/component boundaries. + +## CSS Assets + +- Keep CSS under `ui/static` and split it into manageable, feature-oriented files. Do not grow a monolithic stylesheet or embed substantial style blocks in Python components. +- Load each stylesheet from the page, component, or composition root that needs it with `ui.add_css(...)`. Use shared registration only for genuinely application-wide styles. +- Read stylesheet text through `importlib.resources.files(...)` so loading works from installed packages and is independent of the working directory. +- Centralize CSS reading in one typed helper cached by relative resource path with `functools.cache` or an equivalent unbounded `lru_cache`. Cache the immutable stylesheet text to avoid repeated resource I/O during component renders; keep NiceGUI registration decisions at the caller. +- Do not encode application behavior in CSS or other static assets. + +## State and Side Effects + +- Limit component state to ephemeral interaction state such as loading flags, form values, dialogs, and expansion state. +- Application and worker state must be resolved at the page or application boundary and passed through narrow interfaces such as callbacks or notifier protocols. +- Keep filesystem, network, provider, and worker orchestration behind application services or dedicated adapters. UI code may trigger those operations but must not implement them.