loco_motion-rails 0.0.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +62 -14
  3. data/app/components/daisy/actions/button_component.html.haml +2 -2
  4. data/app/components/daisy/actions/button_component.rb +98 -59
  5. data/app/components/daisy/actions/dropdown_component.html.haml +1 -2
  6. data/app/components/daisy/actions/dropdown_component.rb +7 -10
  7. data/app/components/daisy/actions/modal_component.html.haml +10 -8
  8. data/app/components/daisy/actions/modal_component.rb +6 -6
  9. data/app/components/daisy/actions/swap_component.rb +13 -9
  10. data/app/components/daisy/actions/theme_controller.js +113 -0
  11. data/app/components/daisy/actions/theme_controller_component.rb +58 -17
  12. data/app/components/daisy/actions/theme_preview_component.html.haml +5 -0
  13. data/app/components/daisy/actions/theme_preview_component.rb +68 -0
  14. data/app/components/daisy/data_display/accordion_component.html.haml +0 -1
  15. data/app/components/daisy/data_display/accordion_component.rb +10 -3
  16. data/app/components/daisy/data_display/avatar_component.html.haml +1 -1
  17. data/app/components/daisy/data_display/avatar_component.rb +17 -7
  18. data/app/components/daisy/data_display/badge_component.rb +122 -4
  19. data/app/components/daisy/data_display/card_component.html.haml +1 -1
  20. data/app/components/daisy/data_display/card_component.rb +20 -6
  21. data/app/components/daisy/data_display/chat_component.rb +2 -2
  22. data/app/components/daisy/data_display/collapse_component.rb +9 -5
  23. data/app/components/daisy/data_display/countdown_component.rb +15 -5
  24. data/app/components/daisy/data_display/figure_component.rb +8 -3
  25. data/app/components/daisy/data_display/kbd_component.rb +13 -4
  26. data/app/components/daisy/data_display/list_component.html.haml +5 -0
  27. data/app/components/daisy/data_display/list_component.rb +82 -0
  28. data/app/components/daisy/data_display/list_item_component.rb +39 -0
  29. data/app/components/daisy/data_display/stat_component.html.haml +5 -6
  30. data/app/components/daisy/data_display/stat_component.rb +21 -8
  31. data/app/components/daisy/data_display/status_component.rb +47 -0
  32. data/app/components/daisy/data_display/timeline_component.rb +1 -1
  33. data/app/components/daisy/data_input/cally_component.html.haml +14 -0
  34. data/app/components/daisy/data_input/cally_component.rb +182 -0
  35. data/app/components/daisy/data_input/cally_input_component.html.haml +5 -0
  36. data/app/components/daisy/data_input/cally_input_component.rb +165 -0
  37. data/app/components/daisy/data_input/cally_input_controller.js +235 -0
  38. data/app/components/daisy/data_input/checkbox_component.html.haml +20 -0
  39. data/app/components/daisy/data_input/checkbox_component.rb +106 -0
  40. data/app/components/daisy/data_input/fieldset_component.html.haml +8 -0
  41. data/app/components/daisy/data_input/fieldset_component.rb +57 -0
  42. data/app/components/daisy/data_input/file_input_component.rb +98 -0
  43. data/app/components/daisy/data_input/filter_component.html.haml +3 -0
  44. data/app/components/daisy/data_input/filter_component.rb +221 -0
  45. data/app/components/daisy/data_input/label_component.rb +84 -0
  46. data/app/components/daisy/data_input/radio_button_component.rb +87 -0
  47. data/app/components/daisy/data_input/range_component.rb +95 -0
  48. data/app/components/daisy/data_input/rating_component.html.haml +11 -0
  49. data/app/components/daisy/data_input/rating_component.rb +139 -0
  50. data/app/components/daisy/data_input/select_component.html.haml +27 -0
  51. data/app/components/daisy/data_input/select_component.rb +320 -0
  52. data/app/components/daisy/data_input/text_area_component.rb +127 -0
  53. data/app/components/daisy/data_input/text_input_component.html.haml +27 -0
  54. data/app/components/daisy/data_input/text_input_component.rb +142 -0
  55. data/app/components/daisy/data_input/toggle_component.rb +48 -0
  56. data/app/components/daisy/feedback/alert_component.html.haml +1 -1
  57. data/app/components/daisy/feedback/alert_component.rb +86 -2
  58. data/app/components/daisy/feedback/loading_component.rb +10 -3
  59. data/app/components/daisy/feedback/skeleton_component.rb +1 -1
  60. data/app/components/daisy/layout/divider_component.rb +4 -2
  61. data/app/components/daisy/layout/drawer_component.html.haml +0 -1
  62. data/app/components/daisy/layout/footer_component.rb +6 -6
  63. data/app/components/daisy/mockup/device_component.rb +15 -18
  64. data/app/components/daisy/navigation/breadcrumbs_component.html.haml +0 -1
  65. data/app/components/daisy/navigation/breadcrumbs_component.rb +84 -9
  66. data/app/components/daisy/navigation/dock_component.rb +146 -0
  67. data/app/components/daisy/navigation/link_component.rb +18 -9
  68. data/app/components/daisy/navigation/menu_component.rb +15 -9
  69. data/app/components/daisy/navigation/navbar_component.html.haml +1 -1
  70. data/app/components/daisy/navigation/navbar_component.rb +2 -13
  71. data/app/components/daisy/navigation/steps_component.rb +6 -6
  72. data/app/components/daisy/navigation/tabs_component.html.haml +0 -1
  73. data/app/components/daisy/navigation/tabs_component.rb +26 -16
  74. data/app/components/hero/icon_component.rb +15 -5
  75. data/app/helpers/daisy/form_builder_helper.rb +186 -0
  76. data/app/views/examples/daisy/data_input/filters.html.haml +62 -0
  77. data/lib/daisy.rb +5 -0
  78. data/lib/hero.rb +1 -1
  79. data/lib/loco_motion/base_component.rb +53 -3
  80. data/lib/loco_motion/component_config.rb +1 -0
  81. data/lib/loco_motion/concerns/iconable_component.rb +134 -0
  82. data/lib/loco_motion/concerns/labelable_component.rb +142 -0
  83. data/lib/loco_motion/concerns/linkable_component.rb +40 -0
  84. data/lib/loco_motion/concerns/tippable_component.rb +25 -10
  85. data/lib/loco_motion/engine.rb +6 -0
  86. data/lib/loco_motion/helpers.rb +38 -17
  87. data/lib/loco_motion/patches/view_component/slot_loco_parent_patch.rb +37 -0
  88. data/lib/loco_motion/patches/view_component/slotable_default_patch.rb +21 -0
  89. data/lib/loco_motion/version.rb +1 -1
  90. data/lib/loco_motion.rb +12 -2
  91. metadata +93 -21
  92. data/app/components/daisy/actions/theme_controller_component.html.haml +0 -5
  93. data/app/components/daisy/layout/artboard_component.rb +0 -59
  94. data/app/components/daisy/navigation/bottom_nav_component.rb +0 -138
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d4d1891389f5b0a860f930a6d4e6dbb9053b6a77e349cd0f43b9de22740482b
4
- data.tar.gz: 2f99a232731636bfaeca166092c0fb4ca51ddae6300e420951d0c0791997e1d7
3
+ metadata.gz: 687d91be39ee325ca12d4244a2f3f87d8fc4578b0b6c00df334851c453c6de78
4
+ data.tar.gz: ba936057cb428d3173bdade09ce87c168958e1d3ad8b894ed6114462e907e2fc
5
5
  SHA512:
