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
@@ -1,31 +1,26 @@
1
1
  #
2
- # The Theme Controller component provides a simple interface for switching
3
- # between different DaisyUI themes. It renders a set of radio buttons that
4
- # allow users to select from a predefined list of themes.
5
- #
6
- # The component is designed to work with DaisyUI's theme system and
7
- # automatically updates the `data-theme` attribute on the HTML element when
8
- # a theme is selected.
2
+ # The ThemeComponent serves as a foundation for building a full Theme Switcher.
3
+ # It provides the building blocks that you will use such as the Theme Preview,
4
+ # Theme Radio, and Stimulus ThemeController.
9
5
  #
10
6
  # @loco_example Basic Usage
11
- # = daisy_theme_controller
12
- #
13
- # @loco_example Custom Theme List
14
- # = daisy_theme_controller(themes: ["light", "dark", "cyberpunk"])
15
- #
16
- # @loco_example With Custom Styling
17
- # = daisy_theme_controller(css: "gap-6 p-4 bg-base-200 rounded-lg")
7
+ # = daisy_theme_controller do |tc|
8
+ # - tc.themes.each do |theme|
9
+ # = tc.build_theme_preview(theme)
10
+ # = tc.build_radio_input(theme)
18
11
  #
19
12
  class Daisy::Actions::ThemeControllerComponent < LocoMotion::BaseComponent
20
13
  # Default list of themes to display in the controller
21
14
  SOME_THEMES = ["light", "dark", "synthwave", "retro", "cyberpunk", "wireframe"].freeze
22
15
 
16
+ attr_reader :themes
17
+
23
18
  #
24
19
  # Creates a new instance of the ThemeControllerComponent.
25
20
  #
26
21
  # @param kws [Hash] The keyword arguments for the component.
27
22
  #
28
- # @option kws themes [Array<String>] List of DaisyUI theme names to include
23
+ # @option kws [Array<String>] :themes List of DaisyUI theme names to include
29
24
  # in the controller. Defaults to {SOME_THEMES}.
30
25
  #
31
26
  def initialize(**kws, &block)
@@ -35,9 +30,55 @@ class Daisy::Actions::ThemeControllerComponent < LocoMotion::BaseComponent
35
30
  end
36
31
 
37
32
  #
38
- # Sets up the component's CSS classes for proper layout and spacing.
33
+ # Sets up the component with theme Stimulus controller.
39
34
  #
40
35
  def before_render
41
- add_css(:component, "flex flex-col lg:flex-row gap-4 items-center")
36
+ add_stimulus_controller(:component, "loco-theme")
37
+ end
38
+
39
+ #
40
+ # Renders the component and its content.
41
+ #
42
+ def call
43
+ part(:component) { content }
44
+ end
45
+
46
+ #
47
+ # Builder method to create a radio input for use in selecting themes.
48
+ #
49
+ # @param theme [String] The name of the theme that the input controls.
50
+ # @param options [Hash] Additional options to pass to the component.
51
+ #
52
+ # @return [Daisy::DataInput::RadioButtonComponent] A new radio button
53
+ # component instance.
54
+ #
55
+ def build_radio_input(theme, **options)
56
+ options[:css] = (options[:css] || "").concat(" theme-controller")
57
+ default_options = { name: "theme", id: "theme-#{theme}", value: theme }
58
+
59
+ render Daisy::DataInput::RadioButtonComponent.new(**default_options.deep_merge(options))
60
+ end
61
+
62
+ #
63
+ # Builder method to create a theme preview showing the theme's colors in a 2x2
64
+ # grid.
65
+ #
66
+ # @param theme [String] The theme name to preview.
67
+ #
68
+ # @option options [Integer] :size Size of the preview in Tailwind size units.
69
+ # Defaults to 4 (1rem).
70
+ #
71
+ # @option options [Boolean] :shadow Whether to add a shadow. Defaults to true.
72
+ #
73
+ # @option options [String] :css Additional CSS classes.
74
+ #
75
+ # @return [Daisy::Actions::ThemePreviewComponent] A new theme preview
76
+ # component instance.
77
+ #
78
+ def build_theme_preview(theme, **options)
79
+ render Daisy::Actions::ThemePreviewComponent.new(
80
+ theme: theme,
81
+ **options
82
+ )
42
83
  end
