Skip to content

fix: free the covered sidebar controls, unify selects, give OpenClaw a mark - #58

Merged
yujiezhang-ops merged 1 commit into
mainfrom
fix/sidebar-overlay-selects-and-openclaw-mark
Aug 6, 2026
Merged

fix: free the covered sidebar controls, unify selects, give OpenClaw a mark#58
yujiezhang-ops merged 1 commit into
mainfrom
fix/sidebar-overlay-selects-and-openclaw-mark

Conversation

@yujiezhang-ops

Copy link
Copy Markdown
Collaborator

Closes #54, #55, #56.

1. The language picker was not missing — it was unreachable (#54)

.task-center is position: fixed at the viewport's lower-left corner and contributes no height to the sidebar's flex column, so the rows margin-top: auto pushes to the bottom ended up underneath it. The control stayed rendered, visible, and in the accessibility tree while taking no clicks:

document.elementFromPoint(cx, cy)   // → <SPAN> inside .task-center
sel.contains(hit)                    // → false

At 1180×760 the overlap was 179 × 36 px. The theme row survived only because it cleared the overlay by 2px — which is why this presented as one button disappearing rather than a dead strip along the bottom.

The sidebar now reserves --task-center-reserve at its bottom edge. Three numbers have to agree to avoid the collision (the trigger's height, its viewport offset, the gap), so they live in one token rather than as three separate magic numbers. Nudging bottom or z-index to dodge would only move the collision to a different window height.

2. Selects are unified (#55)

All four were appearance: auto, with no appearance: none anywhere in the stylesheets — native macOS controls here, something else again on Windows and Linux, while every other control stayed consistent. They now share one rule in base.css with a drawn arrow and the existing tokens.

Two things worth knowing:

  • The open <option> list stays OS-drawn. CSS cannot reach it, so this unifies the closed state only. Matching the open list would mean a custom component reimplementing keyboard navigation and the accessibility tree — not worth it for three pickers.
  • background shorthand silently resets the arrow. The three per-picker rules had to move to background-color. Easy to reintroduce later, so it is called out in a comment at each site.

At the 72px icon rail the arrow is dropped rather than shrunk: 48px of column has no room for both the value and the arrow. That rule is written as .language-picker .language-select-compact to match the base rule's specificity — the bare class loses and would have kept the wide padding, leaving a 22px gap with no arrow in it.

3. OpenClaw gets a real mark, with the caveats stated (#56)

Per the decision on #56, the artwork is the lobster cc-switch drew (MIT, Copyright (c) 2025 Jason Young), recoloured here from a red gradient to a single currentColor glyph so it adapts to the theme like the other four.

Two facts a reviewer should not have to discover by diffing:

  1. It is not the vendor's own artwork — no official OpenClaw vector is published.
  2. OneAgent modified it — the linearGradient (#ff4d4d#991b1b), the coloured antenna stroke, and the cyan eye highlights are gone.

The eyes became a mask cut-out rather than a filled shape; once everything shares one colour a filled eye would merge into the body. Geometry is untouched — the viewBox is still 0 0 120 120, and normalising it to 24 would be exactly the re-drawing the geometry test exists to prevent.

MIT permits the change and requires it to be stated, so the statement travels with the artifact rather than living only in source:

  • asset-rights.json carries modified: true plus the specifics
  • the cc-switch licence ships at icons/licenses/cc-switch/LICENSE
  • THIRD_PARTY_NOTICES.md gained a Modified third-party material section — that file is what reaches the user, so a note only in the source manifest would not discharge the requirement
  • the generator now refuses to build a manifest where modified is set without a note (mutation-tested: deleting modificationNote fails --check)

NOTICE is corrected alongside — it still claimed OpenClaw used a generic Lucide symbol and that every image asset was unmodified.

On the tests

The clickability regression is an e2e test, not a unit test. jsdom reports every rect as 0x0, so a unit test cannot see the collision, and asserting display or visibility would have passed throughout — both were correct the whole time. It hit-tests every bottom sidebar control at both sidebar widths, then clicks with a real pointer: dispatching events directly, which is what selectOption does, also passed while the control was covered.

It was written before the CSS fix landed and failed on the real collision first (coveredBy: "SPAN." on .language-select-wide), so it is verified against the actual bug rather than an injected one.

The geometry test now checks each mark against its own source coordinate system instead of one shared value, with a guard so a new asset missing from the map fails rather than being skipped. A new test asserts the modification flag in both directions — claiming an unmodified mark was modified is also wrong.

Verification

  • go vet ./..., go test ./... clean
  • 24 frontend test files / 166 tests, tsc --noEmit clean
  • check-docs.py (48 files), generate_third_party_licenses.py --check, vite build clean
  • Measured in the browser at 1180×760 and 860×600: reserved space clears the overlay by 29px at both, every bottom control hit-tests to itself, arrows resolve to #3a3a3c / #d1d1d6 per theme matching --icon-fg
  • The mark rasterises to exactly one colour with alpha: 0 at both eye centres and alpha: 255 on the body — a genuine single-colour glyph with the eyes punched through

Two pre-existing e2e failures are unrelated. opens onboarding from the landing route and onboarding installs one Agent end to end fail identically on a stashed tree; they depend on a clean ~/.oneagent.

🤖 Generated with Claude Code

…a mark

Three reported problems, verified in the running app before changing anything.

The language picker was not missing, it was unreachable. .task-center is
position: fixed at the viewport's lower-left corner and contributes no
height to the sidebar's flex column, so the rows margin-top: auto pushes to
the bottom ended up underneath it: rendered, visible, in the accessibility
tree, and taking no clicks. elementFromPoint at the select's centre returned
the overlay's SPAN. The theme row survived only because it cleared the
overlay by 2px, which is why this read as one button disappearing rather
than a dead strip along the bottom.

The sidebar now reserves --task-center-reserve at its bottom edge. Three
numbers have to agree to avoid the collision -- the trigger's height, its
viewport offset, and the gap -- so they live in one token instead of as
separate magic numbers, and nudging bottom or z-index to dodge would only
move the collision to a different window height.

Selects are unified. All four were appearance: auto with no
appearance: none anywhere in the stylesheets, so they rendered as native
macOS controls here and as something else again on Windows and Linux while
the rest of the UI stayed consistent. They now share one rule with a drawn
arrow and the existing tokens. Two consequences worth knowing: the open
<option> list stays OS-drawn because CSS cannot reach it, so this unifies
the closed state only; and the three per-picker rules had to move from the
background shorthand to background-color, since the shorthand silently
resets the arrow image.

OpenClaw gets a real mark, with the compliance caveats stated rather than
buried. No official vector is published, so the artwork is the lobster
cc-switch drew (MIT, Copyright (c) 2025 Jason Young), recoloured here from a
red gradient to a single currentColor glyph so it adapts to the theme like
the other four. The eyes became a mask cut-out rather than a filled shape,
or they would have merged into the body once everything shared one colour.
Geometry is untouched: the viewBox is still 120x120, and normalising it to
24 would be the re-drawing the geometry test exists to prevent.

MIT permits the change and requires it to be stated, so the statement
travels with the artifact: asset-rights.json carries modified: true with the
specifics, the cc-switch licence ships under icons/licenses/cc-switch/, and
THIRD_PARTY_NOTICES.md gained a "Modified third-party material" section --
the notices file is what reaches the user, so a note only in the source
manifest would not discharge the requirement. The generator now refuses to
build a manifest where modified is set without a note.

NOTICE is corrected alongside it. It still claimed OpenClaw used a generic
Lucide symbol and that every image asset was unmodified.

The clickability regression is an e2e test, not a unit test: jsdom reports
every rect as 0x0, and asserting display or visibility would have passed
throughout because both were correct the whole time. It hit-tests every
bottom sidebar control at both sidebar widths and then clicks with a real
pointer, since dispatching events directly -- what selectOption does -- also
passed while the control was covered. It was written before the CSS fix
landed and failed on the real collision first.

Verified: go vet, go test, 24 frontend test files / 166 tests,
tsc --noEmit, check-docs.py, licence --check, and vite build. Measured in
the browser at 1180x760 and 860x600: the reserved space clears the overlay
by 29px at both, every control hit-tests to itself, arrows resolve to
--icon-fg per theme, and the mark rasterises to exactly one colour with
alpha 0 at both eyes. Two pre-existing e2e failures are unrelated and fail
identically on a stashed tree.

Closes #54, #55, #56.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yujiezhang-ops
yujiezhang-ops merged commit 818de55 into main Aug 6, 2026
4 checks passed
@yujiezhang-ops
yujiezhang-ops deleted the fix/sidebar-overlay-selects-and-openclaw-mark branch August 7, 2026 09:53
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.

[P0] 任务中心浮层盖住语言切换,该控件完全无法点击

1 participant