6
- metadata.gz: ad963fe072e997ad83879704d8a5d9285f2e964371ee9c7418dfe7377db7950b09f43e3ff8555fad25aee3d141b7b6927ba5e70f965684d749057aaa1d6223c8
7
- data.tar.gz: 367ecb0bf6b3b9d3ff77e6f596b12322fe1b1026bcecc619032c70e59ed94d344f3b18907e8dc8caf63b4d95343e351a808254b50da0db14c8a98b8282cb5a18
6
+ metadata.gz: 01d611aeba154bef36533cc860774e0c640e6e6e9417de8c3f3e060be59b4c1b33071a205b5321b6b99ec5a59814fbcb6ca230757a1d1d10b3bbdfcf1ac8d27f
7
+ data.tar.gz: c8e51c9a451c0199286b1b631da4e126054375113230bab242aad7c9c8387fdadc5244b80654abf0f11eb542615fef90087e522f7dddff01f7f200d3572dc91a
data/README.md CHANGED
@@ -6,19 +6,45 @@ ViewComponent, TailwindCSS, DaisyUI and more!
6
6
 
7
7
  <img src="//loco-motion-docs.profoundry.us/images/loco-chats.png" width="500px" style="border: 1px solid #bbb; padding: 2px; border-radius: 10px;">
8
8
 
9
- _**DISCLAIMER**_
9
+ <!-- omit from toc -->
10
+ ## DISCLAIMER / CURRENT STATUS
10
11
 
11
12
  This project is in active development and many changes occur with every release!