43
84
  end
@@ -0,0 +1,5 @@
1
+ = part(:component) do
2
+ = part(:dot_base)
3
+ = part(:dot_primary)
4
+ = part(:dot_secondary)
5
+ = part(:dot_accent)
@@ -0,0 +1,68 @@
1
+ #
2
+ # The Theme Preview component displays a small preview of a DaisyUI theme's
3
+ # colors. It helps users visualize the theme by showing a 2x2 grid of colored
4
+ # dots representing the base-content, primary, secondary, and accent colors of
5
+ # the theme.
6
+ #
7
+ # @part dot_base The dot showing the base-content color of the theme.
8
+ # @part dot_primary The dot showing the primary color of the theme.
9
+ # @part dot_secondary The dot showing the secondary color of the theme.
10
+ # @part dot_accent The dot showing the accent color of the theme.
11
+ #
12
+ # @loco_example Basic Usage
13
+ # = daisy_theme_preview(theme: "light")
14
+ #
15
+ # @loco_example Custom CSS
16
+ # = daisy_theme_preview(theme: "dark", css: "size-6")
17
+ #
18
+ class Daisy::Actions::ThemePreviewComponent < LocoMotion::BaseComponent
19
+ define_parts :dot_base, :dot_primary, :dot_secondary, :dot_accent
20
+
21
+ #
22
+ # Creates a new instance of the ThemePreviewComponent.
23
+ #
24
+ # @param theme [String] The theme name to preview, can be provided as a
25
+ # positional or keyword argument.
26
+ #
27
+ # @option kws [String] :theme The theme name to preview (if not provided as
28
+ # positional argument).
29
+ #
30
+ # @option kws [String] :css Additional CSS classes to apply to the component.
31
+ #
32
+ def initialize(theme = nil, **kws, &block)
33
+ super
34
+
35
+ @theme = config_option(:theme, theme)
36
+ end
37
+
38
+ #
39
+ # Sets up the component's CSS classes and other attributes before rendering.
40
+ #
41
+ def before_render
42
+ setup_component
43
+ setup_dots
44
+ end
45
+
46
+ #
47
+ # Sets up the component's CSS classes and data attributes.
48
+ #
49
+ def setup_component
50
+ classes = [
51
+ "where:size-4 where:grid where:grid-cols-2 where:place-items-center",
52
+ "where:shrink-0 where:rounded-md where:bg-base-100 where:shadow-sm"
53
+ ].join(" ")
54
+
55
+ add_css(:component, classes)
56
+ add_html(:component, { "data-theme": @theme })
57
+ end
58
+
59
+ #
60
+ # Sets up the CSS classes for the theme color dots.
61
+ #
62
+ def setup_dots
63
+ add_css(:dot_base, "where:bg-base-content where:size-1 where:rounded-full")
64
+ add_css(:dot_primary, "where:bg-primary where:size-1 where:rounded-full")
65
+ add_css(:dot_secondary, "where:bg-secondary where:size-1 where:rounded-full")
66
+ add_css(:dot_accent, "where:bg-accent where:size-1 where:rounded-full")
67
+ end
68
+ end
@@ -1,4 +1,3 @@
1
1
  = part(:component) do
2
2
  - sections.each do |section|
3
- - section.set_loco_parent(component_ref)
4
3
  = section
@@ -35,12 +35,12 @@
35
35
  # - accordion.with_section do |section|
36
36
  # - section.with_title do
37
37
  # .flex.items-center.gap-2
38
- # = heroicon_tag "star"
38
+ # = heroicon "star"
39
39
  # Featured Section
40
40
  # This is the content of the featured section
41
41
  #
42
42
  class Daisy::DataDisplay::AccordionComponent < LocoMotion::BaseComponent
43
- prepend LocoMotion::Concerns::TippableComponent
43
+ include LocoMotion::Concerns::TippableComponent
44
44
 
45
45
  # Renders a single section of the accordion.
46
46
  #
@@ -93,7 +93,7 @@ class Daisy::DataDisplay::AccordionComponent < LocoMotion::BaseComponent
93
93
 
94
94
  def setup_component
