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

07 - Component Library (Houses Module)

Module-specific widgets on top of the shared library in 00-shared/03 (Component Library) and tokens in 00-shared/02 (Design Tokens). Shared primitives reused here (not redefined): AppListPage, AppCard, AppListTile, AppButton, AppTextField, AppBottomSheet, AppDialog, AppMenu, AppFAB, AppSkeleton, AppEmptyState, AppOfflineBanner, AppSnackbar, AppPagination, AppChips, AppBadge, AppAvatar.


1. HouseColorCard (list grid card)

PropTypeDefault
houseHouse-
onTapVoidCallback?-
onEdit / onDeleteVoidCallback?null (hidden when null)
selectedColorColorresolved via HouseColorResolver (11 §3)
  • Layout: 16 dp swatch strip on top (height 56), name (titleMedium), code chip + motto 1-line ellipsis (bodySmall muted).
  • States: default / pressed (elevation+ m-fast) / loading skeleton variant.
  • a11y: semantics label "House <name>, code <code>"; never color-only.
  • Gesture: tap → detail; AppMenu (ellipsis top-right, admin only).

2. HouseHeader (detail banner)

PropType
houseHouse
actionsList<Widget> (menu)
  • Full-width banner painted with resolved house color; dark scrim for contrast (06 §2.5); name displayLarge white, code chip onPrimary, motto italic.
  • Skeleton variant height 180.
  • a11y: banner is decorative; name/code/motto are real text nodes.

3. MemberTile (member row)

PropType
admissionNumberString
name (from joined student record, (planned) fuller payload)String?
onTapVoidCallback?
  • AppAvatar with initials (deterministic hue from admission number - not house color, keeps house swatch meaningful), leading badge AppBadge "member".
  • Row shows admissionNumber; name only when the students payload provides it (today the list returns full student docs - student.schema.ts:16-63 - so name must be derived from the linked user, which the houses flow does not resolve; render admissionNumber-first (planned) name enrichment).
  • Empty state variant handled by parent (06 §2.3).

4. ColorPickerField (editor field)

PropType
valueString? (hex #RRGGBB as stored, house.schema.ts:15-16)
onChangedValueChanged<String?>
presetsList<ColorToken> from 11 §3
  • Renders 8 preset swatch buttons (selected ring) + custom hex AppTextField (validates #RRGGBB).
  • Contrast hint: shows pass/warn against white text (00-shared/09).
  • Semantics: each swatch Semantics(button, label: "color <name>").

5. HouseCountBadge (members count)

PropType
countint? (null = unverified)
unverifiedbool
  • Verified (server count, (planned) endpoint): AppBadge "<n> members".
  • Unverified (client join today): "~<n> members" + tooltip "server-side member count planned". Prevents presenting an estimated count as authoritative (06 §2.3).

6. ConflictFieldError (shared, module-configured)

  • Reused from 00-shared/03; rendered under the code field with server message verbatim: House code "X" already exists. (houses.service.ts:19-21).
  • a11y: live-region announcement; focus moves to offending field.

7. DeleteHouseDialog (confirm)

  • Extends AppDialog: title "Delete house?", body lists consequences:
    • Soft delete (houses.service.ts:51-54) - house disappears from lists.
    • Members keep houseId - dangling refs (student.schema.ts:41-42); no server guard/cascade today (planned).
  • Destructive action styled error, confirm text "Delete".
  • a11y: focus trap, destructive-first reading order (00-shared/09).

8. Composition recipes

ScreenComposition
House list (05 §1)AppListPage + HouseColorCard grid + AppPagination + AppFAB
House detail (05 §2)HouseHeader + members header (HouseCountBadge) + MemberTile list
House editor (05 §3)AppBottomSheet/AppDialog + AppTextField x3 + ColorPickerField + AppButton + ConflictFieldError

9. Component inventory vs. shared

WidgetOwned byWhy not shared
HouseColorCardhouseshouse-specific data shape + swatch layout
HouseHeaderhousesbanner composition
MemberTilehouses (student data rendered here)cross-module display concern
ColorPickerFieldhousesfree-string color semantics (server stores any string)
HouseCountBadgehousesverified/unverified duality
DeleteHouseDialoghousesdelete semantics without server guard