12
- In particular, new Daisy components are being added frequently and older
13
- components are being updated with new features meaning the APIs are very likely
14
- to change!
13
+
14
+ We've added a very basic / untested version of all DaisyUI 4 components. While
15
+ we originally intended to take some time to flesh out and attempt to use these
16
+ components, with the recent release of Tailwind 4 and DaisyUI 5, we feel our
17
+ time is best spent updating all of the components and dependencies for these
18
+ new releases.
19
+
20
+ This means that we will **NOT** be making any bug fixes to the current branch
21
+ (0.4.0), and will instead include any bug fixes / improvements into the 0.5.0
22
+ branch which will also upgrade to Tailwind 4 and DaisyUI 5.
23
+
24
+ - Current Release **(0.4.0)** - Works with DaisyUI 4 and Tailwind 3
25
+ - Next Release **(0.5.0)** - Will work with DaisyUI 5 and Tailwind 4
26
+
27
+ <!-- omit from toc -->
28
+ ## Additional Notes
29
+
30
+ ### DataInput Components
31
+
32
+ Many of the DataInput elements (file input, text input, select dropdown, etc)
33
+ were built rather hastily so that we would have a base version to start from.
34
+
35
+ However, the new DaisyUI 5 components are implemented in a much cleaner way and
36
+ we didn't want to invest too much time building these out and making them more
37
+ ideal since we're about to change them.
38
+
39
+ ### Hosting / Sites
15
40
 
16
41
  We expect to settle on and purchase a real domain name in the near future, but
17
42
  for the time being, the latest documentation is available at the links below.
18
43
 
19
- - [Docs / Demo (Latest Release)][1]
20
- - [API Docs (Latest Release)][2]
21
- - [Docs / Demo (Main Branch / Staging)][3]
44
+ - [Latest Release][1]
45
+ - [Main / Staging][3]
46
+
47
+ ### Getting Help
22
48
 
23
49
  Please reach out by opening an