95
95
  # Reset the name to the config option or the parent name if available
96
- @name = config_option(:name, loco_parent&.name)
96
+ @name = config_option(:name, loco_parent.name)
97
97
 
98
98
  add_css(:component, "collapse")
99
99
  add_css(:component, "collapse-arrow") if loco_parent.config.modifiers.include?(:arrow)
@@ -151,9 +151,16 @@ class Daisy::DataDisplay::AccordionComponent < LocoMotion::BaseComponent
151
151
  # Use `:arrow` to show arrow indicators, or `:plus` to show plus/minus
152
152
  # indicators.
153
153
  #
154
+ # @option kws tip [String] The tooltip text to display when hovering over
155
+ # the component.
156
+ #
154
157
  def initialize(**kws, &block)
155
158
  super
156
159
 
157
160
  @name = config_option(:name, "accordion-#{SecureRandom.uuid}")
158
161
  end
162
+
163
+ def before_render
164
+ super
165
+ end
159
166
  end
@@ -3,7 +3,7 @@
3
3
  - if @src.present?
4
4
  = part(:img)
5
5
  - elsif @icon.present?
6
- = heroicon_tag(@icon, **rendered_html(:icon))
6
+ = render_icon
7
7
  - else
8
8
  = part(:placeholder) do
9
9
  = content
@@ -28,17 +28,19 @@
28
28
  # JD
29
29
  #
30
30
  # @loco_example With Custom Size
31
- # = daisy_avatar(src: "avatar.jpg", css: "w-16 h-16")
31
+ # = daisy_avatar(src: "avatar.jpg", css: "size-16")
32
32
  #
33
33
  # @loco_example With Tooltip
34
34
  # = daisy_avatar(src: "avatar.jpg", tip: "John Doe")
35
35
  #
36
36
  class Daisy::DataDisplay::AvatarComponent < LocoMotion::BaseComponent
37
- prepend LocoMotion::Concerns::TippableComponent
37
+ include LocoMotion::Concerns::IconableComponent
38
+ include LocoMotion::Concerns::LinkableComponent
39
+ include LocoMotion::Concerns::TippableComponent
38
40
 
39
41
  set_component_name :avatar
40
42
 
41
- define_parts :wrapper, :img, :icon, :placeholder
43
+ define_parts :wrapper, :img, :placeholder
42
44
 
43
45
  # Create a new avatar component.
44
46
  #
@@ -51,15 +53,20 @@ class Daisy::DataDisplay::AvatarComponent < LocoMotion::BaseComponent
51
53
  # provided. If neither src nor icon is provided, placeholder content from
52
54
  # the block will be shown.
53
55
  #
56
+ # @option kws tip [String] The tooltip text to display when hovering over
57
+ # the component.
58
+ #
54
59
  def initialize(**kws, &block)
55
60
  super
56
61
 
57
62
  @src = config_option(:src)
58
- @icon = config_option(:icon)
59
63
  end
60
64
 
61
65
  def before_render
66
+ # Run component setup *before* super to allow BaseComponent hooks to run last
62
67
  setup_component
68
+
69
+ super
63
70
  end
64
71
 
65
72
  private
@@ -69,14 +76,17 @@ class Daisy::DataDisplay::AvatarComponent < LocoMotion::BaseComponent
69
76
 
70
77
  # The where pseudo class reduces the specificity of the CSS selector to 0 so
71
78
  # that other Tailwind classes provided by the user will take presedence.
72
- add_css(:wrapper, "[:where(&)]:w-24 [:where(&)]:rounded-full")
79
+ add_css(:wrapper, "where:w-24 where:rounded-full")
73
80
 
74
81
  if @src.present?
75
82
  set_tag_name(:img, :img)
76
83
  add_html(:img, { src: @src, title: @content })
77
84
  else
78
- add_css(:component, "placeholder")
79
- add_css(:wrapper, "[:where(&)]:bg-neutral [:where(&)]:text-neutral-content")
85
+ add_css(:component, "avatar-placeholder")
86
+ add_css(:wrapper, "where:bg-neutral where:text-neutral-content")
80
87
  end
88
+
89
+ # Concern setup is handled by BaseComponent hook via super in before_render
90
+ # setup_tippable_component
81
91
  end
