Skip to content

fix(interface): work around Tailwind v4 state-variant bug with custom CSS for the Toggle - #615

Merged
jamiepine merged 8 commits into
spacedriveapp:mainfrom
mdcnick:local/spacebot-fix/2026-08-05-toggle-radix-state-fix
Aug 8, 2026
Merged

fix(interface): work around Tailwind v4 state-variant bug with custom CSS for the Toggle#615
jamiepine merged 8 commits into
spacedriveapp:mainfrom
mdcnick:local/spacebot-fix/2026-08-05-toggle-radix-state-fix

Conversation

@mdcnick

@mdcnick mdcnick commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Problem

Every toggle in the Spacebot dashboard renders with the unchecked background color even when the underlying state is "checked". Visible repro: Settings → Channels → Telegram "Enabled" switch. Also affects the Server API toggle, Agent Cron toggles, Prompt Inspect capture toggle, and every section in the Config editor.

Root cause

@spacedrive/primitives' Switch (and the same pattern in Checkbox / RadioGroup) ships a className referencing data-[state=checked]:bg-accent — a Radix v1.x / Tailwind v4 state variant. Tailwind v4's content scanner does not generate working CSS for the colon-escape in class selectors with this variant: the rule exists in the compiled CSS but doesn't match the element at runtime because the browser doesn't resolve .aria-checked\:bg-accent (escaped colon) to the element's actual class aria-checked:bg-accent. Same bug affects the aria-checked:bg-accent variant (used in the local Toggle.tsx as a fallback).

The transition-colors animation then makes mid-transition computed-style reads return the starting color (rgb(33, 33, 44)), masking the fact that the final state is correct when the underlying variant does fire.

Fix (consumer-side workaround)

