Skip to content

fix(input_number): give the tall tier's stepper way to the vertical slider - #313

Merged
fx merged 8 commits into
mainfrom
fix/0042-stepper-clipping
Jul 30, 2026
Merged

fix(input_number): give the tall tier's stepper way to the vertical slider#313
fx merged 8 commits into
mainfrom
fix/0042-stepper-clipping

Conversation

@fx

@fx fx commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

An input_number card set to controlStyle: 'stepper' now renders the tier's vertical slider at tall instead of a stepper the tile clips. row and full are untouched, and the stored option is never rewritten — the card returns to the stepper the moment it is two columns wide again.

Implements PR 2 only of docs/changes/0042-tall-tile-control-geometry.md. PRs 3 and 4 remain open, so the change document stays draft and docs/index.yml / docs/index.md are untouched (status: complete still counts 34).

Why the stepper cannot stay

A tall tile is one column wide by definition — 63px on a 12-column desktop grid, leaving a 35px content region. The stepper is content-sized: two 40px size="3" icon buttons, the value button's 60px minimum and the control row's two 8px gaps, 156px in all. Radix's .rt-BaseButton sets flex-shrink: 0, so it could not compress into that region: it overhung 46.5px past each of the tile's own edges and .liebe-card's overflow: hidden cut the buttons off. Editing the value made it worse — the readout becomes a TextField with an inline width: 80px, growing the row to 176px.

This PR applies what PR 1 settled rather than deciding it: a control bounded by its contents on every axis has no floor to size down to, so it is omitted at that tier in favour of one that can — here the vertical slider the tier's layout already asks for, which keeps the entity operable. The mechanism is the shape resolveSelectPresentation already had for input_select's pills.

The content region has no lower bound, and the fix survives that. A screen stored at 16 columns is honoured at both desktop breakpoints, so a 960px container lays out a 43px tile and LCARS's 44px inline inset leaves no content region at all. Nothing here is expressed as "there is enough room" — the substitution is keyed on the tier, which is exactly the condition (one column wide), so it holds at every width including zero. Making the slider that replaces it flexible down to the 24px floor, and omitted below it, is PR 3's.

--liebe-card-padding is not touched. The inset is shared, so buying room here would move the vertical slider too, and under LCARS it would move the wrong way. PR 1's decision removes the temptation rather than relying on the warning.

Changes

  • resolveNumberPresentation(style, tier) in src/store/inputHelperOptions.ts — presentation resolved at render, config never rewritten, sitting beside its input_select sibling.
  • src/components/InputNumberCard.tsx consumes it for the embedded control; the detail dialog's control is unaffected (it resolves from the helper's mode and is never at this tier).
  • Spec status prose in options/input-helpers and design-system, which both named this PR as what would flip them.
  • The stale tier-table quote in controlCardTierLayouts.test.tsx — it still quoted "(or compact stepper)", the phrase PR 1 dropped rather than defined.
  • A workshop story for the fallback, and the TierTall story's comment, which said "stepper between" for a fixture that has rendered a slider since 0022.

Two documentation defects found on the way

Both were the change document contradicting itself about which box PR 2 measures against, and both are fixed here rather than worked around:

  • The testing requirement asked for the control measured against the tile's content box "whatever the fix", which collides with the bullet two below it splitting the two consequences — the stepper's is a clip past the tile's edge, the slider's is an overhang inside the padding. Taken as written it gated this PR on PR 3's work, since a 42px track in a 35px region is the state this PR is correct in. Now split by PR.
  • The PR 2 task line repeated the same "content box" wording and is now a reference to that requirement.

Caught by Codex and CodeRabbit independently.

Testing

  • UnitresolveNumberPresentation across all four tiers and both stored styles; card-level coverage that tall renders the vertical slider with none of the stepper's three surfaces present, that row and full still render the stepper from the same stored config, and that the config object is unchanged after a tier that could not render one.
  • Browsertests/e2e/tall-stepper-fit.spec.ts seeds a 1×3 input_number with controlStyle: 'stepper' set explicitly and measures every rendered control against the tile's border box, which is what overflow: hidden crops. The assumed grid-container width is recorded, and the spec asserts the tile is narrower than the stepper's 156px so a later viewport change cannot quietly turn it into a no-op. Controls are measured individually rather than through their slot — the slot is constrained to the tile and would have reported a perfect fit for exactly this defect. Not run locally; CI's Home Assistant E2E job is the gate.
  • Mutation probes, three, each verified to have applied and to have run tests (122 each): resolver reduced to the identity → 4 failed; the card passing the stored style instead of the resolved one → 3 failed, and only the card-level cases; the tier check inverted to row → 8 failed.