82
92
  end
@@ -18,15 +18,93 @@
18
18
  # @loco_example With Tooltip
19
19
  # = daisy_badge("Beta", tip: "This feature is in beta testing")
20
20
  #
21
+ # @loco_example With Icons
22
+ # = daisy_badge(title: "New", left_icon: "sparkles")
23
+ # = daisy_badge(title: "Download", right_icon: "arrow-down")
24
+ # = daisy_badge(title: "Star", left_icon: "star", right_icon: "plus")
25
+ #
26
+ # @loco_example With Links
27
+ # = daisy_badge(title: "Documentation", href: "#", css: "badge-primary")
28
+ # = daisy_badge(title: "External", href: "#", target: "_blank", css: "badge-secondary")
29
+ # = daisy_badge(title: "GitHub", href: "#", left_icon: "code-bracket")
30
+ #
21
31
  # @loco_example Using a Block
22
32
  # = daisy_badge do
23
33
  # %span.flex.items-center.gap-1
24
- # = heroicon_tag "star", css: "size-4"
34
+ # = heroicon "star", css: "size-4"
25
35
  # Featured
26
36
  #
37
+ # @loco_example Default Badge
38
+ # = daisy_badge { "Default Badge" }
39
+ #
40
+ # @loco_example Primary Badge
41
+ # = daisy_badge(css: "badge-primary") { "Primary Badge" }
42
+ #
43
+ # @loco_example Secondary Badge
44
+ # = daisy_badge(css: "badge-secondary") { "Secondary Badge" }
45
+ #
46
+ # @loco_example Accent Badge
47
+ # = daisy_badge(css: "badge-accent") { "Accent Badge" }
48
+ #
49
+ # @loco_example Ghost Badge
50
+ # = daisy_badge(css: "badge-ghost") { "Ghost Badge" }
51
+ #
52
+ # @loco_example Info Badge
53
+ # = daisy_badge(css: "badge-info") { "Info Badge" }
54
+ #
55
+ # @loco_example Success Badge
56
+ # = daisy_badge(css: "badge-success") { "Success Badge" }
57
+ #
58
+ # @loco_example Warning Badge
59
+ # = daisy_badge(css: "badge-warning") { "Warning Badge" }
60
+ #
61
+ # @loco_example Error Badge
62
+ # = daisy_badge(css: "badge-error") { "Error Badge" }
63
+ #
64
+ # @loco_example Outline Primary Badge
65
+ # = daisy_badge(css: "badge-primary badge-outline") { "Outline Primary" }
66
+ #
67
+ # @loco_example Outline Success Badge
68
+ # = daisy_badge(css: "badge-success badge-outline") { "Outline Success" }
69
+ #
70
+ # @loco_example Outline Warning Badge
71
+ # = daisy_badge(css: "badge-warning badge-outline") { "Outline Warning" }
72
+ #
73
+ # @loco_example Outline Error Badge
74
+ # = daisy_badge(css: "badge-error badge-outline") { "Outline Error" }
75
+ #
76
+ # @loco_example Soft Primary Badge
77
+ # = daisy_badge(css: "badge-primary badge-soft") { "Soft Primary" }
78
+ #
79
+ # @loco_example Soft Success Badge
80
+ # = daisy_badge(css: "badge-success badge-soft") { "Soft Success" }
81
+ #
82
+ # @loco_example Soft Warning Badge
83
+ # = daisy_badge(css: "badge-warning badge-soft") { "Soft Warning" }
84
+ #
85
+ # @loco_example Soft Error Badge
86
+ # = daisy_badge(css: "badge-error badge-soft") { "Soft Error" }
87
+ #
88
+ # @loco_example Dash Primary Badge
89
+ # = daisy_badge(css: "badge-primary badge-dash") { "Dash Primary" }
90
+ #
91
+ # @loco_example Dash Success Badge
92
+ # = daisy_badge(css: "badge-success badge-dash") { "Dash Success" }
93
+ #
94
+ # @loco_example Dash Warning Badge
95
+ # = daisy_badge(css: "badge-warning badge-dash") { "Dash Warning" }
96
+ #
97
+ # @loco_example Dash Error Badge
98
+ # = daisy_badge(css: "badge-error badge-dash") { "Dash Error" }
99
+ #
100
+ # @loco_example Badge with Icon
101
+ # = daisy_badge(icon: "check") { "Icon Badge" }
102
+ #
27
103
  # @!parse class Daisy::DataDisplay::BadgeComponent < LocoMotion::BaseComponent; end
