Repository navigation
feat(execution-history): content-fit runs table columns + centered text - #25
Conversation
Greptile SummaryThis PR replaces the bespoke flexbox runs list with a real semantic
Confidence Score: 5/5Safe to merge — the change is a self-contained UI refactor with no data-layer or auth changes, all states are correctly accounted for, and the previous hover-reveal gap is addressed. The conversion from flexbox to semantic table is mechanically correct: isEmpty is properly gated, all utility rows use valid colSpan rows, column order in header and rows is consistent, sticky-header border rendering uses the established workaround, and the two long-text columns are capped with truncation. No data flow, auth, or store logic was touched. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
RunsPage --> |isEmpty = !loading AND !error AND rows=0| RunsShell
RunsShell --> thead["thead sticky - RunsColumnHeader"]
RunsShell --> tbody["tbody"]
tbody --> emptyBranch{isEmpty?}
emptyBranch -->|yes| EmptyRow["tr - td colSpan=12 - empty state"]
emptyBranch -->|no| children["children body"]
children --> loadingBranch{view.isLoading?}
loadingBranch -->|yes| LoadingRow["tr - td colSpan=12 - Loading runs"]
loadingBranch -->|no| errorBranch{view.isError?}
errorBranch -->|yes| ErrorRow["tr - td colSpan=12 - Unable to load"]
errorBranch -->|no| rowItems["rowItems array"]
rowItems --> RunListRow["tr role=button - RunListRow per run"]
rowItems --> LiveDivider["tr - td colSpan=12 - LiveDivider"]
rowItems --> LoadMoreError["tr - td colSpan=12 - Load more error"]
children --> loadingMore{isLoadingMore?}
loadingMore -->|yes| LoadingMoreRow["tr - td colSpan=12 - Loading more"]
children --> endOfHistory{not hasMore AND not isLoadingMore?}
endOfHistory -->|yes| EndRow["tr - td colSpan=12 - End of history"]
Reviews (3): Last reviewed commit: "fix(execution-history): add a title to t..." | Re-trigger Greptile |
Rebuild the runs list as a real semantic <table> with content-fit columns (table-layout: auto) instead of the fixed-width COL_* flex slots: each column sizes to its widest cell across the header + rows, and the sticky <thead> shares one column model with the rows so they align for free. Short/numeric/badge columns center; text columns left-align. actor + code are width-capped and truncated so content-fit can't blow the table out. The row <Button> becomes a <tr role=button> (click + keyboard); the divider / loading / empty / end-of- history states become colSpan rows.
Greptile P1: the content-fit code cell truncates with no title, so the clipped
preview wasn't reachable on hover (only the actor cell had one). Add
title={run.codePreview} so hovering reveals the full write-bounded preview.
897e665 to
8128880
Compare
|
@greptile the branch was rebased to drop an unrelated commit and the P1 |
…xt (#25) ## What Rebuilds the runs list as a **real semantic `<table>` with content-fit columns** (`table-layout: auto`), replacing the bespoke fixed-width flexbox layout. - **Content-fit**: each column sizes to the maximum width its rows need — the sticky `<thead>` and `<tbody>` rows share one column model, so columns size *and* stay aligned automatically (no more shared `COL_*` fixed-width constants, no `min-w` scroll floor). - **Alignment**: short / numeric / badge columns (status, duration, tools, interaction, log) are **centered**; text columns (started, trigger, actor, code) are left-aligned. - **No blowout**: the two columns that can run long — `actor` (token id / email) and `code` — are width-capped + truncated (hover shows the full value). - The row `<Button>` becomes a `<tr role="button" tabIndex onClick onKeyDown>` (click + keyboard, accessible). The live divider / loading / empty / end-of-history states become `colSpan` rows. ## Why this shape (vs openstatus) Studied `openstatus-data-table`: it renders a real shadcn `<table>` but sets **fixed per-column `size`** values (CSS vars → inline widths) — *not* content-fit. True "snap each column to its content" comes from a real table's default `table-layout: auto`, which is what this uses. Sticky-header border rendering uses `border-separate border-spacing-0` (the same browser-bug workaround openstatus uses). ## Notes - `<table>` carries a narrow `oxlint-disable react/forbid-elements` (with a boundary reason) — the runs table needs its own infinite-scroll container + sticky thead, which the shared `<Table>`'s built-in overflow wrapper would conflict with. Same suppression the shared `Table` component itself uses. - Trade-off: content-fit means the table is its natural content width — narrower than the pane → left-aligned with slack on the right; wider → horizontal scroll. ## Verification typecheck 0 · lint 0/0 · format clean · tests 19/19.
…xt (#25) ## What Rebuilds the runs list as a **real semantic `<table>` with content-fit columns** (`table-layout: auto`), replacing the bespoke fixed-width flexbox layout. - **Content-fit**: each column sizes to the maximum width its rows need — the sticky `<thead>` and `<tbody>` rows share one column model, so columns size *and* stay aligned automatically (no more shared `COL_*` fixed-width constants, no `min-w` scroll floor). - **Alignment**: short / numeric / badge columns (status, duration, tools, interaction, log) are **centered**; text columns (started, trigger, actor, code) are left-aligned. - **No blowout**: the two columns that can run long — `actor` (token id / email) and `code` — are width-capped + truncated (hover shows the full value). - The row `<Button>` becomes a `<tr role="button" tabIndex onClick onKeyDown>` (click + keyboard, accessible). The live divider / loading / empty / end-of-history states become `colSpan` rows. ## Why this shape (vs openstatus) Studied `openstatus-data-table`: it renders a real shadcn `<table>` but sets **fixed per-column `size`** values (CSS vars → inline widths) — *not* content-fit. True "snap each column to its content" comes from a real table's default `table-layout: auto`, which is what this uses. Sticky-header border rendering uses `border-separate border-spacing-0` (the same browser-bug workaround openstatus uses). ## Notes - `<table>` carries a narrow `oxlint-disable react/forbid-elements` (with a boundary reason) — the runs table needs its own infinite-scroll container + sticky thead, which the shared `<Table>`'s built-in overflow wrapper would conflict with. Same suppression the shared `Table` component itself uses. - Trade-off: content-fit means the table is its natural content width — narrower than the pane → left-aligned with slack on the right; wider → horizontal scroll. ## Verification typecheck 0 · lint 0/0 · format clean · tests 19/19.
…xt (#25) ## What Rebuilds the runs list as a **real semantic `<table>` with content-fit columns** (`table-layout: auto`), replacing the bespoke fixed-width flexbox layout. - **Content-fit**: each column sizes to the maximum width its rows need — the sticky `<thead>` and `<tbody>` rows share one column model, so columns size *and* stay aligned automatically (no more shared `COL_*` fixed-width constants, no `min-w` scroll floor). - **Alignment**: short / numeric / badge columns (status, duration, tools, interaction, log) are **centered**; text columns (started, trigger, actor, code) are left-aligned. - **No blowout**: the two columns that can run long — `actor` (token id / email) and `code` — are width-capped + truncated (hover shows the full value). - The row `<Button>` becomes a `<tr role="button" tabIndex onClick onKeyDown>` (click + keyboard, accessible). The live divider / loading / empty / end-of-history states become `colSpan` rows. ## Why this shape (vs openstatus) Studied `openstatus-data-table`: it renders a real shadcn `<table>` but sets **fixed per-column `size`** values (CSS vars → inline widths) — *not* content-fit. True "snap each column to its content" comes from a real table's default `table-layout: auto`, which is what this uses. Sticky-header border rendering uses `border-separate border-spacing-0` (the same browser-bug workaround openstatus uses). ## Notes - `<table>` carries a narrow `oxlint-disable react/forbid-elements` (with a boundary reason) — the runs table needs its own infinite-scroll container + sticky thead, which the shared `<Table>`'s built-in overflow wrapper would conflict with. Same suppression the shared `Table` component itself uses. - Trade-off: content-fit means the table is its natural content width — narrower than the pane → left-aligned with slack on the right; wider → horizontal scroll. ## Verification typecheck 0 · lint 0/0 · format clean · tests 19/19.
What
Rebuilds the runs list as a real semantic
<table>with content-fit columns (table-layout: auto), replacing the bespoke fixed-width flexbox layout.<thead>and<tbody>rows share one column model, so columns size and stay aligned automatically (no more sharedCOL_*fixed-width constants, nomin-wscroll floor).actor(token id / email) andcode— are width-capped + truncated (hover shows the full value).<Button>becomes a<tr role="button" tabIndex onClick onKeyDown>(click + keyboard, accessible). The live divider / loading / empty / end-of-history states becomecolSpanrows.Why this shape (vs openstatus)
Studied
openstatus-data-table: it renders a real shadcn<table>but sets fixed per-columnsizevalues (CSS vars → inline widths) — not content-fit. True "snap each column to its content" comes from a real table's defaulttable-layout: auto, which is what this uses. Sticky-header border rendering usesborder-separate border-spacing-0(the same browser-bug workaround openstatus uses).Notes
<table>carries a narrowoxlint-disable react/forbid-elements(with a boundary reason) — the runs table needs its own infinite-scroll container + sticky thead, which the shared<Table>'s built-in overflow wrapper would conflict with. Same suppression the sharedTablecomponent itself uses.Verification
typecheck 0 · lint 0/0 · format clean · tests 19/19.