Gates

Gate Result
npm test exit 0 — 244 files, 5563 tests, no unhandled rejections
npm run lint exit 0 — 0 errors, 1 pre-existing MigrationCutoffs warning
npm run typecheck exit 0
npm run test:coverage exit 0 — 0 uncovered lines among this PR's changed lines
npm run build-storybook exit 0
codex review --base main clean
CodeRabbit (cr) 3 findings resolved, then skipped (rate-limited)

All run unpiped with their real exit status read, after merging origin/main (which brought in the iconOnly option — no interaction).

Summary by CodeRabbit

  • New Features

    • Tall input_number cards now display a vertical slider instead of stepper controls, even when a stepper is configured.
    • Wider card layouts continue to display configured stepper controls.
    • Added coverage for tall-card control layout and fit behavior.
  • Bug Fixes

    • Prevented number controls from extending beyond or being clipped by tall card tiles.
  • Documentation

    • Updated design-system and layout guidance to reflect the tall-card slider behavior and measurement requirements.

fx added 7 commits July 30, 2026 14:38
…lider

A `tall` tile is one column wide by definition, which on a 12-column desktop
grid is 63px with a 35px content region. The stepper is a content-sized row —
two 40px icon buttons, a 60px value button and two 8px gaps, 156px in all —
and Radix's `.rt-BaseButton` sets `flex-shrink: 0`, so it could not compress
into that region: it overhung 46.5px past each of the tile's own edges and
`.liebe-card`'s `overflow: hidden` cut the buttons off.

Change 0042 PR 1 settled the contract this applies: a control bounded by its
contents on every axis cannot be made cross-axis flexible, so it is omitted at
that tier in favour of one that can — here the vertical slider the tier's
layout already asks for. The resolution is presentation only, the shape
`resolveSelectPresentation` already had: the stored `controlStyle` is never
rewritten, `row` and `full` resolve exactly as before, and the card returns to
the stepper as soon as it is two columns wide again.

`--liebe-card-padding` is untouched. The inset is shared, so buying room here
would move the vertical slider too — that is PR 3's, and under LCARS it would
move the wrong way.

The e2e assertion measures every rendered control against the tile's border
box, which is what `overflow: hidden` crops against. The slider's own overhang
inside the padding is a separate claim at a separate tolerance and belongs to
PR 3; asserting it here would fail on code that is correct for this task.

Refs: docs/changes/0042-tall-tile-control-geometry.md (PR 2)
The line asked for the control measured against the tile's CONTENT box while
the same document's testing requirements split the two consequences on exactly
that distinction — the stepper's is a clip past the tile's edge, the vertical
slider's is an overhang inside the padding — and options/input-helpers' own
scenario for this fallback asks for the edge. Taken literally the line would
have gated this task on PR 3's work, since a 42px slider in a 35px content
region is correct until PR 3 makes the track flexible.
…ldren

The slider is a direct child of `.liebe-card-controls` today, so the union is
the same set — but a wrapper introduced later would be constrained to the slot
and would measure as a perfect fit around a track that escaped, which is the
one failure this spec exists to catch.
The tier is stamped as soon as the card renders, which is before the helper's
state has arrived over the websocket — a snapshot taken between the two would
find an empty control slot and pass every fit comparison vacuously. The
predicate is "any control" rather than "the vertical slider" on purpose: a
poll for the slider would turn a stepper rendering here, the exact defect, into
a timeout with no measurement in the failure.
"Held" reads as the whole tier being met, which the next sentence then takes
back — the slider's own cross-axis fit is 0042 PR 3's.
The requirement asked for the control measured against the tile's CONTENT box
whatever the fix, which contradicts the bullet two below it: the stepper's
consequence is a clip past the tile's edge and the slider's is an overhang
inside the padding, and only the second is a content-region claim. Taken as
written it gated PR 2 on PR 3's work, since a 42px track in a 35px region is
the state PR 2 is correct in.