28
104
  class Daisy::DataDisplay::BadgeComponent < LocoMotion::BaseComponent
29
- prepend LocoMotion::Concerns::TippableComponent
105
+ include LocoMotion::Concerns::IconableComponent
106
+ include LocoMotion::Concerns::LinkableComponent
107
+ include LocoMotion::Concerns::TippableComponent
30
108
 
31
109
  set_component_name :badge
32
110
 
@@ -41,14 +119,50 @@ class Daisy::DataDisplay::BadgeComponent < LocoMotion::BaseComponent
41
119
  # @option kwargs title [String] The text to display in the badge. You can also
42
120
  # pass the title as the first argument or provide content via a block.
43
121
  #
122
+ # @option kwargs href [String] A path or URL to which the user will be
123
+ # directed when the badge is clicked. Forces the Badge to use an `<a>` tag.
124
+ #
125
+ # @option kwargs target [String] The HTML `target` of for the `<a>` tag
126
+ # (`_blank`, `_parent`, or a specific tab / window / iframe, etc).
127
+ #
128
+ # @option kwargs icon [String] The name of Hero icon to render inside the
129
+ # badge. This is an alias of `left_icon`.
130
+ #
131
+ # @option kwargs icon_css [String] The CSS classes to apply to the icon.
132
+ # This is an alias of `left_icon_css`.
133
+ #
134
+ # @option kwargs icon_html [Hash] Additional HTML attributes to apply to the
135
+ # icon. This is an alias of `left_icon_html`.
136
+ #
137
+ # @option kwargs left_icon [String] The name of Hero icon to render inside
138
+ # the badge to the left of the text.
139
+ #
140
+ # @option kwargs left_icon_css [String] The CSS classes to apply to the left
141
+ # icon.
142
+ #
143
+ # @option kwargs left_icon_html [Hash] Additional HTML attributes to apply to
144
+ # the left icon.
145
+ #
146
+ # @option kwargs right_icon [String] The name of Hero icon to render inside
147
+ # the badge to the right of the text.
148
+ #
149
+ # @option kwargs right_icon_css [String] The CSS classes to apply to the
150
+ # right icon.
151
+ #
152
+ # @option kwargs right_icon_html [Hash] Additional HTML attributes to apply
153
+ # to the right icon.
154
+ #
44
155
  def initialize(title = nil, **kws, &block)
45
156
  super
46
157
 
47
- @title = config_option(:title, title)
158
+ @simple_title = config_option(:title, title)
48
159
  end
49
160
 
50
161
  def before_render
162
+ # Run component setup *before* super to allow LinkableComponent to override tag
51
163
  setup_component
164
+
165
+ super
52
166
  end
53
167
 
54
168
  #
@@ -59,7 +173,11 @@ class Daisy::DataDisplay::BadgeComponent < LocoMotion::BaseComponent
59
173
  # additional whitespace gets added to the output.
60
174
  #
61
175
  def call
62
- part(:component) { content || @title }
176
+ part(:component) do
177
+ concat(render_left_icon)
178
+ concat(content || @simple_title)
179
+ concat(render_right_icon)
180
+ end
63
181
  end
64
182
 
65
183
  private
@@ -1,7 +1,7 @@
1
1
  = part(:component) do
2
2
  = top_figure if top_figure?
3
3
 
4
- .card-body
4
+ = part(:body) do
5
5
  = title if title?
6
6
  = content
7
7
  = actions if actions?
@@ -39,7 +39,7 @@
39
39
  # - card.with_top_figure(src: "header.jpg")
40
40
  # - card.with_title do
41
41
  # .flex.items-center.gap-2
42
- # = heroicon_tag "star"
42
+ # = heroicon "star"
43
43
  # Featured Article
44
44
  # %p{ class: "text-base-content/70" } A beautifully designed card with rich content.
45
45
  # - card.with_bottom_figure(src: "footer.jpg")
@@ -51,13 +51,16 @@
51
51
  # = daisy_button(icon: "share", tip: "Share")
52
52
  #
53
53
  class Daisy::DataDisplay::CardComponent < LocoMotion::BaseComponent
54
- prepend LocoMotion::Concerns::TippableComponent
54
+ include LocoMotion::Concerns::TippableComponent
55
+ include LocoMotion::Concerns::LinkableComponent
55
56
 
56
57
  renders_one :title, LocoMotion::BasicComponent.build(tag_name: :h2, css: "card-title")
57
58
  renders_one :top_figure, Daisy::DataDisplay::FigureComponent.build(css: "card-image")
58
59
  renders_one :bottom_figure, Daisy::DataDisplay::FigureComponent.build(css: "card-image")
59
60
  renders_one :actions, LocoMotion::BasicComponent.build(css: "card-actions")
60
61
 
62
+ define_part :body
63
+
61
64
  # @return [String] The title text when using the simple title option.
62
65
  attr_reader :simple_title
63
66
 
@@ -71,19 +74,30 @@ class Daisy::DataDisplay::CardComponent < LocoMotion::BaseComponent
71
74
  # @option kws css [String] Additional CSS classes for styling. Common
72
75
  # options include:
73
76
  # - Image Side: `image-full` (image becomes background)
74
- # - Borders: `bordered`
75
- # - Compact: `compact` (less padding)
77
+ # - Borders: `card-border`
78
+ # - Sizes: `card-sm` (less padding)
76
79
  # - Colors: `bg-base-100`, `bg-primary`, `bg-secondary`
77
80
  #
81
+ # @option kws tip [String] The tooltip text to display when hovering over
82
+ # the component.
83
+ #
78
84
  def initialize(**kws, &block)
79
85
  super
80
86
 
81
87
  @simple_title = kws[:title]
82
-
83
- add_css(:component, "card")
84
88
  end
85
89
 
86
90
  def before_render
91
+ setup_component
92
+ super # Runs TippableComponent's setup hook
93
+
87
94
  with_title { simple_title } if simple_title && !title?
88
95
  end
96
+
97
+ private
98
+
99
+ def setup_component
100
+ add_css(:component, "card")
101
+ add_css(:body, "card-body")
102
+ end
89
103
  end
@@ -47,8 +47,8 @@
47
47
  #
48
48
  class Daisy::DataDisplay::ChatComponent < LocoMotion::BaseComponent
49
49
  renders_one :avatar, Daisy::DataDisplay::AvatarComponent.build(css: "chat-image", icon_css: "size-6 text-base-100", wrapper_css: "w-10 rounded-full")
50
- renders_one :header, LocoMotion::BasicComponent.build(css: "chat-header [:where(&)]:text-neutral-500")
51
- renders_one :footer, LocoMotion::BasicComponent.build(css: "chat-footer [:where(&)]:text-neutral-500")
50
+ renders_one :header, LocoMotion::BasicComponent.build(css: "chat-header where:text-neutral-500")
51
+ renders_one :footer, LocoMotion::BasicComponent.build(css: "chat-footer where:text-neutral-500")
52
52
 
53
53
  renders_many :bubbles, LocoMotion::BasicComponent.build(css: "chat-bubble")
54
54
 
@@ -20,7 +20,7 @@
20
20
  # = daisy_collapse do |collapse|
21
21
  # - collapse.with_title do
22
22
  # .flex.items-center.gap-2
23
- # = heroicon_tag "chevron-down"
23
+ # = heroicon "chevron-down"
24
24
  # Advanced Settings
25
25
  # %p These are some advanced configuration options.
26
26
  # = daisy_button("Apply Settings")
@@ -40,7 +40,7 @@
40
40
  # This section has a plus/minus indicator.
41
41
  #
42
42
  class Daisy::DataDisplay::CollapseComponent < LocoMotion::BaseComponent
43
- prepend LocoMotion::Concerns::TippableComponent
43
+ include LocoMotion::Concerns::TippableComponent
44
44
 
45
45
  define_parts :title, :wrapper
46
46
 
@@ -64,6 +64,9 @@ class Daisy::DataDisplay::CollapseComponent < LocoMotion::BaseComponent
64
64
  # @option kws checkbox [Boolean] Whether to use a checkbox for toggle state
