Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (Feature Flags Module)

Every screen of the module: intent, route, composition, states, permissions, platform behavior. Authoritative components in 00-shared/03; module-specific widgets in 07_Component_Library.md.

Legend — States: idle / loading / success / empty / error(offline, 401) / disabled / permission. Analytics events follow {module}.{screen}.{action} (proposed; SDK open — 00-shared/10 §8).


1. Flags List (/settings/feature-flags)

FieldDetail
PurposeBrowse tenant toggle catalog; grouped by module; quick-toggle; entry to detail/bulk
EntrySettings hub; deep link with ?module= prefilter
Exitrow → detail; bulk sheet; back → settings
SourceGET /feature-flags (all, sorted key asc — feature-flags.service.ts:11); GET /feature-flags?module= (feature-flags.controller.ts:25-27); tab → GET /feature-flags/enabled (feature-flags.controller.ts:30-34)
CompositionAppSearchBar(optional, client-side), module FilterChips (distinct module values), "Enabled only" toggle tab, grouped list (AppSectionHeader per module), row = AppFlagRow
Statesloading (AppSkeleton(list)); empty (AppEmptyState — fresh tenant); error (AppErrorState); offline (cached + banner); permission (no feature-flags.read → route guarded, 403 screen)
Row actionsswitch (optimistic toggle, PUT /feature-flags), AppMenu: Edit, Delete
Bulk CTAAppButton "Bulk update" (enabled when ≥ 1 selection; selection mode via long-press or checkbox toggle)
Analyticsfeatureflags.list.view, featureflags.list.filter{module}, featureflags.toggle{key,value} (proposed)
Adaptivephone: list full width, selection via long-press; tablet/desktop: master-detail at ≥ 840 px, hover row highlight
a11yeach row Semantics(button, toggled:); module headers announced; filter chips with selected state
Motionm-entrance stagger on rows; switch m-fast

2. Flag Detail (/settings/feature-flags/:key)

FieldDetail
PurposeFull picture of one flag + primary toggle
Entrylist row tap; deep link
Exitedit; delete; back to list
SourceGET /feature-flags/:key → doc; 404 if key missing (feature-flags.service.ts:27-31)
Compositionheader (key mono, module AppBadge, enabled AppSwitch), AppInfoRows: label, description (or "—"), timestamps createdAt/updatedAt (BaseSchema timestamps:true, base.schema.ts:33-34), tenant scoping note; edit AppButton; delete AppButton (destructive, dialog)
Statesloading (skeleton); 404 → AppEmptyState "Flag not found" (deleted/renamed); error; offline
Permissionsread → view; update → toggle/edit enabled; delete → delete (target contract, OQ-5)
Analyticsfeatureflags.detail.view, featureflags.detail.toggle{key,value} (proposed)
a11yswitch semantics; key read as mono code; description in body text
Motionhero from list row (m-slow) — optional; toggle m-fast

3. Flag Editor (/settings/feature-flags/:key/edit) — create + edit modes

FieldDetail
PurposeEdit/create one flag: key, enabled, label, description, module
Entrydetail "Edit"; FAB "New flag" (create mode — key empty)
ExitSave → detail (refresh); discard → back
SourceSave = PUT /feature-flags (upsert — create-or-update, feature-flags.controller.ts:42-46); in create mode a missing key creates a new flag
Compositionform fields per 08_Form_Specifications.md; save AppButton (loading)
Statesedit mode pre-fills from detail doc; create mode empty; saving; validation errors inline; warning banner: description/module are not persisted by the server upsert (feature-flag.repository.ts:40) — see OQ-3
Analyticsfeatureflags.edit.save{key}, featureflags.create.save{key} (proposed)
a11ylabels linked, focus first field, error announce
Adaptivefull-screen page (5 fields); tablet centered column ≤ 560 px
Motionm-base push; save success → check + pop

4. Bulk Update (bottom sheet over list)

FieldDetail
PurposeApply a target state to N selected flags
Entrylist "Bulk update" (≥ 1 selected)
SourcePUT /feature-flags/bulk — body array of UpdateFeatureFlagDto (feature-flags.controller.ts:48-52)
Compositionheader "Update N flags", mode toggle (enable all / disable all), optional label edit (single field applied to all — (proposed); server only persists enabled+label, feature-flag.repository.ts:40), apply AppButton
Resultper-row outcome list (success/fail) — server is sequential, no transaction (feature-flags.service.ts:40-44); failed subset can be retried
Statesidle (count N), applying (progress), done (per-row results), error (partial)
Analyticsfeatureflags.bulk.apply{n,target}, featureflags.bulk.result{n_ok,n_fail} (proposed)
a11ysheet focus trap; progress announced (live region)
Motionm-base sheet; rows fade-in stagger

5. Affected-Features Map (detail companion) — (proposed) client composition

FieldDetail
PurposeShow the end-user surface a flag gates ("turning this off hides: Biometric check-in")
Entrydetail screen "Affects" section / tab
SourceNo backend endpoint — the client composes this from: flag module field, the client's own gated-widget registry (FeatureFlagsCubit keys → screens), and (planned) IMPLEMENTATION_PLAN.md:310-336 matrices. Purely a client-side map; mark results with the module badge.
Statesempty ("no client screens mapped to this key yet") — key is not in the registry
NoteMust not claim server authority; render as informational, (proposed) — hidden when no client registrations exist

Shared components used

AppSkeleton, AppEmptyState, AppErrorState, AppOfflineBanner, AppSnackbar, AppBanner, AppSwitch, AppChips (FilterChip), AppListTile, AppCard, AppButton, AppDialog, AppBottomSheet, AppMenu, AppSectionHeader, AppBadge, AppFAB, AppInfoRow, AppSearchBar.

Module-specific: AppFlagRow, AppFlagGroupHeader, AppFlagEditorForm, AppBulkUpdateSheet, AppFlagKeyChip, AppAffectedMapCard — defined in 07_Component_Library.md.

Analytics events (proposed)

featureflags.list.{view,filter,toggle}, featureflags.detail.{view,toggle}, featureflags.edit.{save,fail}, featureflags.create.{save,fail}, featureflags.bulk.{apply,result}, featureflags.delete.{confirm,cancelled}, featureflags.gate.{blocked,shown} (gate events from FeatureFlagsCubit, proposed).

Keyboard, landscape, tablet, desktop

  • List: phone long-press → selection; desktop hover + right-click menu; N new.
  • Editor: Tab key→enabled→label→description→module→save; Enter submits; Esc discards.
  • Bulk sheet: arrow keys navigate rows; Enter toggles selection.
  • All lists ListView.builder; keyboards avoid insets on phone.