Also folds PR 2's task line back to a reference rather than a second copy of
the reasoning.
Copilot AI review requested due to automatic review settings July 30, 2026 15:13
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 46 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2d92307a-a907-4fbe-92fb-27455f61b4d0

📥 Commits

Reviewing files that changed from the base of the PR and between 4209cbb and 6115db2.

📒 Files selected for processing (1)
  • src/store/inputHelperOptions.ts
📝 Walkthrough

Walkthrough

Changes

Tall input control behavior

Layer / File(s) Summary
Tier-aware presentation resolution
src/store/inputHelperOptions.ts, src/components/InputNumberCard.tsx, src/store/__tests__/*
Stored stepper presentation resolves to slider only at the tall tier; wider tiers preserve the stepper and stored configuration.
Tier-specific rendering coverage
src/components/__tests__/*, src/components/InputNumberCard.stories.tsx
Tests and a Storybook story verify vertical slider rendering for tall tiles and stepper rendering for wider tiers.
Browser geometry acceptance
tests/e2e/tall-stepper-fit.spec.ts, docs/changes/*, docs/specs/*
Playwright measures control bounds against the tile edge, while documentation records the updated geometry criteria and status.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • fx/liebe#233: Introduced related input_number control-style and tier presentation logic.

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is specific and accurately summarizes the main behavior change for input_number in the tall tier.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/0042-stepper-clipping

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes input_number tiles configured with controlStyle: 'stepper' clipping their embedded stepper at the tall tier by resolving the rendered presentation to the tier’s vertical slider (without rewriting stored config). It implements PR 2 of docs/changes/0042-tall-tile-control-geometry.md.

Changes:

  • Add a render-time resolver (resolveNumberPresentation) so tall substitutes the vertical slider when stepper is stored.
  • Update InputNumberCard to use the resolved presentation and add unit + e2e coverage for the “no clipping past tile edge at tall” requirement.
  • Update related specs, change doc tasks, and Storybook to reflect the new tall behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/e2e/tall-stepper-fit.spec.ts New Playwright spec measuring control bounding boxes vs the tile border box at tall.
src/store/inputHelperOptions.ts Adds resolveNumberPresentation to substitute slider at tall when stepper is stored.
src/store/tests/inputHelperOptions.test.ts Unit tests for resolveNumberPresentation.
src/components/InputNumberCard.tsx Uses resolveNumberPresentation for the embedded control rendering.
src/components/InputNumberCard.stories.tsx Updates TierTall description and adds a story covering stored-stepper/rendered-slider at tall.
src/components/tests/inputHelperControlStyle.test.tsx Card-level tests asserting tall renders vertical slider even when stepper is stored, and config is not rewritten.
src/components/tests/controlCardTierLayouts.test.tsx Updates stale tier-table quote and aligns test commentary with the new rule.
src/components/tests/cardTierLayouts.test.tsx Adds/adjusts tier layout assertions for the tall substitution behavior.
docs/specs/entity-cards/options/input-helpers.md Updates status prose and documents the tall stepper→slider rule as landed by 0042 PR 2.
docs/specs/design-system/index.md Updates cross-axis-fit section status to reflect PR 2 closure (while leaving PR 3/4 work open).
docs/changes/0042-tall-tile-control-geometry.md Updates testing requirement wording and checks off PR 2 task with clarified measurement target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/store/inputHelperOptions.ts Outdated
@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.65%. Comparing base (904190f) to head (6115db2).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #313      +/-   ##
==========================================
+ Coverage   87.60%   87.65%   +0.04%     
==========================================
  Files         230      231       +1     
  Lines        8440     8472      +32     
  Branches     2848     2847       -1     
==========================================
+ Hits         7394     7426      +32     
  Misses        823      823              
  Partials      223      223              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…at it is

The doc block called the slider "cross-axis flexible", which the code does not
have: its vertical orientation is still a fixed inline-size of
--liebe-control-height in anatomy.css, and making it take the content region
is 0042 PR 3's. Worse than an ordinary stale comment here, because a reader
who believed the slider was already flexible would read the tier check as a
redundant optimisation and delete it — when keying on the tier rather than on
a measured width is the whole reason this survives a content region of zero.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@fx
fx merged commit 23c9c32 into main Jul 30, 2026
8 checks passed
@fx
fx deleted the fix/0042-stepper-clipping branch July 30, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants