diff --git a/content/docs/learn/playground/alternating-colors.mdx b/content/docs/learn/playground/alternating-colors.mdx new file mode 100644 index 0000000..8d0b614 --- /dev/null +++ b/content/docs/learn/playground/alternating-colors.mdx @@ -0,0 +1,85 @@ +--- +title: "Alternating (banded) colors" +description: "A repeating header/odd/even/footer fill pattern, applied over a range from the Format ▸ Alternating colors panel, colors the range immediately and keeps coloring it correctly as rows are inserted or deleted inside it. The panel previews every field edit on the grid immediately, before Done — Done only finalizes it as one undoable command, and Cancel discards the live preview entirely with no trace." +--- + +{/* GENERATED — do not edit by hand */} + +## What it does + +Select a range and open **Format ▸ Alternating colors** to give it a repeating fill pattern, the way Google Sheets does — a distinct **header** color on the range's own first row (on by default), two colors that **alternate** down every row after it, and an optional distinct **footer** color on the range's own last row. Turn Header or Footer off to fold that row back into the ordinary alternation. Every change colors the range on the sheet **immediately**, exactly like real Google Sheets — **Done** doesn't "apply" anything, it just closes the panel; **Cancel** (or Escape, an outside click, or the panel's own close button) discards the live preview entirely, with no trace left behind. + +The banding is **live**: insert or delete rows inside the range and it re-colors correctly from the range's own current top — the header stays pinned to whichever row is now first, and the alternation restarts from there, never from a stale original row position. An explicit cell fill you set yourself (Format ▸ Fill color) always shows through the band rather than being hidden by it, and a conditional-format rule's highlight always wins over both — it exists specifically to call out exceptional cells. + +## Verified behavior + +_Matches Google Sheets:_ Google Sheets' Format ▸ Alternating colors opens a right-docked panel with preset style swatches plus custom color pickers: a Header checkbox + color (defaults on), two required band colors that alternate down the range, and a Footer checkbox + color (defaults off). The header row (the range's own top row) and footer row (its own bottom row), when their checkboxes are on, always render in their own distinct color rather than joining the alternation; every other row alternates the two band colors starting from the first row after the header. Inserting or deleting rows inside the range re-derives the banding from the range's own current top, so the header/footer stay pinned to the range's top/bottom row and the alternation stays correct rather than tracking stale original row positions. The panel previews every field edit live on the grid, the same way every other Sheets format side panel does — Done just closes the panel, it is not an apply gate, and Cancel discards whatever was previewed with no trace left behind. (The live oracle session for this feature could not complete — see the oracle's own "Session method" section — so the panel's exact preset swatches, default hex colors, and precise Format-menu position are Studio's own considered choices, not pixel-matched against a live session.) + +#### Opening Format > Alternating colors shows the panel + +**Given** + +**When** I select **A1:A5**, then click menu item **format.alternatingColors** + +**Then** +- `[data-testid="alternating-colors-dialog"]` is visible +- `[data-testid="alternating-colors-header"]` is visible +- `[data-testid="alternating-colors-footer"]` is visible + +#### Applying the default banding colors the header row and alternates the rest + +**Given** + +**When** I select **A1:A5**, then click menu item **format.alternatingColors**, then click **alternating-colors-done** + +**Then** +- **A1** renders as fill=#d9d9d9 +- **A2** renders as fill=#ffffff +- **A3** renders as fill=#f3f3f3 +- **A4** renders as fill=#ffffff + +#### Turning the header checkbox OFF lets the first row join the ordinary alternation instead + +**Given** + +**When** I select **A1:A5**, then click menu item **format.alternatingColors**, then click **alternating-colors-header**, then click **alternating-colors-done** + +**Then** +- **A1** renders as fill=#ffffff +- **A2** renders as fill=#f3f3f3 + +#### Turning the footer checkbox ON colors the range's own last row distinctly + +**Given** + +**When** I select **A1:A5**, then click menu item **format.alternatingColors**, then click **alternating-colors-footer**, then click **alternating-colors-done** + +**Then** +- **A5** renders as fill=#d9d9d9 + +#### Editing a band color previews it LIVE on the grid, BEFORE Done is clicked + +**Given** + +**When** I select **A1:A3**, then click menu item **format.alternatingColors**, then fill **alternating-colors-first** with `#ff0000` + +**Then** +- **A2** renders as fill=#ff0000 + +#### Cancel discards the live-previewed banding entirely — the grid returns to its pre-panel state + +**Given** + +**When** I select **A1:A3**, then click menu item **format.alternatingColors**, then click **alternating-colors-cancel** + +**Then** +- **A1** renders as fill=false + +#### An explicit cell fill always shows through the band + +**Given** + +**When** I click **A1**, then click menu item **format.fillColor**, then select **A1:A5**, then click menu item **format.alternatingColors**, then click **alternating-colors-done** + +**Then** +- **A1** renders as fill=#fff2cc diff --git a/content/docs/learn/playground/conditional-formatting.mdx b/content/docs/learn/playground/conditional-formatting.mdx index 97a7f2e..c6a8710 100644 --- a/content/docs/learn/playground/conditional-formatting.mdx +++ b/content/docs/learn/playground/conditional-formatting.mdx @@ -1,19 +1,21 @@ --- title: "Conditional formatting (daily-driver slice)" -description: "A single-condition value-comparison rule or a 2-stop color scale, applied over a range from the Format ▸ Conditional formatting dialog, colors matching cells live (tracking edits) without touching their value/formula; a rule undoes/redoes like any edit. The dialog ITSELF previews every field edit on the grid immediately, before Done — Done only finalizes it as one undoable command, and Cancel discards the live preview entirely with no trace." +description: "A single-condition value-comparison rule, a 2-stop color scale, or a custom-formula rule (an arbitrary boolean formula, checked per cell), applied over a range from the Format ▸ Conditional formatting dialog, colors matching cells live (tracking edits) without touching their value/formula; a rule undoes/redoes like any edit. The dialog ITSELF previews every field edit on the grid immediately, before Done — Done only finalizes it as one undoable command, and Cancel discards the live preview entirely with no trace." --- {/* GENERATED — do not edit by hand */} ## What it does -Select a range and open **Format ▸ Conditional formatting** to color-code cells by their own value, the way Google Sheets does — this daily-driver slice covers the two most common shapes: a **single-condition rule** ("format cells if greater than / less than / equal to / between a value, in a chosen fill color") and a **color scale** (a 2-stop gradient from a min color to a max color across the range's own numbers). Pick a condition and a value (and a second value for "Is between"/"Is not between"), or switch to the Color scale tab — **every change colors the range on the sheet immediately**, exactly like real Google Sheets. **Done** doesn't "apply" anything; it just closes the panel, keeping whatever you last saw on the grid. **Cancel** (or Escape, an outside click, or the panel's own close button) discards the live preview entirely — the grid returns to its exact pre-panel state, with no rule left behind. +Select a range and open **Format ▸ Conditional formatting** to color-code cells by their own value, the way Google Sheets does. Three shapes: a **single-condition rule** ("format cells if greater than / less than / equal to / between a value, in a chosen fill color"), a **color scale** (a 2-stop gradient from a min color to a max color across the range's own numbers), and a **custom formula** ("format cells if this formula is TRUE" — any formula you'd type into a cell, checked against each cell in the range). Pick a condition and a value (and a second value for "Is between"/"Is not between"), switch to the Color scale tab, or switch to the Custom formula tab and type a formula — **every change colors the range on the sheet immediately**, exactly like real Google Sheets. **Done** doesn't "apply" anything; it just closes the panel, keeping whatever you last saw on the grid. **Cancel** (or Escape, an outside click, or the panel's own close button) discards the live preview entirely — the grid returns to its exact pre-panel state, with no rule left behind. A rule is **live**: it re-evaluates every time the sheet recalculates, so a cell that crosses the threshold as a dependent formula changes recolors automatically — nothing is baked in at the moment you click Done. It's **presentation only**: coloring `=A1+B1` tints the cell without touching the formula or its computed value. However many fields you tune before clicking Done, the rule still **undoes/redoes as ONE edit** — Ctrl+Z after Done always fully removes it in a single step, never leaving you partway through your own tuning session. +A custom-formula rule is typed once, anchored to the range's own top-left cell, and each cell in the range checks its own version of it shifted the same way a fill handle would shift a formula — a rule over `A1:A10` reading `=B1>10` checks `=B2>10` at `A2`, `=B3>10` at `A3`, and so on. The formula can read any cell — even a cell outside the range, or a cell other than the one it's coloring — so you can highlight column A based on column B, or color a whole row when one of its cells crosses a threshold. + ## Verified behavior -_Matches Google Sheets:_ Google Sheets' Format ▸ Conditional formatting opens a "Conditional format rules" panel with two tabs. The "Single color" tab offers a "Format cells if…" condition dropdown (Is empty/not empty, five text conditions, three date conditions, six numeric-comparison operators — Greater than/Greater than or equal to/Less than/Less than or equal to/Is equal to/Is not equal to, plus Is between/Is not between, and "Custom formula is") and a formatting-style picker (bold/italic/underline/strikethrough/text color/ fill color; default a light green ~#b7e1cd). The "Color scale" tab offers a min/mid/maxpoint picker (default a 2-stop White→Green preset, midpoint "None") with a live gradient preview. Multiple rules can stack over the same or overlapping ranges via "+Add another rule". A rule is grid-owned presentation, re-evaluated against each cell's live value on every recalc (never baked into a static per-cell format), and undoes/redoes like any other edit. This daily-driver slice ships all eight numeric operators (Greater than/Greater than or equal to/Less than/Less than or equal to/Is equal to/Is not equal to/Is between/Is not between), restricts their values to numbers (no text/date/formula conditions), narrows the color scale to 2-stop (matching Sheets' own default, no midpoint), and presents it in a right-docked, non-modal panel matching Sheets' own docked side panel (a fixed, non-resizable width is the one residual chrome gap) — see the oracle's "Accepted divergences" for the full list. Full parity (text/date conditions, custom formula, 3-stop scale, alternating colors, themes) is tracked separately. The panel's OWN fields preview live on the grid before Done — real Google Sheets applies conditional- format highlighting live as the panel's own condition/style/color-scale fields are adjusted; Done just closes the panel, it is not an apply gate, and Cancel discards whatever was previewed with no trace left behind. +_Matches Google Sheets:_ Google Sheets' Format ▸ Conditional formatting opens a "Conditional format rules" panel with two tabs. The "Single color" tab offers a "Format cells if…" condition dropdown (Is empty/not empty, five text conditions, three date conditions, six numeric-comparison operators — Greater than/Greater than or equal to/Less than/Less than or equal to/Is equal to/Is not equal to, plus Is between/Is not between, and "Custom formula is") and a formatting-style picker (bold/italic/underline/strikethrough/text color/ fill color; default a light green ~#b7e1cd). The "Color scale" tab offers a min/mid/maxpoint picker (default a 2-stop White→Green preset, midpoint "None") with a live gradient preview. Multiple rules can stack over the same or overlapping ranges via "+Add another rule". A rule is grid-owned presentation, re-evaluated against each cell's live value on every recalc (never baked into a static per-cell format), and undoes/redoes like any other edit. This daily-driver slice ships all eight numeric operators (Greater than/Greater than or equal to/Less than/Less than or equal to/Is equal to/Is not equal to/Is between/Is not between), restricts their values to numbers (no text/date/formula conditions), narrows the color scale to 2-stop (matching Sheets' own default, no midpoint), and presents it in a right-docked, non-modal panel matching Sheets' own docked side panel (a fixed, non-resizable width is the one residual chrome gap) — see the oracle's "Accepted divergences" for the full list. A later slice adds the "Custom formula is" tab: one arbitrary boolean formula, anchored to the range's own top-left cell exactly like a fill (each covered cell evaluates its own relative-shifted copy), matching a fill color when the formula's live result is TRUE. Remaining full parity (text/date conditions, 3-stop scale) is tracked separately (alternating colors and themes are their own, distinct Format-menu features, not conditional-format rule kinds). The panel's OWN fields preview live on the grid before Done — real Google Sheets applies conditional-format highlighting live as the panel's own condition/style/color-scale/formula fields are adjusted; Done just closes the panel, it is not an apply gate, and Cancel discards whatever was previewed with no trace left behind. #### Opening Format > Conditional formatting shows the Single color tab by default @@ -146,3 +148,36 @@ _Matches Google Sheets:_ Google Sheets' Format ▸ Conditional formatting opens **Then** - **A1** renders as fill=#b7e1cd - **A2** renders as fill=false + +#### A custom-formula rule colors a cell whose formula resolves to TRUE + +**Given** +- **A1** = `15` +- **B1** = `10` + +**When** I click **A1**, then click menu item **format.conditionalFormatting**, then click **conditional-format-tab-custom-formula**, then fill **conditional-format-formula** with `=A1>B1`, then click **conditional-format-done** + +**Then** +- **A1** renders as fill=#b7e1cd + +#### A custom-formula rule leaves a cell uncolored when its formula resolves to FALSE + +**Given** +- **A1** = `5` +- **B1** = `10` + +**When** I click **A1**, then click menu item **format.conditionalFormatting**, then click **conditional-format-tab-custom-formula**, then fill **conditional-format-formula** with `=A1>B1`, then click **conditional-format-done** + +**Then** +- **A1** renders as fill=false + +#### A custom-formula rule can color a TEXT cell based on a formula that never reads its own value + +**Given** +- **A1** = `hello` +- **B1** = `15` + +**When** I click **A1**, then click menu item **format.conditionalFormatting**, then click **conditional-format-tab-custom-formula**, then fill **conditional-format-formula** with `=B1>10`, then click **conditional-format-done** + +**Then** +- **A1** renders as fill=#b7e1cd diff --git a/content/docs/learn/playground/filter-by-value.mdx b/content/docs/learn/playground/filter-by-value.mdx new file mode 100644 index 0000000..291e664 --- /dev/null +++ b/content/docs/learn/playground/filter-by-value.mdx @@ -0,0 +1,142 @@ +--- +title: "Filter a range by value (daily-driver slice)" +description: "Data ▸ Create a filter (or a header's funnel button) opens a panel listing the selected range's columns; unchecking a value for a column hides every row whose raw value in that column is unchecked, and re-checking it (or removing the filter) restores those rows. The header row is never hidden. Two columns' criteria on the SAME filter combine as AND. Creating a filter, changing its criteria, and removing it are each one undoable command." +--- + +{/* GENERATED — do not edit by hand */} + +## What it does + +**Data ▸ Create a filter** opens a panel over the currently-selected range: one tab per column, and — for whichever column is selected — a checkbox list of every distinct value in it. Unchecking a value hides every row whose value in that column matches; checking it back (or clicking **Remove filter**) restores those rows. The range's own first row is the filter's header and is never hidden. + +Two things worth knowing: + +1. **A filtered-out row takes up no space at all** — it isn't dimmed or struck through, it collapses to zero height, exactly like the rows above and below it closed the gap. Row numbers keep their ORIGINAL value (so hiding row 3 shows `1, 2, 4, 5`, not a renumbered `1, 2, 3, 4`) — the header is a reference/formula anchor, and renumbering would misrepresent which sheet row it addresses. +2. **Two columns on the same filter combine as AND.** Narrowing column A and column B both apply — a row has to pass both to stay visible. + +Creating a filter, narrowing a column's criteria, and removing the filter are each **one undoable command**, so a single Ctrl+Z reverses whichever of those you just did. + +A cell counted as **blank** (nothing typed into it) is its own distinct entry in the checklist, labeled `(Blanks)`, separate from any typed value. + +## Try it + + + +## What this slice deliberately does not do + +The live oracle session that would have verified this feature's actual hide/show mechanics against Google Sheets failed on browser tooling before it could drive anything past the filter's creation chrome (see the oracle brief's "Session method (transparency)" section for the full account) — so everything below the creation chrome is a **Studio decision**, built to be the least-invented reading of a checkbox-value filter, not a claim of Sheets parity: + +- **The panel's exact contents and layout were never seen.** Sheets' own dropdown, its "Select all"/search box, and its exact hide-affordance were never driven live. Studio's docked, tabbed panel is its own design, not a reproduction. +- **No click-to-unhide affordance on the row-header gutter.** Sheets is believed to show a small expand control between two header numbers that straddle a hidden run; this was never observed, so it isn't built. Re-opening the panel and re-checking a value is the only way to unhide here. +- **No filter-by-condition, no filter views, no slicers.** Full parity stays out of scope; this slice is value-only, one filter per sheet. +- **Multi-column AND-stacking is inferred, not observed.** Oracle observation 13 shows one filter puts a dropdown in every covered column's header (one filter, several columns) — that several-column shape is real; that unrelated columns' criteria combine as AND is the standard reading of that shape, not something the live session actually exercised. + +Every one of these is called out, with the reasoning, in the oracle brief's "Studio decisions (not Sheets-observed)" section — a future session with working browser tooling should revisit each. + +## Verified behavior + +_Matches Google Sheets:_ Google Sheets' Data ▸ Create a filter is a single menu item (no submenu) that, over a selected range, changes the sheet's chrome without touching any data: a funnel-glyph dropdown button appears in each cell of the range's first row, that row renders bold, the column headers it covers are tinted green, a green outline is drawn around the range, and the toolbar's filter icon becomes active — live-verified, with nothing hidden yet (all rows stay visible). That is the full extent of what this session could verify live: a fresh attempt to drive the filter's actual value-hiding behaviour (what the dropdown lists, what unchecking a value does, how hidden rows affect row-header numbering, whether it survives reload, whether undo is one step, whether two columns' criteria stack) failed on browser tooling six separate times over roughly 45 minutes, not on Sheets itself — see the oracle brief's "Session method (transparency)" section for the full account. Everything this slice ships beyond the verified creation chrome is therefore a documented STUDIO DECISION (the oracle's "Studio decisions (not Sheets-observed)" section), not a fresh Sheets citation: the mechanically obvious, lowest-invention reading of a checkbox-list value filter (hide a row iff its checked-value set excludes that row's value in the column), built to be corrected by a future session with working tooling rather than left unshipped a second time. + +#### Data ▸ Create a filter opens the panel with nothing hidden yet + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A3** = `alpha` +- **A4** = `delta` + +**When** I select **A1:A4**, then click menu item **data.createFilter** + +**Then** +- `[data-testid="filter-panel"]` is visible + +#### Unchecking a value hides every row holding it; the header row never hides + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A3** = `alpha` +- **A4** = `delta` + +**When** I select **A1:A4**, then click menu item **data.createFilter**, then click **filter-panel-value-delta**, then click **filter-panel-done** + +**Then** +- row **2** is exactly 0px tall +- row **4** is exactly 0px tall + +#### Re-checking a value before Done leaves it visible + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A3** = `alpha` + +**When** I select **A1:A3**, then click menu item **data.createFilter**, then click **filter-panel-value-delta**, then click **filter-panel-value-delta**, then click **filter-panel-done** + +**Then** + +#### A blank cell can be filtered out via the (Blanks) entry + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A4** = `alpha` + +**When** I select **A1:A4**, then click menu item **data.createFilter**, then click **filter-panel-value-blank**, then click **filter-panel-done** + +**Then** +- row **3** is exactly 0px tall + +#### Two columns' criteria on the same filter stack as AND + +**Given** +- **A1** = `Name` +- **B1** = `Dept` +- **A2** = `delta` +- **B2** = `eng` +- **A3** = `alpha` +- **B3** = `sales` +- **A4** = `delta` +- **B4** = `sales` + +**When** I select **A1:B4**, then click menu item **data.createFilter**, then click **filter-panel-column-1**, then click **filter-panel-value-sales**, then click **filter-panel-done** + +**Then** +- row **3** is exactly 0px tall +- row **4** is exactly 0px tall + +#### The panel's own Remove filter button removes it and restores every row + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A3** = `alpha` + +**When** I select **A1:A3**, then click menu item **data.createFilter**, then click **filter-panel-remove** + +**Then** +- `[data-testid="filter-panel"]` is hidden + +#### ONE undo after narrowing a filter restores every row + +**Given** +- **A1** = `Name` +- **A2** = `delta` +- **A3** = `alpha` + +**When** I select **A1:A3**, then click menu item **data.createFilter**, then click **filter-panel-value-delta**, then click **filter-panel-done**, then click **A1**, then undo + +**Then** + +#### Creating a filter refuses a single-row selection — nothing to filter + +**Given** +- **A1** = `Name` +- **B1** = `Dept` + +**When** I select **A1:B1**, then click menu item **data.createFilter** + +**Then** +- **A1** shows `Name` +- **B1** shows `Dept` +- `[data-testid="filter-panel"]` is hidden diff --git a/content/docs/learn/playground/meta.json b/content/docs/learn/playground/meta.json index 0eaf70c..7eb98d2 100644 --- a/content/docs/learn/playground/meta.json +++ b/content/docs/learn/playground/meta.json @@ -55,6 +55,8 @@ "sort-range", "structure-insert-delete", "views", - "chart-axis-labels" + "chart-axis-labels", + "alternating-colors", + "filter-by-value" ] } diff --git a/content/docs/learn/playground/navigate-range-select.mdx b/content/docs/learn/playground/navigate-range-select.mdx index 1607861..28aebf2 100644 --- a/content/docs/learn/playground/navigate-range-select.mdx +++ b/content/docs/learn/playground/navigate-range-select.mdx @@ -52,7 +52,7 @@ _Matches Google Sheets:_ In Google Sheets, clicking a cell selects it alone; shi **Then** - the active cell is **B2** -#### Tab moves the active cell one column right +#### Tab moves the active cell one column right without extending the selection **Given** @@ -60,8 +60,10 @@ _Matches Google Sheets:_ In Google Sheets, clicking a cell selects it alone; shi **Then** - the active cell is **B1** +- the selection is just **B1** — it did not extend +- keyboard focus is on the **grid** -#### Shift+Tab moves the active cell one column left +#### Shift+Tab moves the active cell one column left without extending the selection **Given** @@ -69,8 +71,10 @@ _Matches Google Sheets:_ In Google Sheets, clicking a cell selects it alone; shi **Then** - the active cell is **B1** +- the selection is just **B1** — it did not extend +- keyboard focus is on the **grid** -#### Tab from an open editor commits the edit and moves one column right +#### Tab from an open editor commits the edit, moves one column right, and keeps focus on the grid **Given** @@ -79,8 +83,10 @@ _Matches Google Sheets:_ In Google Sheets, clicking a cell selects it alone; shi **Then** - **B2** shows `9` - the active cell is **C2** +- the selection is just **C2** — it did not extend +- keyboard focus is on the **grid** -#### Shift+Tab from an open editor commits the edit and moves one column left +#### Shift+Tab from an open editor commits the edit, moves one column left, and keeps focus on the grid **Given** @@ -89,6 +95,8 @@ _Matches Google Sheets:_ In Google Sheets, clicking a cell selects it alone; shi **Then** - **C2** shows `9` - the active cell is **B2** +- the selection is just **B2** — it did not extend +- keyboard focus is on the **grid** #### Committing an edit with Enter moves the active cell down diff --git a/content/docs/learn/playground/sort-range.mdx b/content/docs/learn/playground/sort-range.mdx index 4bfcb2c..f6f7840 100644 --- a/content/docs/learn/playground/sort-range.mdx +++ b/content/docs/learn/playground/sort-range.mdx @@ -33,7 +33,7 @@ Sorting is destructive, so anything the live oracle session did not actually dem - **No ordering is claimed within the boolean group or within the error group**, and no tie-break between two equal keys: the sort is _stable_, so equal keys keep their original relative order. - **A range overlapping a merged cell, or a spilled dynamic array, is refused** rather than sorted. Neither was ever put inside a sorted range in the oracle session, and both have a concrete way to lose data if guessed at: permuting content under a merge hides it (the merge stays put, so whatever lands in a covered cell vanishes from the grid while still sitting in the model), and moving a spill anchor re-spills from a new origin, hard-materialises the echoes it left behind, and cannot be undone in one step. The menu row is a no-op on such a selection; the API command throws with the reason. - **A relative reference with nowhere to go becomes `#REF!`.** `=A1` moving up out of row 1 has no cell to point at. Sort hands the text to the same `adjustFormula` translate that fill and copy/paste already use, so it behaves identically to them — but Sheets was never asked what _it_ does, so this is recorded as unobserved rather than claimed as parity. -- **No filter.** `Data ▸ Create a filter` stays "coming soon". The oracle captured a filter's creation chrome (green column headers, per-header dropdown buttons, a bold header row) but none of the behaviour that matters — what the dropdown contains, how hidden rows renumber, whether it survives reload, whether undo removes it in one step — and Studio has no row-hiding mechanism at all today. It is filed separately; the wider parity scope stays open. +- **Filter by value is a separate manifest.** `Data ▸ Create a filter` now ships alongside sort in this same daily-driver slice — see the `filter-by-value` manifest for its own scope and ground truth. Every one of these is recorded, with the reason, in the oracle brief's **"NOT OBSERVED — do not guess these"** section. @@ -280,12 +280,3 @@ _Matches Google Sheets:_ Google Sheets' Data ▸ Sort range is a submenu offerin - **A1** shows `delta` - **A2** shows `alpha` - **B2** shows `keep-me` - -#### Data ▸ Create a filter is still disabled — this slice ships sort only - -**Given** - -**When** I click menu item **data.createFilter** - -**Then** -- `[data-menu-item="data.createFilter"]` is visible