From 270608f1172a5a122609ae72564e415b2193f23d Mon Sep 17 00:00:00 2001 From: Djalma Araujo Date: Tue, 24 Mar 2026 07:59:53 -0300 Subject: [PATCH 1/3] Regenerate ruby_ui components after gem bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run `rails g ruby_ui:component:all --force true` to sync generated components with the updated ruby_ui gem (f882429 → 755b288). --- .../combobox/combobox_toggle_all_checkbox.rb | 5 +- app/components/ruby_ui/docs/base.rb | 90 +++++++++++++++++++ .../ruby_ui/docs/component_setup_tabs.rb | 15 ++++ .../ruby_ui/docs/components_table.rb | 13 +++ app/components/ruby_ui/docs/header.rb | 17 ++++ .../ruby_ui/docs/sidebar_examples.rb | 22 +++++ .../ruby_ui/docs/visual_code_example.rb | 22 +++++ app/components/ruby_ui/form/form_field.rb | 2 +- .../ruby_ui/form/form_field_error.rb | 2 +- .../ruby_ui/form/form_field_hint.rb | 2 +- .../ruby_ui/form/form_field_label.rb | 2 +- app/components/ruby_ui/input/input.rb | 3 +- .../ruby_ui/native_select/native_select.rb | 39 ++++++++ .../native_select/native_select_group.rb | 15 ++++ .../native_select/native_select_icon.rb | 39 ++++++++ .../native_select/native_select_option.rb | 15 ++++ app/components/ruby_ui/sheet/sheet_content.rb | 2 +- 17 files changed, 297 insertions(+), 8 deletions(-) create mode 100644 app/components/ruby_ui/docs/base.rb create mode 100644 app/components/ruby_ui/docs/component_setup_tabs.rb create mode 100644 app/components/ruby_ui/docs/components_table.rb create mode 100644 app/components/ruby_ui/docs/header.rb create mode 100644 app/components/ruby_ui/docs/sidebar_examples.rb create mode 100644 app/components/ruby_ui/docs/visual_code_example.rb create mode 100644 app/components/ruby_ui/native_select/native_select.rb create mode 100644 app/components/ruby_ui/native_select/native_select_group.rb create mode 100644 app/components/ruby_ui/native_select/native_select_icon.rb create mode 100644 app/components/ruby_ui/native_select/native_select_option.rb diff --git a/app/components/ruby_ui/combobox/combobox_toggle_all_checkbox.rb b/app/components/ruby_ui/combobox/combobox_toggle_all_checkbox.rb index 01a6e811..8cb97c0d 100644 --- a/app/components/ruby_ui/combobox/combobox_toggle_all_checkbox.rb +++ b/app/components/ruby_ui/combobox/combobox_toggle_all_checkbox.rb @@ -12,9 +12,10 @@ def default_attrs { class: [ "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background accent-primary", - "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", "disabled:cursor-not-allowed disabled:opacity-50", - "aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none" + "checked:bg-primary checked:text-primary-foreground", + "aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none", + "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2" ], data: { ruby_ui__combobox_target: "toggleAll", diff --git a/app/components/ruby_ui/docs/base.rb b/app/components/ruby_ui/docs/base.rb new file mode 100644 index 00000000..459cf6a3 --- /dev/null +++ b/app/components/ruby_ui/docs/base.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +module Views + class Base < Phlex::HTML + def Heading(level:, &) + tag = :"h#{level}" + send(tag, &) + end + + def component_files(component_name) + [] + end + + # Text helper for wrapping paragraphs + def Text(&) + p(&) + end + + # InlineLink helper for documentation links + def InlineLink(href:, target: nil, class: nil, &) + a(href: href, target: target, class: binding.local_variable_get(:class), &) + end + + # Alert component helpers + def Alert(&) + div(&) + end + + def AlertTitle(&) + h4(&) + end + + def AlertDescription(&) + p(&) + end + + # Route helper stubs - return "#" as placeholder + def docs_sheet_path + "#" + end + + def docs_separator_path + "#" + end + + def docs_accordion_path + "#" + end + + def docs_alert_path + "#" + end + + def docs_alert_dialog_path + "#" + end + + def docs_aspect_ratio_path + "#" + end + + def docs_avatar_path + "#" + end + + def docs_badge_path + "#" + end + + def docs_installation_path + "#" + end + + # InlineCode helper for typography examples + def InlineCode(&) + code(&) + end + end +end + +# Module-level components stub +module Components + def self.Heading(level:, &block) + # Stub for module-level Heading calls + end + + def self.TypographyList(items:, numbered: false) + # Stub for TypographyList component + end +end diff --git a/app/components/ruby_ui/docs/component_setup_tabs.rb b/app/components/ruby_ui/docs/component_setup_tabs.rb new file mode 100644 index 00000000..4f48449e --- /dev/null +++ b/app/components/ruby_ui/docs/component_setup_tabs.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Components + module ComponentSetup + class Tabs < Phlex::HTML + def initialize(component_name:) + @component_name = component_name + end + + def view_template + # Minimal stub - empty by default + end + end + end +end diff --git a/app/components/ruby_ui/docs/components_table.rb b/app/components/ruby_ui/docs/components_table.rb new file mode 100644 index 00000000..4738a144 --- /dev/null +++ b/app/components/ruby_ui/docs/components_table.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Docs + class ComponentsTable < Phlex::HTML + def initialize(files) + @files = files + end + + def view_template + # Minimal stub - empty by default + end + end +end diff --git a/app/components/ruby_ui/docs/header.rb b/app/components/ruby_ui/docs/header.rb new file mode 100644 index 00000000..4624a796 --- /dev/null +++ b/app/components/ruby_ui/docs/header.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Docs + class Header < Phlex::HTML + def initialize(title:, description: nil) + @title = title + @description = description + end + + def view_template + div do + h1 { @title } + p { @description } if @description + end + end + end +end diff --git a/app/components/ruby_ui/docs/sidebar_examples.rb b/app/components/ruby_ui/docs/sidebar_examples.rb new file mode 100644 index 00000000..e9db4a34 --- /dev/null +++ b/app/components/ruby_ui/docs/sidebar_examples.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +# Stub constants for sidebar documentation examples +# These are replaced with actual implementations in the web app + +module Views + module Docs + class Sidebar < Views::Base + class Example + CODE = <<~RUBY + # Sidebar example code placeholder + RUBY + end + + class InsetExample + CODE = <<~RUBY + # Sidebar inset example code placeholder + RUBY + end + end + end +end diff --git a/app/components/ruby_ui/docs/visual_code_example.rb b/app/components/ruby_ui/docs/visual_code_example.rb new file mode 100644 index 00000000..39c6154d --- /dev/null +++ b/app/components/ruby_ui/docs/visual_code_example.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Docs + class VisualCodeExample < Phlex::HTML + def initialize(title:, context:, description: nil, src: nil) + @title = title + @context = context + @description = description + @src = src + end + + def view_template(&block) + code = block.call + div do + h3 { @title } + p { @description } if @description + pre { code } + @context.instance_eval(code) + end + end + end +end diff --git a/app/components/ruby_ui/form/form_field.rb b/app/components/ruby_ui/form/form_field.rb index dc4b511c..3665f02b 100644 --- a/app/components/ruby_ui/form/form_field.rb +++ b/app/components/ruby_ui/form/form_field.rb @@ -13,7 +13,7 @@ def default_attrs data: { controller: "ruby-ui--form-field" }, - class: "space-y-2" + class: "flex flex-col gap-2" } end end diff --git a/app/components/ruby_ui/form/form_field_error.rb b/app/components/ruby_ui/form/form_field_error.rb index 58c43d35..c47d779c 100644 --- a/app/components/ruby_ui/form/form_field_error.rb +++ b/app/components/ruby_ui/form/form_field_error.rb @@ -13,7 +13,7 @@ def default_attrs data: { ruby_ui__form_field_target: "error" }, - class: "text-xs font-medium text-destructive" + class: "empty:hidden text-sm font-medium text-destructive" } end end diff --git a/app/components/ruby_ui/form/form_field_hint.rb b/app/components/ruby_ui/form/form_field_hint.rb index 5304a259..ba7a5b6c 100644 --- a/app/components/ruby_ui/form/form_field_hint.rb +++ b/app/components/ruby_ui/form/form_field_hint.rb @@ -9,7 +9,7 @@ def view_template(&) private def default_attrs - {class: "text-sm text-muted-foreground"} + {class: "empty:hidden text-sm text-muted-foreground"} end end end diff --git a/app/components/ruby_ui/form/form_field_label.rb b/app/components/ruby_ui/form/form_field_label.rb index 5a7b85b1..bfda2b27 100644 --- a/app/components/ruby_ui/form/form_field_label.rb +++ b/app/components/ruby_ui/form/form_field_label.rb @@ -11,7 +11,7 @@ def view_template(&) def default_attrs { class: [ - "text-sm font-medium leading-none inline-block", + "empty:hidden text-sm font-medium leading-none", "peer-disabled:cursor-not-allowed peer-disabled:opacity-70", "peer-aria-disabled:cursor-not-allowed peer-aria-disabled:opacity-70 peer-aria-disabled:pointer-events-none" ] diff --git a/app/components/ruby_ui/input/input.rb b/app/components/ruby_ui/input/input.rb index fdb3a484..45c79860 100644 --- a/app/components/ruby_ui/input/input.rb +++ b/app/components/ruby_ui/input/input.rb @@ -24,8 +24,9 @@ def default_attrs "placeholder:text-muted-foreground", "disabled:cursor-not-allowed disabled:opacity-50", "file:border-0 file:bg-transparent file:text-sm file:font-medium", + "aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none", "focus-visible:outline-none focus-visible:ring-ring/50 focus-visible:ring-2 focus-visible:border-ring focus-visible:shadow-sm", - "aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:pointer-events-none" + (@type.to_s == "file") ? "pt-[7px]" : "" ] } end diff --git a/app/components/ruby_ui/native_select/native_select.rb b/app/components/ruby_ui/native_select/native_select.rb new file mode 100644 index 00000000..9c100968 --- /dev/null +++ b/app/components/ruby_ui/native_select/native_select.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module RubyUI + class NativeSelect < Base + def initialize(size: :default, **attrs) + @size = size + super(**attrs) + end + + def view_template(&block) + div( + class: "group/native-select relative w-fit has-[select:disabled]:opacity-50" + ) do + select(**attrs, &block) + render RubyUI::NativeSelectIcon.new + end + end + + private + + def default_attrs + { + data: { + ruby_ui__form_field_target: "input", + action: "change->ruby-ui--form-field#onChange invalid->ruby-ui--form-field#onInvalid" + }, + class: [ + "border-border bg-transparent text-sm w-full min-w-0 appearance-none rounded-md border py-1 pr-8 pl-2.5 shadow-xs transition-[color,box-shadow] outline-none select-none ring-0 ring-ring/0", + "placeholder:text-muted-foreground", + "selection:bg-primary selection:text-primary-foreground", + "focus-visible:outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-2", + "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", + "aria-invalid:ring-destructive/20 aria-invalid:border-destructive aria-invalid:ring-2", + (@size == :sm) ? "h-7 rounded-md py-0.5" : "h-9" + ] + } + end + end +end diff --git a/app/components/ruby_ui/native_select/native_select_group.rb b/app/components/ruby_ui/native_select/native_select_group.rb new file mode 100644 index 00000000..d3fae6d7 --- /dev/null +++ b/app/components/ruby_ui/native_select/native_select_group.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module RubyUI + class NativeSelectGroup < Base + def view_template(&) + optgroup(**attrs, &) + end + + private + + def default_attrs + {} + end + end +end diff --git a/app/components/ruby_ui/native_select/native_select_icon.rb b/app/components/ruby_ui/native_select/native_select_icon.rb new file mode 100644 index 00000000..1169df8a --- /dev/null +++ b/app/components/ruby_ui/native_select/native_select_icon.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module RubyUI + class NativeSelectIcon < Base + def view_template(&block) + span(**attrs) do + if block + block.call + else + icon + end + end + end + + private + + def icon + svg( + xmlns: "http://www.w3.org/2000/svg", + viewbox: "0 0 24 24", + fill: "none", + stroke: "currentColor", + stroke_width: "2", + stroke_linecap: "round", + stroke_linejoin: "round", + class: "size-4", + aria_hidden: "true" + ) do |s| + s.path(d: "m6 9 6 6 6-6") + end + end + + def default_attrs + { + class: "text-muted-foreground pointer-events-none absolute top-1/2 right-2.5 -translate-y-1/2 select-none" + } + end + end +end diff --git a/app/components/ruby_ui/native_select/native_select_option.rb b/app/components/ruby_ui/native_select/native_select_option.rb new file mode 100644 index 00000000..bf4dd3e3 --- /dev/null +++ b/app/components/ruby_ui/native_select/native_select_option.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module RubyUI + class NativeSelectOption < Base + def view_template(&) + option(**attrs, &) + end + + private + + def default_attrs + {} + end + end +end diff --git a/app/components/ruby_ui/sheet/sheet_content.rb b/app/components/ruby_ui/sheet/sheet_content.rb index bf3a3115..a097f1e1 100644 --- a/app/components/ruby_ui/sheet/sheet_content.rb +++ b/app/components/ruby_ui/sheet/sheet_content.rb @@ -33,7 +33,7 @@ def default_attrs { data_state: "open", # For animate in class: [ - "fixed pointer-events-auto z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", + "fixed pointer-events-auto z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 overflow-scroll", @side_classes ] } From 8fa4bfbf385551112ab52421c60f49cdfd10a760 Mon Sep 17 00:00:00 2001 From: Djalma Araujo Date: Tue, 24 Mar 2026 08:02:09 -0300 Subject: [PATCH 2/3] Remove generated ruby_ui/docs stubs that conflict with existing components The docs component stubs (base, component_setup_tabs, etc.) generated by ruby_ui:component:all conflict with the app's existing Components::ComponentSetup namespace, causing a superclass mismatch TypeError. --- app/components/ruby_ui/docs/base.rb | 90 ------------------- .../ruby_ui/docs/component_setup_tabs.rb | 15 ---- .../ruby_ui/docs/components_table.rb | 13 --- app/components/ruby_ui/docs/header.rb | 17 ---- .../ruby_ui/docs/sidebar_examples.rb | 22 ----- .../ruby_ui/docs/visual_code_example.rb | 22 ----- 6 files changed, 179 deletions(-) delete mode 100644 app/components/ruby_ui/docs/base.rb delete mode 100644 app/components/ruby_ui/docs/component_setup_tabs.rb delete mode 100644 app/components/ruby_ui/docs/components_table.rb delete mode 100644 app/components/ruby_ui/docs/header.rb delete mode 100644 app/components/ruby_ui/docs/sidebar_examples.rb delete mode 100644 app/components/ruby_ui/docs/visual_code_example.rb diff --git a/app/components/ruby_ui/docs/base.rb b/app/components/ruby_ui/docs/base.rb deleted file mode 100644 index 459cf6a3..00000000 --- a/app/components/ruby_ui/docs/base.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: true - -module Views - class Base < Phlex::HTML - def Heading(level:, &) - tag = :"h#{level}" - send(tag, &) - end - - def component_files(component_name) - [] - end - - # Text helper for wrapping paragraphs - def Text(&) - p(&) - end - - # InlineLink helper for documentation links - def InlineLink(href:, target: nil, class: nil, &) - a(href: href, target: target, class: binding.local_variable_get(:class), &) - end - - # Alert component helpers - def Alert(&) - div(&) - end - - def AlertTitle(&) - h4(&) - end - - def AlertDescription(&) - p(&) - end - - # Route helper stubs - return "#" as placeholder - def docs_sheet_path - "#" - end - - def docs_separator_path - "#" - end - - def docs_accordion_path - "#" - end - - def docs_alert_path - "#" - end - - def docs_alert_dialog_path - "#" - end - - def docs_aspect_ratio_path - "#" - end - - def docs_avatar_path - "#" - end - - def docs_badge_path - "#" - end - - def docs_installation_path - "#" - end - - # InlineCode helper for typography examples - def InlineCode(&) - code(&) - end - end -end - -# Module-level components stub -module Components - def self.Heading(level:, &block) - # Stub for module-level Heading calls - end - - def self.TypographyList(items:, numbered: false) - # Stub for TypographyList component - end -end diff --git a/app/components/ruby_ui/docs/component_setup_tabs.rb b/app/components/ruby_ui/docs/component_setup_tabs.rb deleted file mode 100644 index 4f48449e..00000000 --- a/app/components/ruby_ui/docs/component_setup_tabs.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module Components - module ComponentSetup - class Tabs < Phlex::HTML - def initialize(component_name:) - @component_name = component_name - end - - def view_template - # Minimal stub - empty by default - end - end - end -end diff --git a/app/components/ruby_ui/docs/components_table.rb b/app/components/ruby_ui/docs/components_table.rb deleted file mode 100644 index 4738a144..00000000 --- a/app/components/ruby_ui/docs/components_table.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module Docs - class ComponentsTable < Phlex::HTML - def initialize(files) - @files = files - end - - def view_template - # Minimal stub - empty by default - end - end -end diff --git a/app/components/ruby_ui/docs/header.rb b/app/components/ruby_ui/docs/header.rb deleted file mode 100644 index 4624a796..00000000 --- a/app/components/ruby_ui/docs/header.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module Docs - class Header < Phlex::HTML - def initialize(title:, description: nil) - @title = title - @description = description - end - - def view_template - div do - h1 { @title } - p { @description } if @description - end - end - end -end diff --git a/app/components/ruby_ui/docs/sidebar_examples.rb b/app/components/ruby_ui/docs/sidebar_examples.rb deleted file mode 100644 index e9db4a34..00000000 --- a/app/components/ruby_ui/docs/sidebar_examples.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -# Stub constants for sidebar documentation examples -# These are replaced with actual implementations in the web app - -module Views - module Docs - class Sidebar < Views::Base - class Example - CODE = <<~RUBY - # Sidebar example code placeholder - RUBY - end - - class InsetExample - CODE = <<~RUBY - # Sidebar inset example code placeholder - RUBY - end - end - end -end diff --git a/app/components/ruby_ui/docs/visual_code_example.rb b/app/components/ruby_ui/docs/visual_code_example.rb deleted file mode 100644 index 39c6154d..00000000 --- a/app/components/ruby_ui/docs/visual_code_example.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -module Docs - class VisualCodeExample < Phlex::HTML - def initialize(title:, context:, description: nil, src: nil) - @title = title - @context = context - @description = description - @src = src - end - - def view_template(&block) - code = block.call - div do - h3 { @title } - p { @description } if @description - pre { code } - @context.instance_eval(code) - end - end - end -end From 197a223781e5fa64e7bd6977514ea6713b7f1826 Mon Sep 17 00:00:00 2001 From: Djalma Araujo Date: Tue, 24 Mar 2026 08:09:41 -0300 Subject: [PATCH 3/3] Fix verify_components: ignore generated docs stubs The ruby_ui generator creates docs component stubs that conflict with the app's existing Components::ComponentSetup namespace (superclass mismatch). Revert those generated files before the git status check. --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27af1e4a..ea923291 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,9 @@ jobs: - name: Build run: bin/rails g ruby_ui:component:all --force true + - name: Remove generated docs stubs (conflict with app overrides) + run: git checkout -- app/components/ruby_ui/docs/ 2>/dev/null || rm -rf app/components/ruby_ui/docs/ + - uses: CatChen/check-git-status-action@v2 with: fail-if-not-clean: true