facebook / facebook/astryx

XDSSection/XDSHStack: no overflow or flex grow/shrink props — multi-pane layouts need custom CSS

Open
#2,623 0 comments 0 reactions 1 assignee Claimed by @rubyycheung View on GitHub
component enhancement
Dominant language
TypeScript
Stars
13k
Forks
1.1k
Avg merge
1d 15h
Merged PRs (30d)
690

Description

## Problem

`XDSSection` and `XDSStack`/`XDSHStack` expose sizing props (`width`, `height`, `maxWidth`, `minHeight`) but **no** props for:

- **overflow** (`overflow-x` / `overflow-y` / scroll)
- **flex item sizing** (`flex-grow` / `flex-shrink` / `flex-basis`)

This forces any multi-pane / scrollable layout built from these primitives to drop to raw `stylex` for layout plumbing, which costs Custom-CSS points on the [template grading rubric](https://github.com/facebookexperimental/xds/wiki/Contributing-Templates#3-custom-css-15-pts) even though there's no idiomatic alternative.

## Concrete case: the `file-explorer` page template

A macOS-Finder-style Miller-column browser (`packages/cli/templates/pages/file-explorer/page.tsx`) is otherwise pure XDS (zero raw HTML, zero raw SVG, complete doc) but is capped at **A (90/100)** purely by Custom CSS, because it needs:

| Custom style | Property | What XDS prop would replace it |
|---|---|---|
| `page` | `height: 100dvh` | A way for `XDSLayout height="fill"` to fill the host when the host `/` aren't `height:100%` (or a documented "fill the viewport" escape) |
| `columnRow` | `overflowX: auto`, `overflowY: hidden` | `overflow` / `scroll` prop on `XDSHStack` (horizontal scroll of the column strip on small viewports) |
| `scrollable` | `overflowY: auto` | `isScrollable` / `overflow` prop on `XDSSection` (per-column vertical scroll) |
| `fixedColumn` | `flexShrink: 0` | `shrink={false}` / flex-item prop on `XDSSection` |
| `detailColumn` | `flexGrow: 1`, `flexShrink: 0`, `flexBasis: 320` | `grow` / `shrink` / `basis` props on `XDSSection` |

`XDSLayoutPanel` already supports `isScrollable` + `width` + `hasDivider` natively, but it only works in `XDSLayout`'s fixed `start`/`content`/`end` slots — it can't host a **dynamic, runtime-variable number** of columns (Finder columns grow/shrink as you navigate), and nested layouts **squeeze** fixed-width panels on narrow viewports instead of scrolling horizontally. So the data-driven `.map()` + `XDSHStack` + `XDSSection` approach is the right structure, and it has no prop-based way to express overflow/flex sizing.

## Proposed

Add to `XDSSection` (and ideally `XDSStack`/`XDSHStack`/`XDSVStack`):

- `isScrollable?: boolean` or `overflow?: 'visible' | 'auto' | 'clip' | 'hidden'` (and/or per-axis)
- flex-item props: `grow?: boolean | number`, `shrink?: boolean | number`, `basis?: SizeValue`

This would let scrollable multi-pane layouts (file browsers, kanban boards, horizontal card strips) be expressed prop-only and score full Custom-CSS marks.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.