146 lines
3.6 KiB
Markdown
146 lines
3.6 KiB
Markdown
# Displays
|
|
|
|
## Definition
|
|
|
|
A **Display** encapsulates **reusable, UI-only display logic**.
|
|
|
|
In this codebase, a Display is a **Frontend Value Object**:
|
|
|
|
- class-based
|
|
- immutable
|
|
- deterministic
|
|
- side-effect free
|
|
|
|
It answers the question:
|
|
|
|
> “How should this specific piece of information be shown?”
|
|
|
|
Displays are **not screen-specific**.
|
|
They exist to avoid duplicating presentation logic across View Models.
|
|
|
|
**Naming Convention:**
|
|
- Displays MUST end with `Display` suffix
|
|
- Displays MUST be reusable across multiple screens
|
|
- Valid examples: `PriceDisplay`, `EmailDisplay`, `RatingDisplay`
|
|
- Invalid examples: `DashboardRatingDisplay`, `UserProfileDisplay`
|
|
|
|
---
|
|
|
|
## Responsibilities
|
|
|
|
A Display MAY:
|
|
|
|
- format values (money, dates, durations)
|
|
- handle localization only when localization inputs are deterministic (for example: mapping stable codes to stable labels)
|
|
- map codes to labels
|
|
- encapsulate UI display conventions
|
|
- be reused across multiple View Models
|
|
|
|
In addition, a Display MAY:
|
|
|
|
- normalize presentation inputs (for example trimming/casing)
|
|
- expose multiple explicit display variants (for example `shortLabel`, `longLabel`)
|
|
|
|
A Display MUST:
|
|
|
|
- be deterministic
|
|
- be side-effect free
|
|
- operate only on presentation data
|
|
|
|
A Display MUST:
|
|
|
|
- be implemented as a **class** with a small, explicit API
|
|
- accept only primitives/plain data in its constructor (or static factory)
|
|
- expose only primitive outputs (strings/numbers/booleans)
|
|
|
|
---
|
|
|
|
## Restrictions
|
|
|
|
A Display MUST NOT:
|
|
|
|
- contain business logic
|
|
- enforce domain invariants
|
|
- perform validation
|
|
- influence system behavior
|
|
- be sent back to the server
|
|
- depend on backend or infrastructure concerns
|
|
|
|
In this repository, a Display MUST NOT:
|
|
|
|
- call `Intl.*`
|
|
- call `Date.toLocaleString()` / `Date.toLocaleDateString()` / `Date.toLocaleTimeString()`
|
|
|
|
Reason: these are runtime-locale/timezone dependent and cause SSR/hydration mismatches.
|
|
|
|
## Localization rule (strict)
|
|
|
|
Localization MUST NOT depend on runtime locale APIs.
|
|
|
|
Allowed approaches:
|
|
|
|
- API returns the exact labels/strings for the current user context.
|
|
- Website maps stable codes to stable labels using a deterministic table.
|
|
|
|
Forbidden approaches:
|
|
|
|
- any usage of `Intl.*`
|
|
- any usage of `toLocale*`
|
|
|
|
If a rule affects system correctness or persistence,
|
|
it does not belong in a Display.
|
|
|
|
---
|
|
|
|
## Ownership & Placement
|
|
|
|
- Displays belong to the **presentation layer**
|
|
- They are frontend-only
|
|
- They are not shared with the backend or core
|
|
|
|
Placement rule (strict):
|
|
|
|
- Displays live under `apps/website/lib/display-objects/*`.
|
|
- Filenames MUST match the class name with `.tsx` extension (e.g., `RatingDisplay.tsx` contains `class RatingDisplay`)
|
|
|
|
---
|
|
|
|
## Relationship to View Models
|
|
|
|
- View Models MAY use Displays
|
|
- Displays MUST NOT depend on View Models
|
|
- Displays represent **parts**
|
|
- View Models represent **screens**
|
|
|
|
Additional strict rules:
|
|
|
|
- View Models SHOULD compose Displays.
|
|
- Displays MUST NOT be serialized or passed across boundaries.
|
|
- They must not appear in server-to-client DTOs.
|
|
- Templates should receive primitive display outputs, not Display instances.
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
Displays SHOULD be tested because they often contain:
|
|
|
|
- locale-specific behavior
|
|
- formatting rules
|
|
- edge cases visible to users
|
|
|
|
Additionally:
|
|
|
|
- test determinism by running the same inputs under Node and browser contexts (where applicable)
|
|
- test boundary rules (no `Intl.*`, no `toLocale*`)
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
- Displays encapsulate **how something looks**
|
|
- View Models encapsulate **what a screen needs**
|
|
- Both are presentation concerns
|
|
- Neither contains business truth
|
|
|
|
In one sentence: Displays are **Value Objects for UI display**, not utility functions. |