65
65
  # (true) or focus/tabindex mode (false). Defaults to true.
66
66
  #
67
+ # @option kws tip [String] The tooltip text to display when hovering over
68
+ # the component.
69
+ #
67
70
  def initialize(*args, **kws, &block)
68
71
  super
69
72
 
@@ -72,9 +75,10 @@ class Daisy::DataDisplay::CollapseComponent < LocoMotion::BaseComponent
72
75
  end
73
76
 
74
77
  def before_render
75
- setup_component
76
- setup_title
77
- setup_wrapper
78
+ setup_component # Set base styles/attributes
79
+ super # Run concern setup hooks
80
+ setup_title # Set title part styles
81
+ setup_wrapper # Set wrapper part styles
78
82
  end
79
83
 
80
84
  def setup_component
@@ -26,7 +26,7 @@
26
26
  # = daisy_countdown(3.hours + 30.minutes, separator: " → ")
27
27
  #
28
28
  class Daisy::DataDisplay::CountdownComponent < LocoMotion::BaseComponent
29
- prepend LocoMotion::Concerns::TippableComponent
29
+ include LocoMotion::Concerns::TippableComponent
30
30
 
31
31
  define_parts :days, :hours, :minutes, :seconds
32
32
  define_modifiers :words, :letters
@@ -53,6 +53,9 @@ class Daisy::DataDisplay::CountdownComponent < LocoMotion::BaseComponent
53
53
  #
54
54
  # @option kws [Hash] :parts_html HTML attributes to apply to all time parts.
55
55
  #
56
+ # @option kws [String] :tip The tooltip text to display when hovering over
57
+ # the component.
58
+ #
56
59
  def initialize(*args, **kws, &block)
57
60
  super
58
61
 
@@ -63,22 +66,29 @@ class Daisy::DataDisplay::CountdownComponent < LocoMotion::BaseComponent
63
66
  end
64
67
 
65
68
  def before_render
66
- add_stimulus_controller(:component, "countdown")
69
+ setup_component # Configure countdown parts and stimulus
70
+ super # Run TippableComponent hook
71
+ end
72
+
73
+ private
74
+
75
+ def setup_component
76
+ add_stimulus_controller(:component, "loco-countdown")
67
77
 
68
78
  add_css(:component, "flex")
69
- add_css(:component, "[:where(&)]:gap-x-2") if modifiers.include?(:words)
79
+ add_css(:component, "where:gap-x-2") if modifiers.include?(:words)
70
80
 
71
81
  %i(days hours minutes seconds).each do |part|
72
82
  default_html = {
73
83
  data: {
74
84
  # Note: We can't use nested hashes here because the Rails content_tag
75
85
  # helper is stupid and won't traverse them.
76
- "countdown-target": part
86
+ "loco-countdown-target": part
77
87
  }
78
88
  }
79
89
 
80
90
  add_css(part, "countdown")
81
- add_css(part, "[:where(&)]:gap-x-1") if modifiers.include?(:words)
91
+ add_css(part, "where:gap-x-1") if modifiers.include?(:words)
82
92
  add_css(part, @parts_css) if @parts_css
83
93
 
84
94
  add_html(part, default_html)
@@ -16,6 +16,8 @@
16
16
  # Content when no image is provided
17
17
  #
18
18
  class Daisy::DataDisplay::FigureComponent < LocoMotion::BaseComponent
19
+ include LocoMotion::Concerns::LinkableComponent
20
+
19
21
  define_part :image, tag_name: :img
20
22
 
21
23
  # Creates a new figure component.
@@ -35,15 +37,18 @@ class Daisy::DataDisplay::FigureComponent < LocoMotion::BaseComponent
35
37
  def before_render
36
38
  set_tag_name(:component, :figure)
37
39
  add_html(:image, src: @src) if @src
40
+
41
+ super
38
42
  end
39
43
 
40
44
  def call
41
45
  part(:component) do
42
46
  if @src
43
- part(:image)
44
- else
45
- content
47
+ concat(part(:image))
46
48
  end
49
+
50
+ # Always show the content
51
+ concat(content)
47
52
  end
48
53
  end
49
54
  end