XDSHeading/XDSText: no responsive `type`/`size` prop — fluid display headlines require a hand-written @media override
- Dominant language
- TypeScript
- Stars
- 13k
- Forks
- 1.1k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 690
Description
## Summary
Neither `XDSHeading` nor `XDSText` can express a **breakpoint-dependent type/size** (e.g. `display-2` on desktop, `display-3` on mobile). Their `type`/`size` props are scalar. So any template that wants a responsive display headline must hand-write a `@media` `fontSize` override via StyleX, which costs Custom CSS points under the template rubric and re-derives values the design tokens already define.
## Repro
`packages/cli/templates/pages/centered-hero/page.tsx` (and identically `gallery-hero/page.tsx`):
```ts
const styles = stylex.create({
titleResponsive: {
fontSize: {
default: 'var(--text-display-2-size)',
'@media (max-width: 640px)': 'var(--text-display-3-size)',
},
},
});
```
…applied as `xstyle` on the headline because there's no prop for it:
```tsx
…
```
Verified the full prop tables: `XDSHeading.type` is `'display-1' | 'display-2' | 'display-3'` (scalar) and `XDSText.type` is `'body' | 'large' | 'label' | 'supporting' | 'code'` (scalar). No responsive/object form, no fluid option.
## Impact
Responsive display headlines are a common pattern (hero/landing templates). Today every such template carries an off-rubric `@media fontSize` block. This is shared by at least `centered-hero` and `gallery-hero`.
## Proposed fix (either)
1. **Responsive object form** for `type`/`size`, mirroring how some XDS props already accept breakpoint maps:
```tsx
```
2. **Fluid display tokens** — make `--text-display-1/2/3-size` `clamp()`-based so display headings scale fluidly with the viewport and the breakpoint swap becomes unnecessary. (`clamp()` is StyleX-supported per CLAUDE.md.)
Either removes the need for the hand-written media query in templates.
## Related, smaller gap (separate but adjacent)
While here: there's also no **directional spacing prop** on layout primitives — `XDSSection.padding` is uniform and `XDSVStack` has no padding prop, so "top-only" spacing (e.g. a hero's top inset) also requires a one-line `paddingTop` custom style. Mentioning for context; can split into its own issue if preferred.
## Context
Found polishing the `centered-hero` page template toward a perfect template-rubric score. Everything else was fixable with pure components (adopting `XDSAspectRatio` for the image, `XDSHeading` for the headline); this responsive-type override is the one genuinely unavoidable custom CSS.
Contributor guide
Assessment
This issue has not been assessed yet.