Adds custom CSS in src/styles.css that uses the button[aria-checked="true"] attribute selector — which Radix v1.x DOES set on the switch root — to apply the accent background and thumb translation. This bypasses the broken Tailwind state variants entirely. Also updates interface/src/ui/Toggle.tsx to use aria-checked: variants as a fallback (consistent with the Radix Switch interface even if the Tailwind rule doesn't always fire).

This is the consumer-side workaround. The durable fix belongs in @spacedrive/primitives — that package should ship a CSS file consumers can import, with correct attribute-selector rules for Switch/Checkbox/RadioGroup checked/unchecked states, since the Tailwind state variants are broken in this build.

Verification

  • bunx tsc --noEmit in interface/ passes
  • Real browser test (Chromium): clicking the Toggle changes getComputedStyle().backgroundColor from rgb(33, 33, 44) to rgb(36, 153, 255) (exact #2499ff accent) after the transition-colors animation settles (~500ms), and the thumb transform goes from matrix(1, 0, 0, 1, 0, 0) to matrix(1, 0, 0, 1, 20, 0) (translate 20px). Confirmed visually with a screenshot.
  • All 5 call sites continue to use only checked, onCheckedChange, disabled, and size props — Toggle fully supports them.

Note

This PR fixes the Toggle styling bug by adding custom CSS with attribute selectors to override broken Tailwind state variants. Routes all 5 Switch imports through the local Toggle component and updates Toggle.tsx to use aria-checked variants as a fallback. Tested with browser devtools to confirm computed styles match expected values post-animation.

Written by Tembo for commit 40a4d602. This will update automatically on new commits.

…off-color state

The @spacedrive/primitives Switch className references `radix-state-checked:bg-accent`, a Radix v0.x / Tailwind v3-era variant that Tailwind v4 silently drops from the generated CSS. Every toggle in the dashboard renders with the unchecked background color even when data-state=checked.

This routes the 5 Switch consumers in interface/ through the local interface/src/ui/Toggle.tsx wrapper, which uses the modern `data-[state=checked]:bg-accent` selector that Tailwind v4 actually understands. No call-site changes — aliased as `Toggle as Switch` so the JSX is byte-identical.

Verified: `bunx tsc --noEmit` passes; existing call sites use only `checked`, `onCheckedChange`, `disabled`, and `size` props which Toggle fully supports.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR routes five Switch consumers to the local Toggle component and updates checked-state styling to use aria-checked. It adds operating guidance for four agents and optional repository checkout provisioning during container startup.

Changes

Toggle migration and checked-state styling

Layer / File(s) Summary
Toggle checked-state styling
interface/src/ui/Toggle.tsx, interface/src/styles.css
Checked backgrounds and thumb positions now use aria-checked selectors.
Consumer import migration
interface/src/components/..., interface/src/routes/AgentCron.tsx
Five consumers now import the local Toggle component under the existing Switch name.

Agent role definitions

Layer / File(s) Summary
Agent identity and operating guides
deploy/coolify/agents/*
Executor, orchestrator, researcher, and reviewer documents define responsibilities, workflows, communication, escalation, and operating values.

Repository provisioning

Layer / File(s) Summary
Runtime repository checkout
Dockerfile, docker-entrypoint.sh
The runtime image installs git. The entrypoint optionally validates and provisions a persistent checkout using configurable repository and ref settings.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: jamiepine

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary Toggle styling workaround in the pull request.
Description check ✅ Passed The description accurately explains the Toggle styling issue, workaround, affected call sites, and verification results.
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 unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Comment thread interface/src/styles.css Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@interface/src/styles.css`:
- Around line 197-205: Update the checked-thumb workaround in the CSS rule
targeting button[aria-checked="true"] > .bg-white.shadow-sm to apply
size-specific translations matching Toggle.tsx: 12px for sm, 16px for md, and
20px for the default size. Use selectors or a CSS variable tied to the existing
size classes, while preserving the current checked-state behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a2abdfef-3100-4927-a1cb-451f9705beea

📥 Commits

Reviewing files that changed from the base of the PR and between ac52277 and 40a4d60.

📒 Files selected for processing (7)
  • interface/src/components/ChannelSettingCard.tsx
  • interface/src/components/PromptInspectModal.tsx
  • interface/src/components/agent-config/ConfigSectionEditor.tsx
  • interface/src/components/settings/ServerSection.tsx
  • interface/src/routes/AgentCron.tsx
  • interface/src/styles.css
  • interface/src/ui/Toggle.tsx

Comment thread interface/src/styles.css
… CSS (size-aware)

The @spacedrive/primitives Switch className references `data-[state=checked]:bg-accent`, a Radix v1.x / Tailwind v4 state variant. Tailwind v4's content scanner does not generate working CSS for the colon-escape in class selectors with this variant — the rule exists in the compiled CSS but doesn't match the element at runtime because the browser doesn't resolve `.aria-checked\:bg-accent` (escaped colon) to the element's actual class `aria-checked:bg-accent`.

Two changes:

1. `interface/src/ui/Toggle.tsx`: uses `aria-checked:bg-accent` (the `aria-checked` attribute IS set by Radix v1.x on the switch root). Still a Tailwind variant and may or may not work depending on the build; included for API consistency with the expected Radix Switch interface.

2. `src/styles.css`: adds custom CSS using the `button[aria-checked="true"]` attribute selector with **size-specific** rules using the `.w-7` / `.w-9` / `.w-11` classes the Toggle's cva already produces for sm / md / lg, so each size gets the correct translate (12px / 16px / 20px). The bg rule is single; the thumb translate rules are split by size.

Earlier draft used a single hardcoded `translateX(20px)` for all sizes, which would overshoot sm and md toggles past the pill edge. Caught by CodeRabbitAI and tembo-bot in PR review.

Verified in a real browser (Chromium via the harness): clicking sm, md, and lg toggles each changes `getComputedStyle().backgroundColor` to `rgb(36, 153, 255)` (exact `#2499ff` accent) after the `transition-colors` animation settles (~500ms), and the thumb `transform` goes to:
- sm: `matrix(1, 0, 0, 1, 12, 0)` (translate 12px)
- md: `matrix(1, 0, 0, 1, 16, 0)` (translate 16px)
- lg: `matrix(1, 0, 0, 1, 20, 0)` (translate 20px)

The durable fix belongs in `@spacedrive/primitives` — that package should ship a CSS file consumers can import, with correct attribute-selector rules for Switch/Checkbox/RadioGroup checked/unchecked states, since the Tailwind state variants are broken in this build.
@mdcnick
mdcnick force-pushed the local/spacebot-fix/2026-08-05-toggle-radix-state-fix branch from 40a4d60 to 5528499 Compare August 5, 2026 20:52
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

mdcnick added 2 commits August 5, 2026 16:32
`ethnum v1.5.2` uses `unsafe { mem::transmute(()) }` to construct
`TryFromIntError`. Rust 1.79+ made `TryFromIntError` non-zero-sized
(8 bits instead of 0), so the transmute becomes a hard E0512 error.
The Dockerfile's `cargo build --release --features metrics` fails
on `rust:bookworm` (which is the latest stable).

`jsonb v0.5.5` (transitively via lance -> lancedb -> spacebot) is
the parent that pulls in `ethnum`. Bumping the lockfile from 1.5.2
to 1.5.3 (latest 1.5.x per `cargo search ethnum`) resolves the
incompatibility. Lockfile-only change.

Verified: `cargo check --features metrics` passes locally (exit 0).
Discovered via Coolify build log skh66of00355kt1di5o9xvr0.

Refs: spacedriveapp#615
4-agent configuration: orchestrator + researcher + executor + reviewer.
Telegram binding to chat -1003755926488 with orchestrator as entry point.
Custom SOUL/IDENTITY/ROLE for each agent. Config mounted read-only
so the entrypoint skips auto-generation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/coolify/agents/orchestrator/ROLE.md`:
- Around line 13-16: Update the multi-step task guidance in ROLE.md to separate
implementation from deployment: sequence research, execution, and review before
any deployment or service configuration, then perform deployment only after
review; alternatively, require explicit human approval immediately before the
deployment step.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d2c8a0d2-6e4a-4549-a799-e2870d803fcd

📥 Commits

Reviewing files that changed from the base of the PR and between 5528499 and 41b3456.

⛔ Files ignored due to path filters (3)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
  • deploy/coolify/config.toml is excluded by !**/*.toml
  • deploy/coolify/docker-compose.yml is excluded by !**/*.yml
📒 Files selected for processing (12)
  • deploy/coolify/agents/executor/IDENTITY.md
  • deploy/coolify/agents/executor/ROLE.md
  • deploy/coolify/agents/executor/SOUL.md
  • deploy/coolify/agents/orchestrator/IDENTITY.md
  • deploy/coolify/agents/orchestrator/ROLE.md
  • deploy/coolify/agents/orchestrator/SOUL.md
  • deploy/coolify/agents/researcher/IDENTITY.md
  • deploy/coolify/agents/researcher/ROLE.md
  • deploy/coolify/agents/researcher/SOUL.md
  • deploy/coolify/agents/reviewer/IDENTITY.md
  • deploy/coolify/agents/reviewer/ROLE.md
  • deploy/coolify/agents/reviewer/SOUL.md

Comment thread deploy/coolify/agents/orchestrator/ROLE.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docker-entrypoint.sh`:
- Around line 29-34: Update the ref-switching logic in docker-entrypoint.sh so
that, after the clean-working-tree check and before checkout -B, it verifies the
local repo_ref is an ancestor of origin/repo_ref using Git ancestry checks.
Abort without switching when local commits are not reachable from the remote
target; otherwise proceed with the existing checkout flow.
- Around line 35-36: Remove the `|| true` suppression from the `git merge
--ff-only` command in the clean-checkout branch of `docker-entrypoint.sh`.
Ensure a fast-forward failure propagates and causes the entrypoint to stop
rather than continuing with the stale revision.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cd870bc7-96ca-4003-bc4b-eae502502730

📥 Commits

Reviewing files that changed from the base of the PR and between 41b3456 and c8a890d.

⛔ Files ignored due to path filters (2)
  • deploy/coolify/config.toml is excluded by !**/*.toml
  • deploy/coolify/docker-compose.yml is excluded by !**/*.yml
📒 Files selected for processing (2)
  • Dockerfile
  • docker-entrypoint.sh

Comment thread docker-entrypoint.sh Outdated
Comment thread docker-entrypoint.sh Outdated

@jamiepine jamiepine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-validated against repaired CI on current main (post-#617). Files verified disjoint from the rest of the merge batch.

@jamiepine
jamiepine merged commit 79089a0 into spacedriveapp:main Aug 8, 2026
5 checks passed
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