docs: add spacing primitives design spec
This commit is contained in:
parent
cf64404d25
commit
c89f526780
1 changed files with 178 additions and 0 deletions
|
|
@ -0,0 +1,178 @@
|
|||
# Go Backend Spacing Primitives Design
|
||||
|
||||
**Date:** 2026-05-10
|
||||
|
||||
**Goal**
|
||||
|
||||
Add fixed-size spacing primitives to the Go backend UI library so templates can insert consistent horizontal and vertical gaps between other components without relying on ad hoc inline markup.
|
||||
|
||||
**Chosen Approach**
|
||||
|
||||
Introduce two small presentational primitives:
|
||||
|
||||
- `SpaceX` for horizontal spacing
|
||||
- `SpaceY` for vertical spacing
|
||||
|
||||
Both primitives will use the same named spacing scale:
|
||||
|
||||
- `xs`
|
||||
- `sm`
|
||||
- `md`
|
||||
- `lg`
|
||||
- `xl`
|
||||
|
||||
This keeps call sites explicit, matches the primitive-oriented structure of the Go UI library, and avoids introducing a child-owning layout abstraction such as `Stack` for this slice.
|
||||
|
||||
**Scope**
|
||||
|
||||
- Add shared spacing step tokens for UI primitives.
|
||||
- Add `SpaceX` and `SpaceY` templ components.
|
||||
- Add stylesheet classes for all supported spacing steps.
|
||||
- Add catalog examples and a dedicated catalog page for spacing.
|
||||
- Add direct UI tests and catalog coverage tests.
|
||||
|
||||
**Out Of Scope**
|
||||
|
||||
- Flexible or grow-to-fill spacers
|
||||
- Stack or layout wrapper primitives
|
||||
- Responsive spacing props
|
||||
- Margin utility generation
|
||||
- Replacing existing manual spacing usage across the app
|
||||
|
||||
**API**
|
||||
|
||||
Add:
|
||||
|
||||
- `type SpacingStep string`
|
||||
|
||||
Supported values:
|
||||
|
||||
- `SpacingStepXS`
|
||||
- `SpacingStepSM`
|
||||
- `SpacingStepMD`
|
||||
- `SpacingStepLG`
|
||||
- `SpacingStepXL`
|
||||
|
||||
Add a shared prop shape:
|
||||
|
||||
- `type SpaceProps struct { Size SpacingStep }`
|
||||
|
||||
Add two primitives:
|
||||
|
||||
- `SpaceX(SpaceProps)`
|
||||
- `SpaceY(SpaceProps)`
|
||||
|
||||
Default behavior:
|
||||
|
||||
- missing or unknown `Size` normalizes to `SpacingStepMD`
|
||||
|
||||
**Rendering Contract**
|
||||
|
||||
`SpaceX`:
|
||||
|
||||
- renders a presentational `span`
|
||||
- includes `aria-hidden="true"`
|
||||
- applies a fixed-width class such as `ui-space-x-md`
|
||||
- uses `display: inline-block`
|
||||
- uses `flex-shrink: 0`
|
||||
|
||||
`SpaceY`:
|
||||
|
||||
- renders a presentational `div`
|
||||
- includes `aria-hidden="true"`
|
||||
- applies a fixed-height class such as `ui-space-y-md`
|
||||
|
||||
These primitives are empty elements. They do not accept children and do not carry semantic meaning.
|
||||
|
||||
**CSS Contract**
|
||||
|
||||
Add classes for each step:
|
||||
|
||||
- `.ui-space-x-xs` through `.ui-space-x-xl`
|
||||
- `.ui-space-y-xs` through `.ui-space-y-xl`
|
||||
|
||||
Class responsibilities:
|
||||
|
||||
- horizontal classes set width only
|
||||
- vertical classes set height only
|
||||
|
||||
Base element behavior should come from the rendered element plus a small shared class contract, not from inline styles.
|
||||
|
||||
Recommended scale for this slice:
|
||||
|
||||
- `xs`: `0.25rem`
|
||||
- `sm`: `0.5rem`
|
||||
- `md`: `0.75rem`
|
||||
- `lg`: `1rem`
|
||||
- `xl`: `1.5rem`
|
||||
|
||||
This is intentionally small and practical for the current design system. If the library later adopts a broader token system, these values can be remapped behind the same API.
|
||||
|
||||
**Normalization And Helpers**
|
||||
|
||||
Follow the existing UI pattern of centralizing normalization logic:
|
||||
|
||||
- add a `normalizedSpacingStep` helper
|
||||
- add `spaceXClass` and `spaceYClass` helpers
|
||||
|
||||
This keeps templ files simple and makes invalid values deterministic.
|
||||
|
||||
**Catalog**
|
||||
|
||||
Add a `spacing` catalog page with examples for:
|
||||
|
||||
- horizontal spacing between two buttons using `SpaceX`
|
||||
- vertical spacing between stacked content blocks using `SpaceY`
|
||||
|
||||
The examples should render the real primitives rather than static HTML snippets.
|
||||
|
||||
**Testing**
|
||||
|
||||
Add UI tests that verify:
|
||||
|
||||
- `SpaceX` defaults to `md`
|
||||
- `SpaceY` defaults to `md`
|
||||
- explicit step selection renders the expected class
|
||||
- spacers render `aria-hidden="true"`
|
||||
|
||||
Add stylesheet coverage checks for:
|
||||
|
||||
- `.ui-space-x-md`
|
||||
- `.ui-space-y-md`
|
||||
|
||||
Add catalog tests that verify:
|
||||
|
||||
- the `spacing` page exists
|
||||
- the first spacing example renders real spacer markup
|
||||
|
||||
**Implementation Notes**
|
||||
|
||||
Files expected for this slice:
|
||||
|
||||
- `go-backend/internal/web/ui/space.templ`
|
||||
- `go-backend/internal/web/ui/space_templ.go`
|
||||
- updates to `go-backend/internal/web/ui/variants.go` or a nearby helper file for spacing normalization
|
||||
- updates to `go-backend/internal/web/ui/catalog/examples.go`
|
||||
- updates to `go-backend/internal/web/ui/catalog/pages.go`
|
||||
- updates to `go-backend/internal/web/ui/ui_test.go`
|
||||
- updates to `go-backend/internal/web/ui/catalog/catalog_test.go`
|
||||
- updates to `go-backend/static/styles.css`
|
||||
|
||||
No application call sites need to change as part of this slice. The deliverable is the primitive itself plus documentation and tests.
|
||||
|
||||
**Open Decisions Resolved**
|
||||
|
||||
- API shape: separate `SpaceX` and `SpaceY`
|
||||
- sizing model: named spacing steps
|
||||
- behavior: fixed width and fixed height only
|
||||
- fallback behavior: default invalid or empty size to `md`
|
||||
|
||||
**Success Criteria**
|
||||
|
||||
This work is complete when:
|
||||
|
||||
- the UI library exposes `SpaceX` and `SpaceY`
|
||||
- both components render stable classes from the shared spacing scale
|
||||
- the spacing catalog page documents horizontal and vertical usage
|
||||
- tests cover primitive markup and catalog registration
|
||||
- the existing Go backend web UI tests remain green
|
||||
Loading…
Reference in a new issue