diff --git a/docs/app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js b/docs/app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js index d3cb0584..c4b3f629 100644 --- a/docs/app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js +++ b/docs/app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js @@ -2,9 +2,19 @@ import { Controller } from "@hotwired/stimulus"; export default class extends Controller { + connect() { + this.element + .querySelectorAll("input[type=checkbox][data-column-key]") + .forEach((checkbox) => + this._apply(checkbox.dataset.columnKey, checkbox.checked) + ); + } + toggle(event) { - const key = event.target.dataset.columnKey; - const visible = event.target.checked; + this._apply(event.target.dataset.columnKey, event.target.checked); + } + + _apply(key, visible) { const root = this.element.closest('[data-controller~="ruby-ui--data-table"]'); if (!root) return; root diff --git a/gem/lib/ruby_ui/data_table/data_table_column_toggle.rb b/gem/lib/ruby_ui/data_table/data_table_column_toggle.rb index ad20b217..b694b522 100644 --- a/gem/lib/ruby_ui/data_table/data_table_column_toggle.rb +++ b/gem/lib/ruby_ui/data_table/data_table_column_toggle.rb @@ -2,8 +2,9 @@ module RubyUI class DataTableColumnToggle < Base - def initialize(columns:, **attrs) + def initialize(columns:, label: "Columns", **attrs) @columns = columns + @label = label super(**attrs) end @@ -12,7 +13,7 @@ def view_template render RubyUI::DropdownMenu.new do render RubyUI::DropdownMenuTrigger.new do render RubyUI::Button.new(variant: :outline, size: :sm) do - plain "Columns" + plain @label # inline chevron-down SVG (lucide 24px, 1px stroke) svg( xmlns: "http://www.w3.org/2000/svg", @@ -35,8 +36,11 @@ def view_template label(class: "flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm cursor-pointer hover:bg-accent") do input( type: "checkbox", - checked: true, - class: "h-4 w-4 rounded border border-input accent-primary cursor-pointer", + checked: col.fetch(:visible, true), + class: [ + "h-4 w-4 rounded border border-input accent-primary cursor-pointer", + "checked:bg-primary checked:text-primary-foreground dark:checked:bg-secondary checked:text-primary checked:border-primary" + ], data: { column_key: col[:key].to_s, action: "change->ruby-ui--data-table-column-visibility#toggle" diff --git a/gem/lib/ruby_ui/data_table/data_table_column_visibility_controller.js b/gem/lib/ruby_ui/data_table/data_table_column_visibility_controller.js index d3cb0584..c4b3f629 100644 --- a/gem/lib/ruby_ui/data_table/data_table_column_visibility_controller.js +++ b/gem/lib/ruby_ui/data_table/data_table_column_visibility_controller.js @@ -2,9 +2,19 @@ import { Controller } from "@hotwired/stimulus"; export default class extends Controller { + connect() { + this.element + .querySelectorAll("input[type=checkbox][data-column-key]") + .forEach((checkbox) => + this._apply(checkbox.dataset.columnKey, checkbox.checked) + ); + } + toggle(event) { - const key = event.target.dataset.columnKey; - const visible = event.target.checked; + this._apply(event.target.dataset.columnKey, event.target.checked); + } + + _apply(key, visible) { const root = this.element.closest('[data-controller~="ruby-ui--data-table"]'); if (!root) return; root diff --git a/gem/test/ruby_ui/data_table_column_toggle_test.rb b/gem/test/ruby_ui/data_table_column_toggle_test.rb index ef3c4527..e4311279 100644 --- a/gem/test/ruby_ui/data_table_column_toggle_test.rb +++ b/gem/test/ruby_ui/data_table_column_toggle_test.rb @@ -17,4 +17,24 @@ def test_renders_dropdown_with_checkbox_per_column assert_match(/Email/, output) assert_match(/Salary/, output) end + + def test_renders_a_custom_trigger_label + output = phlex do + RubyUI.DataTableColumnToggle(label: "Colunas", columns: [ + {key: :email, label: "Email"} + ]) + end + assert_match(/Colunas/, output) + end + + def test_column_can_start_hidden + output = phlex do + RubyUI.DataTableColumnToggle(columns: [ + {key: :email, label: "Email"}, + {key: :salary, label: "Salary", visible: false} + ]) + end + # only the visible column renders the `checked` boolean attribute on its checkbox + assert_equal 1, output.scan(/\bchecked(?:\s|>)/).length + end end diff --git a/mcp/data/registry.json b/mcp/data/registry.json index 0c83744e..f94f438a 100644 --- a/mcp/data/registry.json +++ b/mcp/data/registry.json @@ -1182,11 +1182,11 @@ }, { "path": "data_table_column_toggle.rb", - "content": "# frozen_string_literal: true\n\nmodule RubyUI\n class DataTableColumnToggle < Base\n def initialize(columns:, **attrs)\n @columns = columns\n super(**attrs)\n end\n\n def view_template\n div(**attrs) do\n render RubyUI::DropdownMenu.new do\n render RubyUI::DropdownMenuTrigger.new do\n render RubyUI::Button.new(variant: :outline, size: :sm) do\n plain \"Columns\"\n # inline chevron-down SVG (lucide 24px, 1px stroke)\n svg(\n xmlns: \"http://www.w3.org/2000/svg\",\n width: \"16\",\n height: \"16\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n stroke_width: \"2\",\n stroke_linecap: \"round\",\n stroke_linejoin: \"round\",\n class: \"w-4 h-4 ml-1\"\n ) do |s|\n s.polyline(points: \"6 9 12 15 18 9\")\n end\n end\n end\n render RubyUI::DropdownMenuContent.new do\n @columns.each do |col|\n label(class: \"flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm cursor-pointer hover:bg-accent\") do\n input(\n type: \"checkbox\",\n checked: true,\n class: \"h-4 w-4 rounded border border-input accent-primary cursor-pointer\",\n data: {\n column_key: col[:key].to_s,\n action: \"change->ruby-ui--data-table-column-visibility#toggle\"\n }\n )\n span { plain col[:label] }\n end\n end\n end\n end\n end\n end\n\n private\n\n def default_attrs\n {\n class: \"relative\",\n data: {controller: \"ruby-ui--data-table-column-visibility\"}\n }\n end\n end\nend\n" + "content": "# frozen_string_literal: true\n\nmodule RubyUI\n class DataTableColumnToggle < Base\n def initialize(columns:, label: \"Columns\", **attrs)\n @columns = columns\n @label = label\n super(**attrs)\n end\n\n def view_template\n div(**attrs) do\n render RubyUI::DropdownMenu.new do\n render RubyUI::DropdownMenuTrigger.new do\n render RubyUI::Button.new(variant: :outline, size: :sm) do\n plain @label\n # inline chevron-down SVG (lucide 24px, 1px stroke)\n svg(\n xmlns: \"http://www.w3.org/2000/svg\",\n width: \"16\",\n height: \"16\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n stroke_width: \"2\",\n stroke_linecap: \"round\",\n stroke_linejoin: \"round\",\n class: \"w-4 h-4 ml-1\"\n ) do |s|\n s.polyline(points: \"6 9 12 15 18 9\")\n end\n end\n end\n render RubyUI::DropdownMenuContent.new do\n @columns.each do |col|\n label(class: \"flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm cursor-pointer hover:bg-accent\") do\n input(\n type: \"checkbox\",\n checked: col.fetch(:visible, true),\n class: [\n \"h-4 w-4 rounded border border-input accent-primary cursor-pointer\",\n \"checked:bg-primary checked:text-primary-foreground dark:checked:bg-secondary checked:text-primary checked:border-primary\"\n ],\n data: {\n column_key: col[:key].to_s,\n action: \"change->ruby-ui--data-table-column-visibility#toggle\"\n }\n )\n span { plain col[:label] }\n end\n end\n end\n end\n end\n end\n\n private\n\n def default_attrs\n {\n class: \"relative\",\n data: {controller: \"ruby-ui--data-table-column-visibility\"}\n }\n end\n end\nend\n" }, { "path": "data_table_column_visibility_controller.js", - "content": "// app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js\nimport { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n toggle(event) {\n const key = event.target.dataset.columnKey;\n const visible = event.target.checked;\n const root = this.element.closest('[data-controller~=\"ruby-ui--data-table\"]');\n if (!root) return;\n root\n .querySelectorAll(`[data-column=\"${key}\"]`)\n .forEach((el) => el.classList.toggle(\"hidden\", !visible));\n }\n}\n" + "content": "// app/javascript/controllers/ruby_ui/data_table_column_visibility_controller.js\nimport { Controller } from \"@hotwired/stimulus\";\n\nexport default class extends Controller {\n connect() {\n this.element\n .querySelectorAll(\"input[type=checkbox][data-column-key]\")\n .forEach((checkbox) =>\n this._apply(checkbox.dataset.columnKey, checkbox.checked)\n );\n }\n\n toggle(event) {\n this._apply(event.target.dataset.columnKey, event.target.checked);\n }\n\n _apply(key, visible) {\n const root = this.element.closest('[data-controller~=\"ruby-ui--data-table\"]');\n if (!root) return;\n root\n .querySelectorAll(`[data-column=\"${key}\"]`)\n .forEach((el) => el.classList.toggle(\"hidden\", !visible));\n }\n}\n" }, { "path": "data_table_controller.js",