24
50
  [Issue](https://github.com/profoundry-us/loco_motion/issues) if you've found a
@@ -47,6 +73,8 @@ your solution is aligned with our goals.
47
73
  - [Install](#install)
48
74
  - [Using Components](#using-components)
49
75
  - [Developing](#developing)
76
+ - [Contributing](#contributing)
77
+ - [Releasing](#releasing)
50
78
  - [Tooling](#tooling)
51
79
  - [TODO / Next Steps](#todo--next-steps)
52
80
 
@@ -731,7 +759,7 @@ gem "loco_motion", github: "profoundry-us/loco_motion", branch: "main", require:
731
759
 
732
760
  # or
733
761
 
734
- gem "loco_motion-rails", "0.0.7", require: "loco_motion"
762
+ gem "loco_motion-rails", "0.4.0", require: "loco_motion"
735
763
  ```
736
764
 
737
765
  Next add the following lines to the `contents` section of your
@@ -856,6 +884,20 @@ See the `Makefile` for all available commands.
856
884
  > make demo-restart
857
885
  > ```
858
886
 
887
+ ### Contributing
888
+
889
+ If you're interested in contributing to LocoMotion, please check out our
890
+ [CONTRIBUTING guide](docs/dev_guides/CONTRIBUTING.md) which provides detailed
891
+ information about the contribution process, code standards, documentation
892
+ requirements, and testing procedures.
893
+
894
+ ### Releasing
895
+
896
+ For core team members who need to release new versions of LocoMotion, please
897
+ refer to our [RELEASING guide](docs/dev_guides/RELEASING.md) for step-by-step
898
+ instructions on version updates, building, testing, and publishing both the Ruby
899
+ gem and NPM package.
900
+
859
901
  ### Tooling
860
902
 
861
903
  For VSCode, you may want to add the following to your settings to get
@@ -919,9 +961,9 @@ the GitHub Discussions feature and let us know!
919
961
  - [x] Basic versions of DaisyUI Data Display
920
962
  - [x] Basic versions of DaisyUI Navigation
921
963
  - [x] Basic versions of DaisyUI Feedback
922
- - [ ] Basic versions of DaisyUI Data Input
923
- - [ ] Basic versions of DaisyUI Layout
924
- - [ ] Basic versions of DaisyUI Mockup
964
+ - [x] Basic versions of DaisyUI Data Input
965
+ - [x] Basic versions of DaisyUI Layout
966
+ - [x] Basic versions of DaisyUI Mockup
925
967
  - [x] ~~Get YARD docs rendering with (better) Markdown~~ _**Working for now**_
926
968
  - [x] Extract relevant pieces into a yard-loco_motion plugin
927
969
  - [x] Publish Gem
@@ -932,9 +974,9 @@ the GitHub Discussions feature and let us know!
932
974
  - [ ] Choose, recommend, and document a pagination gem
933
975
  - [ ] Discuss caching techniques / setup
934
976
  - [x] Create / publish a staging version of the demo site ([Demo Staging][2])
935
- - [ ] Create / publish a staging version of the docs site
936
- - [ ] Create / publish a production version of the demo site
937
- - [ ] Create / publish a production version of the docs site
977
+ - [x] Create / publish a staging version of the docs site
978
+ - [x] Create / publish a production version of the demo site
979
+ - [x] Create / publish a production version of the docs site
938
980
  - [x] Update demo site to allow for a different docs site using ENV var
939
981
  - [x] Update README to suggest Playwright
940
982
  - [ ] Build some have docs / guides / examples for using playwright-ruby-client
@@ -946,6 +988,12 @@ the GitHub Discussions feature and let us know!
946
988
  - [ ] See if we can update the Join component to auto-add the `join-item` CSS
947
989
  under certain conditions
948
990
  - [ ] Add title and description content_for blocks to all examples for SEO purposes
991
+ - [ ] Update to Tailwind 4 and DaisyUI 5
992
+ - [ ] Rename the `Dockerfile` to `Dockerfile.loco` to be more concise
993
+ - [x] See if we can remove all of the `set_loco_parent` calls in favor of using
994
+ the `lib/loco_motion/patches/view_component/slot_loco_parent_patch.rb`
995
+ - [ ] Make the tooltips documentation button a component and use it for the
996
+ Labelable concern docs too
949
997
 
950
998
  [1]: https://loco-motion.profoundry.us/
951
999
  [2]: https://loco-motion-demo-staging.profoundry.us/
@@ -2,6 +2,6 @@
2
2
  - if content?
3
3
  = content
4
4
  - else
5
- = heroicon_tag(@left_icon, **left_icon_html) if @left_icon
5
+ = render_left_icon
6
6
  = @simple_title if @simple_title
7
- = heroicon_tag(@right_icon, **right_icon_html) if @right_icon
7
+ = render_right_icon
@@ -3,7 +3,7 @@
3
3
  # that are styled to look like a clickable element.
4
4
  #
5
5
  # Note that we do **not** use component parts for the icons since we're calling
6
- # `heroicon_tag` within the component. But we **do** provide custom CSS & HTML
6
+ # `heroicon` within the component. But we **do** provide custom CSS & HTML
7
7
  # options to allow overriding / customization.
8
8
  #
9
9
  # Includes the {LocoMotion::Concerns::TippableComponent} module to enable easy
@@ -19,8 +19,88 @@
19
19
  #
20
20
  # = daisy_button(title: "Button with Two Icons", left_icon: "heart", right_icon: "plus")
21
21
  #
22
+ # @loco_example Button Group
23
+ # = daisy_button_group do
24
+ # = daisy_button do
25
+ # Button 1
26
+ # = daisy_button do
27
+ # Button 2
28
+ #
29
+ # @loco_example Default Button
30
+ # = daisy_button { "Default Button" }
31
+ #
32
+ # @loco_example Primary Button
33
+ # = daisy_button(css: "btn-primary") { "Primary Button" }
34
+ #
35
+ # @loco_example Secondary Button
36
+ # = daisy_button(css: "btn-secondary") { "Secondary Button" }
37
+ #
38
+ # @loco_example Accent Button
39
+ # = daisy_button(css: "btn-accent") { "Accent Button" }
40
+ #
41
+ # @loco_example Ghost Button
42
+ # = daisy_button(css: "btn-ghost") { "Ghost Button" }
43
+ #
44
+ # @loco_example Link Button
45
+ # = daisy_button(css: "btn-link") { "Link Button" }
46
+ #
47
+ # @loco_example Info Button
48
+ # = daisy_button(css: "btn-info") { "Info Button" }
49
+ #
50
+ # @loco_example Success Button
51
+ # = daisy_button(css: "btn-success") { "Success Button" }
52
+ #
53
+ # @loco_example Warning Button
54
+ # = daisy_button(css: "btn-warning") { "Warning Button" }
55
+ #
56
+ # @loco_example Error Button
57
+ # = daisy_button(css: "btn-error") { "Error Button" }
58
+ #
59
+ # @loco_example Outline Primary Button
60
+ # = daisy_button(css: "btn-primary btn-outline") { "Outline Primary" }
61
+ #
62
+ # @loco_example Outline Success Button
63
+ # = daisy_button(css: "btn-success btn-outline") { "Outline Success" }
64
+ #
65
+ # @loco_example Outline Warning Button
66
+ # = daisy_button(css: "btn-warning btn-outline") { "Outline Warning" }
67
+ #
68
+ # @loco_example Outline Error Button
69
+ # = daisy_button(css: "btn-error btn-outline") { "Outline Error" }
70
+ #
71
+ # @loco_example Soft Primary Button
72
+ # = daisy_button(css: "btn-primary btn-soft") { "Soft Primary" }
73
+ #
74
+ # @loco_example Soft Success Button
75
+ # = daisy_button(css: "btn-success btn-soft") { "Soft Success" }
76
+ #
77
+ # @loco_example Soft Warning Button
78
+ # = daisy_button(css: "btn-warning btn-soft") { "Soft Warning" }
79
+ #
80
+ # @loco_example Soft Error Button
81
+ # = daisy_button(css: "btn-error btn-soft") { "Soft Error" }
82
+ #
83
+ # @loco_example Dash Primary Button
84
+ # = daisy_button(css: "btn-primary btn-dash") { "Dash Primary" }
85
+ #
86
+ # @loco_example Dash Success Button
87
+ # = daisy_button(css: "btn-success btn-dash") { "Dash Success" }
88
+ #
89
+ # @loco_example Dash Warning Button
90
+ # = daisy_button(css: "btn-warning btn-dash") { "Dash Warning" }
91
+ #
92
+ # @loco_example Dash Error Button
93
+ # = daisy_button(css: "btn-error btn-dash") { "Dash Error" }
94
+ #
95
+ # @loco_example Wide Button
96
+ # = daisy_button(css: "btn-wide") { "Wide Button" }
97
+ #
22
98
  class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
23
- prepend LocoMotion::Concerns::TippableComponent
99
+ include LocoMotion::Concerns::TippableComponent
100
+ include LocoMotion::Concerns::LinkableComponent
101
+ include LocoMotion::Concerns::IconableComponent
102
+
103
+ define_parts :label
24
104
 
25
105
  #
26
106
  # Instantiate a new Button component.
@@ -29,20 +109,11 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
29
109
  # of title, left icon, or right icon is provided. Will be considered the
30
110
  # `action` parameter if **both** the title and a block are provided.
31
111
  #
32
- # @param action [String] The Stimulus action that should fire when the button
33
- # is clicked.
34
- #
35
112
  # @param kws [Hash] The keyword arguments for the component.
36
113
  #
37
114
  # @option kws title [String] The title of the button. You can also
38
115
  # pass the title, icons, or any other HTML content as a block.
39
116
  #
40
- # @option kws action [String] The Stimulus action that should fire
41
- # when the button is clicked.
42
- #
43
- # > **Note:** _You should use either the `action` or the `href` option, but
44
- # not both._
45
- #
46
117
  # @option kws href [String] A path or URL to which the user will be
47
118
  # directed when the button is clicked. Forces the Button to use an `<a>`
48
119
  # tag.
@@ -74,11 +145,9 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
74
145
  # @option kws right_icon [String] The name of Hero icon to render inside
75
146
  # the button to the right of the text.
76
147
  #
77
- # @option kws right_icon_css [String] The CSS classes to apply to the right
78
- # icon.
148
+ # @option kws right_icon_css [String] Right icon CSS (via IconableComponent).
79
149
  #
80
- # @option kws right_icon_html [Hash] Additional HTML attributes to apply to
81
- # the right icon.
150
+ # @option kws right_icon_html [Hash] Right icon HTML (via IconableComponent).
82
151
  #
83
152
  def initialize(title = nil, action = nil, **kws, &block)
84
153
  super
@@ -92,21 +161,7 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
92
161
 
93
162
  @action = config_option(:action, action)
94
163
 
95
- @href = config_option(:href)
96
- @target = config_option(:target)
97
-
98
- @icon = config_option(:icon)
99
- @icon_css = config_option(:icon_css, "[:where(&)]:size-5")
100
- @icon_html = config_option(:icon_html, {})
101
-
102
- @left_icon = config_option(:left_icon, @icon)
103
- @left_icon_css = config_option(:left_icon_css, @icon_css)
104
- @left_icon_html = config_option(:left_icon_html, @icon_html)
105
-
106
- @right_icon = config_option(:right_icon)
107
- @right_icon_css = config_option(:right_icon_css, @icon_css)
108
- @right_icon_html = config_option(:right_icon_html, @icon_html)
109
-
164
+ # Initialize concerns -- handled by BaseComponent hook
110
165
  default_title = @left_icon || @right_icon ? nil : "Submit"
111
166
  @simple_title = config_option(:title, title || default_title)
112
167
  end
@@ -115,42 +170,26 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
115
170
  # Calls the {setup_component} method before rendering the component.
116
171
  #
117
172
  def before_render
173
+ # Run before the super so LinkableComponent can override our tag name
118
174
  setup_component
175
+
176
+ super
119
177
  end
120
178
 
121
179
  #
122
- # Sets the tagname to `<a>` if an `href` is provided, otherwise sets it to
123
- # `<button>`. Adds the `btn` CSS class to the component. Also adds
124
- # `items-center` and `gap-2` CSS classes if an icon is present.
180
+ # Performs button-specific setup. Adds the `btn` CSS class to the component.
181
+ # Also adds `items-center` and `gap-2` CSS classes if an icon is present.
182
+ # Tag name setup (`<a>` vs `<button>`) and tooltip setup are handled by
183
+ # LinkableComponent and TippableComponent concerns via BaseComponent hooks.
125
184
  #
126
185
  def setup_component
127
- if @href
128
- set_tag_name(:component, :a)
129
- add_html(:component, { href: @href, target: @target })
130
- else
131
- set_tag_name(:component, :button)
132
- end
133
-
134
- add_css(:component, "btn")
186
+ # Ensure tag is button if LinkableComponent didn't set it to <a>
187
+ set_tag_name(:component, :button)
135
188
 
136
- if @icon || @left_icon || @right_icon
137
- add_css(:component, "[:where(&)]:items-center [:where(&)]:gap-2")
138
- end
189
+ # Add the btn class
190
+ add_css(:component, "btn") unless @skip_styling
139
191
 
140
- add_html(:component, { "data-action": @action }) if @action
141
- end
142
-
143
- #
144
- # Returns the HTML attributes for the left icon.
145
- #
146
- def left_icon_html
147
- { class: @left_icon_css }.merge(@left_icon_html)
148
- end
149
-
150
- #
151
- # Returns the HTML attributes for the right icon.
152
- #
153
- def right_icon_html
154
- { class: @right_icon_css }.merge(@right_icon_html)
192
+ # Add data-action if specified
193
+ add_html(:component, { "data-action": @action }) if @action
155
194
  end
156
195
  end
@@ -7,7 +7,6 @@
7
7
  - if items.any?
8
8
  = part(:menu) do
9
9
  - items.each do |item|
10
- = part(:menu_item) do
11
- = item
10
+ = item
12
11
  - else
13
12
  = content
@@ -31,7 +31,7 @@
31
31
  # @loco_example Custom Activator
32
32
  # = daisy_dropdown do |dropdown|
33
33
  # - dropdown.with_activator do
34
- # = heroicon_tag "bars-3", css: "size-6"
34
+ # = heroicon "bars-3", css: "size-6"
35
35
  # - dropdown.with_item do
36
36
  # Menu Item 1
37
37
  # - dropdown.with_item do
@@ -43,26 +43,26 @@
43
43
  # User Settings
44
44
  # - dropdown.with_item do
45
45
  # .flex.gap-2.items-center
46
- # = heroicon_tag "user-circle"
46
+ # = heroicon "user-circle"
47
47
  # Profile
48
48
  # - dropdown.with_item do
49
49
  # .flex.gap-2.items-center
50
- # = heroicon_tag "cog-6-tooth"
50
+ # = heroicon "cog-6-tooth"
51
51
  # Settings
52
52
  # - dropdown.with_item do
53
53
  # .flex.gap-2.items-center.text-error
54
- # = heroicon_tag "arrow-right-on-rectangle"
54
+ # = heroicon "arrow-right-on-rectangle"
55
55
  # Logout
56
56
  #
57
57
  class Daisy::Actions::DropdownComponent < LocoMotion::BaseComponent
58
58
 
59
59
  include ViewComponent::SlotableDefault
60
60
 
61
- define_parts :menu, :menu_item
61
+ define_parts :menu
62
62
 
63
63
  renders_one :activator, LocoMotion::BasicComponent.build(html: { role: "button", tabindex: 0 })
64
64
  renders_one :button, Daisy::Actions::ButtonComponent
65
- renders_many :items
65
+ renders_many :items, LocoMotion::BasicComponent.build(tag_name: :li, css: "menu-item")
66
66
 
67
67
  #
68
68
  # Creates a new instance of the DropdownComponent.
@@ -102,10 +102,7 @@ class Daisy::Actions::DropdownComponent < LocoMotion::BaseComponent
102
102
  def setup_menu
103
103
  # Setup menu itself
104
104
  set_tag_name(:menu, :ul)
105
- add_css(:menu, "dropdown-content menu bg-base-100 rounded-box shadow w-52 p-2 z-[1]")
106
-
107
- # Setup menu items
108
- set_tag_name(:menu_item, :li)
105
+ add_css(:menu, "dropdown-content where:menu where:bg-base-100 where:rounded-box where:shadow where:w-52 where:p-2 where:z-[1]")
109
106
  end
110
107
 
111
108
  #
@@ -11,7 +11,7 @@
11
11
  - if close_icon?
12
12
  = close_icon
13
13
  - else
14
- = heroicon_tag "x-mark"
14
+ = heroicon "x-mark"
15
15
 
16
16
  - if title?
17
17
  = title
@@ -21,12 +21,14 @@
21
21
 
22
22
  = content
23
23
 
24
- = part(:actions) do
25
- = part(:start_actions) do
26
- - if start_actions?
27
- = start_actions
28
- = part(:end_actions) do
29
- - if end_actions?
30
- = end_actions
24
+ - if start_actions? || end_actions?
25
+ = part(:actions) do
26
+ = part(:start_actions) do
27
+ - if start_actions?
28
+ = start_actions
29
+ = part(:end_actions) do
30
+ - if end_actions?
31
+ = end_actions
32
+
31
33
  = part(:backdrop) do
32
34
  %button close
@@ -7,7 +7,6 @@
7
7
  # (`showModal()` and `close()`). This provides better accessibility and keyboard
8
8
  # navigation compared to div-based modals.
9
9
  #
10
- # @part dialog The main `<dialog>` container that wraps the modal content.
11
10
  # @part box The container for the modal content, providing padding and layout.
12
11
  # @part close_icon_wrapper The container for the close icon, positioned in the
13
12
  # top-right corner.
@@ -55,7 +54,7 @@
55
54
  # = daisy_modal(title: "User Details") do |modal|
56
55
  # - modal.with_activator do
57
56
  # .flex.items-center.gap-2.cursor-pointer
58
- # = heroicon_tag "user-circle"
57
+ # = heroicon "user-circle"
59
58
  # %span View Details
60
59
  #
61
60
  # %dl.space-y-2
@@ -71,7 +70,7 @@
71
70
  class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
72
71
  set_component_name :modal
73
72
 
74
- define_parts :dialog, :box, :actions, :close_icon_wrapper, :close_icon,
73
+ define_parts :box, :actions, :close_icon_wrapper, :close_icon,
75
74
  :backdrop, :title, :start_actions, :end_actions
76
75
 
77
76
  renders_one :activator, LocoMotion::BasicComponent.build(html: { role: "button", tabindex: 0 })
@@ -165,15 +164,16 @@ class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
165
164
  add_html(:close_icon_wrapper, { method: "dialog" })
166
165
 
167
166
  set_tag_name(:close_icon, :button)
168
- add_css(:close_icon, "absolute top-2 right-2 p-1 btn btn-circle btn-ghost btn-xs")
167
+ add_css(:close_icon, "where:absolute where:top-2 where:right-2 where:p-1 where:btn where:btn-circle where:btn-ghost where:btn-xs")
169
168
  end
170
169
 
171
170
  def setup_title
172
- add_css(:title, "mb-2 text-xl font-bold")
171
+ set_tag_name(:title, 'h4')
172
+ add_css(:title, "where:mb-2 where:text-xl where:font-bold")
173
173
  end
174
174
 
175
175
  def setup_actions
176
- add_css(:actions, "mt-2 flex flex-row items-center justify-between")
176
+ add_css(:actions, "where:mt-2 where:flex where:flex-row where:items-center where:justify-between")
177
177
  end
178
178
 
179
179
  # Provide a default button if no button is supplied.
@@ -32,9 +32,9 @@
32
32
  # @loco_example Icon Swap with Tooltip
33
33
  # = daisy_swap(tip: "Toggle Theme") do |swap|
34
34
  # - swap.with_on do
35
- # = heroicon_tag "sun", css: "size-6"
35
+ # = heroicon "sun", css: "size-6"
36
36
  # - swap.with_off do
37
- # = heroicon_tag "moon", css: "size-6"
37
+ # = heroicon "moon", css: "size-6"
38
38
  #
39
39
  # @loco_example Complex Content with Animation
40
40
  # = daisy_swap(css: "swap-flip") do |swap|
@@ -51,19 +51,19 @@
51
51
  # = daisy_swap(css: "swap-flip", tip: "Task Status") do |swap|
52
52
  # - swap.with_on do
53
53
  # .text-success
54
- # = heroicon_tag "check-circle"
54
+ # = heroicon "check-circle"
55
55
  # %span Complete
56
56
  # - swap.with_off do
57
57
  # .text-error
58
- # = heroicon_tag "x-circle"
58
+ # = heroicon "x-circle"
59
59
  # %span Failed
60
60
  # - swap.with_indeterminate do
61
61
  # .text-warning
62
- # = heroicon_tag "clock"
62
+ # = heroicon "clock"
63
63
  # %span Processing
64
64
  #
65
65
  class Daisy::Actions::SwapComponent < LocoMotion::BaseComponent
66
- prepend LocoMotion::Concerns::TippableComponent
66
+ include LocoMotion::Concerns::TippableComponent
67
67
 
68
68
  class SwapOn < LocoMotion::BasicComponent
69
69
  def before_render
@@ -121,6 +121,9 @@ class Daisy::Actions::SwapComponent < LocoMotion::BaseComponent
121
121
  # @option kws indeterminate [Boolean] If true, starts the swap in an indeterminate
122
122
  # state. Requires the indeterminate slot to be meaningful.
123
123
  #
124
+ # @option kws tip [String] The tooltip text to display when hovering over
125
+ # the component.
126
+ #
124
127
  def initialize(on = nil, off = nil, checked = nil, **kws, &block)
125
128
  super
126
129
 
@@ -133,9 +136,10 @@ class Daisy::Actions::SwapComponent < LocoMotion::BaseComponent
133
136
  # Sets up the component with various CSS classes and HTML attributes.
134
137
  #
135
138
  def before_render
136
- setup_component
137
- setup_checkbox
138
- setup_on_off
139
+ setup_component # Set tag, base CSS
140
+ setup_checkbox # Setup the hidden checkbox part
141
+ setup_on_off # Setup the on/off part CSS
142
+ super # Run TippableComponent hook
139
143
  end
140
144
 
141
145
  private
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Theme Controller
3
+ *
4
+ * A Stimulus controller that manages theme selection and persistence.
5
+ * It handles theme switching, localStorage persistence, and synchronization
6
+ * across multiple theme selectors on the same page.
7
+ */
8
+ import { Controller } from "@hotwired/stimulus"
9
+
10
+ export default class extends Controller {
11
+ /**
12
+ * Called when the controller is connected to the DOM.
13
+ * Sets the initial theme input state and sets up event listeners.
14
+ */
15
+ connect() {
16
+ this.setInput()
17
+
18
+ // Setup a custom listener to watch for changes on the page in case the
19
+ // page has multiple theme selectors
20
+ this.storageChangeListener = this.storageChanged.bind(this)
21
+
22
+ window.addEventListener('localstorage-update', this.storageChangeListener)
23
+ }
24
+
25
+ /**
26
+ * Called when the controller is disconnected from the DOM.
27
+ * Removes event listeners to prevent memory leaks.
28
+ */
29
+ disconnect() {
30
+ window.removeEventListener('localstorage-update', this.storageChangeListener)
31
+ }
32
+
33
+ /**
34
+ * Sets the appropriate radio input as checked based on the current theme.
35
+ * This ensures the UI reflects the active theme.
36
+ */
37
+ setInput() {
38
+ const theme = this.getCurrentTheme()
39
+ const input = this.element.querySelector(`input[value='${theme}']`);
40
+
41
+ if (input) {
42
+ input.checked = true;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Clears the user's theme preference from localStorage.
48
+ * Removes the saved theme and dispatches an event to notify other controllers.
49
+ *
50
+ * @param {Event} event - The triggering click event
51
+ */
52
+ clearTheme(event) {
53
+ // If we are passed a themeName parameter, clear all inputs with that theme
54
+ if (event && event.params && event.params.themeName) {
55
+ const inputs = document.querySelectorAll(`input[name='${event.params.themeName}']`)
56
+
57
+ if (inputs) {
58
+ inputs.forEach(input => {
59
+ input.checked = false
60
+ })
61
+ }
62
+ }
63
+
64
+ // Remove the savedTheme from local storage
65
+ localStorage.removeItem("savedTheme")
66
+
67
+ // Fire off an update
68
+ const updateEvent = new CustomEvent('localstorage-update', { detail: { key: 'savedTheme', newValue: null } })
69
+ window.dispatchEvent(updateEvent)
70
+ }
71
+
72
+ /**
73
+ * Changes the theme based on user selection.
74
+ * Updates localStorage and dispatches a custom event to notify other controllers.
75
+ *
76
+ * @param {Event} event - The triggering click event
77
+ */
78
+ setTheme(event) {
79
+ const input = event.currentTarget.querySelector('input')
80
+
81
+ if (input) {
82
+ localStorage.setItem("savedTheme", input.value)
83
+
84
+ const updateEvent = new CustomEvent('localstorage-update', { detail: { key: 'savedTheme', newValue: input.value } })
85
+ window.dispatchEvent(updateEvent)
86
+ }
87
+
88
+ event.preventDefault();
89
+ }
90
+
91
+ /**
92
+ * Retrieves the current theme from localStorage.
93
+ *
94
+ * @returns {string} The current theme name
95
+ */
96
+ getCurrentTheme() {
97
+ const savedTheme = localStorage.getItem('savedTheme')
98
+
99
+ if (savedTheme) {
100
+ return savedTheme
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Event handler for 'localstorage-update' events.
106
+ * Updates the input state when theme changes in another controller.
107
+ *
108
+ * @param {CustomEvent} event - The storage changed event
109
+ */
110
+ storageChanged(event) {
111
+ this.setInput()
112
+ }
113
+ }