Skip to content

[Render Preview] [Feature] Toggle + ToggleGroup; refactor ThemeToggle#392

Open
djalmaaraujo wants to merge 22 commits into
mainfrom
da/toggle
Open

[Render Preview] [Feature] Toggle + ToggleGroup; refactor ThemeToggle#392
djalmaaraujo wants to merge 22 commits into
mainfrom
da/toggle

Conversation

@djalmaaraujo
Copy link
Copy Markdown
Contributor

Summary

  • Adds RubyUI::Toggle — two-state button (<button aria-pressed> + optional hidden input). Variants :default / :outline. Sizes :sm / :default / :lg. Mirrors shadcn/ui new-york-v4 Toggle.
  • Adds RubyUI::ToggleGroup + RubyUI::ToggleGroupItem — single (radio-like, roving tabindex, WAI-ARIA radiogroup) or multiple (independent toggles). Group owns selection + native form serialization.
  • Refactors RubyUI::ThemeToggle to compose Toggle (pressed = dark mode); removes SetDarkMode / SetLightMode helpers (breaking — gem is copy-paste distribution).
  • Stimulus controllers for both primitives; no custom CSS; no new gem/npm deps.
  • Docs pages, dependencies.yml, sidebar entries, sitemap/llms regenerated.

Test plan

  • cd gem && bundle exec rake — 187 tests, 779 assertions, 0 failures, StandardRB clean
  • /docs/toggle renders, all examples interactive
  • /docs/toggle_group single (arrow keys + space/enter), multiple, disabled
  • /docs/theme_toggle toggles theme, persists across reload
  • Cross-browser visual check
  • Screen reader announces radio (single) vs toggle button (multiple/standalone)

@djalmaaraujo djalmaaraujo requested a review from cirdes as a code owner May 11, 2026 22:22
Copy toggle_controller.js and toggle_group_controller.js from gem into
docs/app/javascript/controllers/ruby_ui/ and update theme_toggle_controller.js
to the new API (apply action + applyTheme helper replacing setLightTheme/setDarkTheme).
Regenerate Stimulus manifest so all three controllers are registered.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

5 issues found across 30 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="gem/lib/ruby_ui/theme_toggle/theme_toggle.rb">

<violation number="1" location="gem/lib/ruby_ui/theme_toggle/theme_toggle.rb:11">
P2: Duplicate Stimulus controller: `Toggle` already declares `ruby-ui--toggle` in its `default_attrs`. Phlex's `mix` concatenates `data-controller` strings, so the rendered output will be `"ruby-ui--toggle ruby-ui--toggle ruby-ui--theme-toggle"`. Only the additional controller should be specified here.</violation>
</file>

<file name="gem/lib/ruby_ui/theme_toggle/theme_toggle_controller.js">

<violation number="1" location="gem/lib/ruby_ui/theme_toggle/theme_toggle_controller.js:36">
P1: Wrong dataset key: `"rubyUi--TogglePressedValue"` should be `"rubyUi-TogglePressedValue"` (single hyphen). The HTML `data-` attribute conversion maps `data-ruby-ui--toggle-pressed-value` to the property key `rubyUi-TogglePressedValue`. The extra hyphen means this line sets a different (unused) attribute and the Toggle controller never sees the updated pressed state.</violation>
</file>

<file name="gem/lib/ruby_ui/toggle_group/toggle_group_item.rb">

<violation number="1" location="gem/lib/ruby_ui/toggle_group/toggle_group_item.rb:41">
P2: Roving tabindex bug: when a non-first item is selected in `:single` mode, both the first item (via `roving_first`) and the selected item (via `pressed`) get `tabindex="0"`. The `roving_first` fallback should only apply when no item in the group is selected.</violation>
</file>

<file name="docs/app/javascript/controllers/ruby_ui/toggle_controller.js">

<violation number="1" location="docs/app/javascript/controllers/ruby_ui/toggle_controller.js:25">
P2: The `pressedValueChanged` callback dispatches a `change` event during controller initialization (Stimulus value callbacks fire on `connect`). This causes a spurious event on page load before any user interaction. Guard against the initial call by checking the `previous` argument.</violation>
</file>

<file name="gem/lib/ruby_ui/toggle/toggle.rb">

<violation number="1" location="gem/lib/ruby_ui/toggle/toggle.rb:38">
P1: The hidden input is rendered as a sibling of the `<button>` that hosts the Stimulus controller, but Stimulus targets must be descendants of the controller element. When `name:` is provided, `this.hasInputTarget` will always be `false` and the hidden input value will never update on click, breaking form serialization.

Wrap both elements in a container that owns the controller, or move the controller declaration to a wrapping element.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread gem/lib/ruby_ui/theme_toggle/theme_toggle_controller.js Outdated
Comment thread gem/lib/ruby_ui/toggle/toggle.rb Outdated
Comment thread gem/lib/ruby_ui/theme_toggle/theme_toggle.rb Outdated
Comment thread gem/lib/ruby_ui/toggle_group/toggle_group_item.rb Outdated
Comment thread docs/app/javascript/controllers/ruby_ui/toggle_controller.js Outdated
@djalmaaraujo djalmaaraujo changed the title [Feature] Toggle + ToggleGroup; refactor ThemeToggle [Render Preview] [Feature] Toggle + ToggleGroup; refactor ThemeToggle May 12, 2026
…hemeToggle uses wrapper kwarg to compose controllers
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.

1 participant