loco_motion-rails 0.0.7 → 0.0.8
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.
- checksums.yaml +4 -4
- data/README.md +45 -1
- data/app/components/daisy/actions/button_component.rb +109 -8
- data/app/components/daisy/actions/dropdown_component.html.haml +5 -5
- data/app/components/daisy/actions/dropdown_component.rb +94 -25
- data/app/components/daisy/actions/modal_component.html.haml +3 -2
- data/app/components/daisy/actions/modal_component.rb +94 -45
- data/app/components/daisy/actions/swap_component.rb +114 -5
- data/app/components/daisy/actions/theme_controller_component.html.haml +1 -1
- data/app/components/daisy/actions/theme_controller_component.rb +36 -1
- data/app/components/daisy/data_display/accordion_component.rb +79 -3
- data/app/components/daisy/data_display/avatar_component.rb +36 -16
- data/app/components/daisy/data_display/badge_component.rb +35 -5
- data/app/components/daisy/data_display/card_component.html.haml +5 -13
- data/app/components/daisy/data_display/card_component.rb +74 -39
- data/app/components/daisy/data_display/carousel_component.rb +38 -0
- data/app/components/daisy/data_display/chat_component.rb +40 -10
- data/app/components/daisy/data_display/collapse_component.rb +58 -1
- data/app/components/daisy/data_display/countdown_component.rb +49 -0
- data/app/components/daisy/data_display/diff_component.rb +37 -0
- data/app/components/daisy/data_display/figure_component.rb +49 -0
- data/app/components/daisy/data_display/kbd_component.rb +50 -2
- data/app/components/daisy/data_display/stat_component.rb +64 -6
- data/app/components/daisy/data_display/table_component.rb +99 -34
- data/app/components/daisy/data_display/timeline_component.rb +45 -0
- data/app/components/daisy/data_display/timeline_event_component.rb +39 -1
- data/app/components/daisy/feedback/alert_component.rb +46 -1
- data/app/components/daisy/feedback/loading_component.rb +39 -0
- data/app/components/daisy/feedback/progress_component.rb +39 -1
- data/app/components/daisy/feedback/radial_progress_component.rb +44 -1
- data/app/components/daisy/feedback/skeleton_component.rb +44 -0
- data/app/components/daisy/feedback/toast_component.rb +36 -0
- data/app/components/daisy/feedback/tooltip_component.rb +46 -10
- data/app/components/daisy/layout/artboard_component.rb +48 -0
- data/app/components/daisy/layout/divider_component.rb +50 -10
- data/app/components/daisy/layout/drawer_component.rb +62 -17
- data/app/components/daisy/layout/footer_component.rb +51 -11
- data/app/components/daisy/layout/hero_component.rb +67 -5
- data/app/components/daisy/layout/indicator_component.rb +55 -8
- data/app/components/daisy/layout/join_component.rb +71 -0
- data/app/components/daisy/layout/stack_component.rb +59 -0
- data/app/components/daisy/mockup/browser_component.rb +78 -0
- data/app/components/daisy/mockup/code_component.rb +144 -0
- data/app/components/daisy/mockup/device_component.rb +81 -0
- data/app/components/daisy/mockup/frame_component.rb +62 -0
- data/app/components/daisy/navigation/bottom_nav_component.rb +81 -2
- data/app/components/daisy/navigation/breadcrumbs_component.rb +40 -3
- data/app/components/daisy/navigation/link_component.rb +31 -6
- data/app/components/daisy/navigation/menu_component.rb +52 -20
- data/app/components/daisy/navigation/navbar_component.html.haml +1 -1
- data/app/components/daisy/navigation/navbar_component.rb +63 -2
- data/app/components/daisy/navigation/steps_component.rb +76 -0
- data/app/components/daisy/navigation/tabs_component.rb +110 -7
- data/app/components/hero/icon_component.rb +40 -0
- data/lib/daisy.rb +5 -0
- data/lib/loco_motion/helpers.rb +7 -0
- data/lib/loco_motion/version.rb +5 -0
- metadata +25 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d4d1891389f5b0a860f930a6d4e6dbb9053b6a77e349cd0f43b9de22740482b
|
4
|
+
data.tar.gz: 2f99a232731636bfaeca166092c0fb4ca51ddae6300e420951d0c0791997e1d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad963fe072e997ad83879704d8a5d9285f2e964371ee9c7418dfe7377db7950b09f43e3ff8555fad25aee3d141b7b6927ba5e70f965684d749057aaa1d6223c8
|
7
|
+
data.tar.gz: 367ecb0bf6b3b9d3ff77e6f596b12322fe1b1026bcecc619032c70e59ed94d344f3b18907e8dc8caf63b4d95343e351a808254b50da0db14c8a98b8282cb5a18
|
data/README.md
CHANGED
@@ -33,11 +33,13 @@ your solution is aligned with our goals.
|
|
33
33
|
- [About](#about)
|
34
34
|
- [Getting Started](#getting-started)
|
35
35
|
- [Installing / Setting up Rails](#installing--setting-up-rails)
|
36
|
+
- [Using UUIDs by Default](#using-uuids-by-default)
|
36
37
|
- [Install HAML (Optional)](#install-haml-optional)
|
37
38
|
- [Install DaisyUI (Optional)](#install-daisyui-optional)
|
38
39
|
- [Try Out Your Application](#try-out-your-application)
|
39
40
|
- [Debugging](#debugging)
|
40
41
|
- [Testing](#testing)
|
42
|
+
- [Services / Service Objects](#services--service-objects)
|
41
43
|
- [Authentication](#authentication)
|
42
44
|
- [Web Console](#web-console)
|
43
45
|
- [BetterErrors (Optional)](#bettererrors-optional)
|
@@ -203,6 +205,20 @@ Congratulations!
|
|
203
205
|
You can now visit [http://localhost:3000](http://localhost:3000) in your web
|
204
206
|
browser and see your running Rails application!
|
205
207
|
|
208
|
+
### Using UUIDs by Default
|
209
|
+
|
210
|
+
We believe strongly in migrating all of your primary keys to UUIDs to increase
|
211
|
+
security as well as avoiding potential scaling issues in the future.
|
212
|
+
|
213
|
+
To enable this by default, create the following file:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
# config/initializers/generators.rb
|
217
|
+
Rails.application.config.generators do |generator|
|
218
|
+
generator.orm :active_record, primary_key_type: :uuid
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
206
222
|
### Install HAML (Optional)
|
207
223
|
|
208
224
|
While you can use the default ERB templating system that comes with Rails, we
|
@@ -479,6 +495,28 @@ We'll have some guides and examples for this coming soon!
|
|
479
495
|
> We plan to have a writeup soon (an ADR specifically) on exactly why we made
|
480
496
|
> the switch.
|
481
497
|
|
498
|
+
## Services / Service Objects
|
499
|
+
|
500
|
+
It is best practice to separate your logic into Service Objects rather than
|
501
|
+
shoving all of it into your Controllers and Models.
|
502
|
+
|
503
|
+
One solution we really like is
|
504
|
+
[ActiveInteraction](https://github.com/AaronLasseigne/active_interaction).
|
505
|
+
|
506
|
+
It is very stable, has wonderful documentation, and gives you a clean way to
|
507
|
+
build your service objects with support for things like composed interactions
|
508
|
+
and even ActiveModel validations.
|
509
|
+
|
510
|
+
Add `gem 'active_interaction', '~> 5.3'` to your `Gemfile` and create a new
|
511
|
+
class called `ApplicationInteraction` if you want to give it a try!
|
512
|
+
|
513
|
+
```
|
514
|
+
# app/interactions/application_interaction.rb
|
515
|
+
class ApplicationInteraction < ActiveInteraction::Base
|
516
|
+
# Your interactions will inherit from this class!
|
517
|
+
end
|
518
|
+
```
|
519
|
+
|
482
520
|
## Authentication
|
483
521
|
|
484
522
|
There are a **lot** of different ways to handle user authentication in Ruby on
|
@@ -884,7 +922,7 @@ the GitHub Discussions feature and let us know!
|
|
884
922
|
- [ ] Basic versions of DaisyUI Data Input
|
885
923
|
- [ ] Basic versions of DaisyUI Layout
|
886
924
|
- [ ] Basic versions of DaisyUI Mockup
|
887
|
-
- [
|
925
|
+
- [x] ~~Get YARD docs rendering with (better) Markdown~~ _**Working for now**_
|
888
926
|
- [x] Extract relevant pieces into a yard-loco_motion plugin
|
889
927
|
- [x] Publish Gem
|
890
928
|
- [x] Publish NPM package
|
@@ -902,6 +940,12 @@ the GitHub Discussions feature and let us know!
|
|
902
940
|
- [ ] Build some have docs / guides / examples for using playwright-ruby-client
|
903
941
|
- [x] See if we can build a `Tippable` concern that relevant components can
|
904
942
|
include to automatically add the tooltip param and classes where possible
|
943
|
+
- [x] Rename `tail` methods to `end` since we use that in other places
|
944
|
+
- [x] Update CardComponent Figure to be a proper class like other components
|
945
|
+
- [x] Create a GitHub pull request template to standardize PR submissions
|
946
|
+
- [ ] See if we can update the Join component to auto-add the `join-item` CSS
|
947
|
+
under certain conditions
|
948
|
+
- [ ] Add title and description content_for blocks to all examples for SEO purposes
|
905
949
|
|
906
950
|
[1]: https://loco-motion.profoundry.us/
|
907
951
|
[2]: https://loco-motion-demo-staging.profoundry.us/
|
@@ -1,12 +1,97 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
|
+
# The Button component can be used to render HTML `<button>` or `<a>` elements
|
3
|
+
# that are styled to look like a clickable element.
|
4
|
+
#
|
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
|
7
|
+
# options to allow overriding / customization.
|
8
|
+
#
|
9
|
+
# Includes the {LocoMotion::Concerns::TippableComponent} module to enable easy
|
10
|
+
# tooltip addition.
|
11
|
+
#
|
12
|
+
# @loco_example Basic Usage
|
13
|
+
# = daisy_button("Click Me")
|
14
|
+
#
|
15
|
+
# = daisy_button do
|
16
|
+
# Click Me Too
|
17
|
+
#
|
18
|
+
# = daisy_button(icon: "heart", tip: "Love")
|
19
|
+
#
|
20
|
+
# = daisy_button(title: "Button with Two Icons", left_icon: "heart", right_icon: "plus")
|
21
|
+
#
|
2
22
|
class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
|
3
23
|
prepend LocoMotion::Concerns::TippableComponent
|
4
24
|
|
5
|
-
|
6
|
-
|
7
|
-
|
25
|
+
#
|
26
|
+
# Instantiate a new Button component.
|
27
|
+
#
|
28
|
+
# @param title [String] The title of the button. Defaults to "Submit" if none
|
29
|
+
# of title, left icon, or right icon is provided. Will be considered the
|
30
|
+
# `action` parameter if **both** the title and a block are provided.
|
31
|
+
#
|
32
|
+
# @param action [String] The Stimulus action that should fire when the button
|
33
|
+
# is clicked.
|
34
|
+
#
|
35
|
+
# @param kws [Hash] The keyword arguments for the component.
|
36
|
+
#
|
37
|
+
# @option kws title [String] The title of the button. You can also
|
38
|
+
# pass the title, icons, or any other HTML content as a block.
|
39
|
+
#
|
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
|
+
# @option kws href [String] A path or URL to which the user will be
|
47
|
+
# directed when the button is clicked. Forces the Button to use an `<a>`
|
48
|
+
# tag.
|
49
|
+
#
|
50
|
+
# > **Note:** _You should use either the `action` or the `href` option, but
|
51
|
+
# not both._
|
52
|
+
#
|
53
|
+
# @option kws target [String] The HTML `target` of for the `<a>` tag
|
54
|
+
# (`_blank`, `_parent`, or a specific tab / window / iframe, etc).
|
55
|
+
#
|
56
|
+
# @option kws icon [String] The name of Hero icon to render inside
|
57
|
+
# the button. This is an alias of `left_icon`.
|
58
|
+
#
|
59
|
+
# @option kws icon_css [String] The CSS classes to apply to the icon.
|
60
|
+
# This is an alias of `left_icon_css`.
|
61
|
+
#
|
62
|
+
# @option kws icon_html [Hash] Additional HTML attributes to apply to
|
63
|
+
# the icon. This is an alias of `left_icon_html`.
|
64
|
+
#
|
65
|
+
# @option kws left_icon [String] The name of Hero icon to render inside
|
66
|
+
# the button to the left of the text.
|
67
|
+
#
|
68
|
+
# @option kws left_icon_css [String] The CSS classes to apply to the left
|
69
|
+
# icon.
|
70
|
+
#
|
71
|
+
# @option kws left_icon_html [Hash] Additional HTML attributes to apply to
|
72
|
+
# the left icon.
|
73
|
+
#
|
74
|
+
# @option kws right_icon [String] The name of Hero icon to render inside
|
75
|
+
# the button to the right of the text.
|
76
|
+
#
|
77
|
+
# @option kws right_icon_css [String] The CSS classes to apply to the right
|
78
|
+
# icon.
|
79
|
+
#
|
80
|
+
# @option kws right_icon_html [Hash] Additional HTML attributes to apply to
|
81
|
+
# the right icon.
|
82
|
+
#
|
83
|
+
def initialize(title = nil, action = nil, **kws, &block)
|
8
84
|
super
|
9
85
|
|
86
|
+
# If both a title and a block are provided, assume the title is the action
|
87
|
+
action = title if title && block_given?
|
88
|
+
|
89
|
+
# Force the title to be nil if a block is given so we don't accidentally
|
90
|
+
# render two titles
|
91
|
+
title = nil if block_given?
|
92
|
+
|
93
|
+
@action = config_option(:action, action)
|
94
|
+
|
10
95
|
@href = config_option(:href)
|
11
96
|
@target = config_option(:target)
|
12
97
|
|
@@ -23,15 +108,21 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
|
|
23
108
|
@right_icon_html = config_option(:right_icon_html, @icon_html)
|
24
109
|
|
25
110
|
default_title = @left_icon || @right_icon ? nil : "Submit"
|
26
|
-
@simple_title = config_option(:title,
|
111
|
+
@simple_title = config_option(:title, title || default_title)
|
27
112
|
end
|
28
113
|
|
114
|
+
#
|
115
|
+
# Calls the {setup_component} method before rendering the component.
|
116
|
+
#
|
29
117
|
def before_render
|
30
118
|
setup_component
|
31
119
|
end
|
32
120
|
|
33
|
-
|
34
|
-
|
121
|
+
#
|
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.
|
125
|
+
#
|
35
126
|
def setup_component
|
36
127
|
if @href
|
37
128
|
set_tag_name(:component, :a)
|
@@ -42,13 +133,23 @@ class Daisy::Actions::ButtonComponent < LocoMotion::BaseComponent
|
|
42
133
|
|
43
134
|
add_css(:component, "btn")
|
44
135
|
|
45
|
-
|
136
|
+
if @icon || @left_icon || @right_icon
|
137
|
+
add_css(:component, "[:where(&)]:items-center [:where(&)]:gap-2")
|
138
|
+
end
|
139
|
+
|
140
|
+
add_html(:component, { "data-action": @action }) if @action
|
46
141
|
end
|
47
142
|
|
143
|
+
#
|
144
|
+
# Returns the HTML attributes for the left icon.
|
145
|
+
#
|
48
146
|
def left_icon_html
|
49
147
|
{ class: @left_icon_css }.merge(@left_icon_html)
|
50
148
|
end
|
51
149
|
|
150
|
+
#
|
151
|
+
# Returns the HTML attributes for the right icon.
|
152
|
+
#
|
52
153
|
def right_icon_html
|
53
154
|
{ class: @right_icon_css }.merge(@right_icon_html)
|
54
155
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
= part(:component) do
|
2
|
-
- if
|
3
|
-
=
|
2
|
+
- if activator?
|
3
|
+
= activator
|
4
4
|
- else
|
5
|
-
=
|
6
|
-
= @simple_title
|
5
|
+
= button
|
7
6
|
|
8
7
|
- if items.any?
|
9
8
|
= part(:menu) do
|
10
9
|
- items.each do |item|
|
11
|
-
=
|
10
|
+
= part(:menu_item) do
|
11
|
+
= item
|
12
12
|
- else
|
13
13
|
= content
|
@@ -1,48 +1,117 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
|
+
# The Dropdown component shows a Button, or any other component you wish, with a
|
3
|
+
# hovering menu that opens on click (or hover). It provides a flexible way to
|
4
|
+
# create dropdown menus with customizable triggers and content.
|
5
|
+
#
|
6
|
+
# Note that the dropdown uses slots for both the activator and menu items,
|
7
|
+
# allowing for maximum flexibility in how the dropdown is triggered and what
|
8
|
+
# content it displays.
|
9
|
+
#
|
10
|
+
# @part menu The default / styled menu rendered by the dropdown. Contains all
|
11
|
+
# menu items and provides the dropdown's positioning and animation.
|
12
|
+
# @part menu_item The styles for every item in the dropdown. Provides consistent
|
13
|
+
# spacing and hover states.
|
14
|
+
#
|
15
|
+
# @slot button The button that triggers the dropdown. This is the default trigger
|
16
|
+
# and is styled automatically.
|
17
|
+
# @slot activator A custom (i.e. non-button) activator for the dropdown.
|
18
|
+
# Automatically adds the `role="button"` and `tabindex="0"` attributes.
|
19
|
+
# @slot item+ The items in the dropdown. Each item will be styled consistently
|
20
|
+
# with proper spacing and hover states.
|
21
|
+
#
|
22
|
+
# @loco_example Basic Usage
|
23
|
+
# = daisy_dropdown do |dropdown|
|
24
|
+
# - dropdown.with_button do
|
25
|
+
# Click me!
|
26
|
+
# - dropdown.with_item do
|
27
|
+
# Item 1
|
28
|
+
# - dropdown.with_item do
|
29
|
+
# Item 2
|
30
|
+
#
|
31
|
+
# @loco_example Custom Activator
|
32
|
+
# = daisy_dropdown do |dropdown|
|
33
|
+
# - dropdown.with_activator do
|
34
|
+
# = heroicon_tag "bars-3", css: "size-6"
|
35
|
+
# - dropdown.with_item do
|
36
|
+
# Menu Item 1
|
37
|
+
# - dropdown.with_item do
|
38
|
+
# Menu Item 2
|
39
|
+
#
|
40
|
+
# @loco_example Complex Items
|
41
|
+
# = daisy_dropdown do |dropdown|
|
42
|
+
# - dropdown.with_button do
|
43
|
+
# User Settings
|
44
|
+
# - dropdown.with_item do
|
45
|
+
# .flex.gap-2.items-center
|
46
|
+
# = heroicon_tag "user-circle"
|
47
|
+
# Profile
|
48
|
+
# - dropdown.with_item do
|
49
|
+
# .flex.gap-2.items-center
|
50
|
+
# = heroicon_tag "cog-6-tooth"
|
51
|
+
# Settings
|
52
|
+
# - dropdown.with_item do
|
53
|
+
# .flex.gap-2.items-center.text-error
|
54
|
+
# = heroicon_tag "arrow-right-on-rectangle"
|
55
|
+
# Logout
|
56
|
+
#
|
2
57
|
class Daisy::Actions::DropdownComponent < LocoMotion::BaseComponent
|
3
58
|
|
4
|
-
|
5
|
-
def before_render
|
6
|
-
add_html(:component, { role: "button", tabindex: 0 })
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
ItemComponent = LocoMotion::BasicComponent.build do
|
11
|
-
def before_render
|
12
|
-
set_tag_name(:component, :li)
|
13
|
-
end
|
14
|
-
end
|
59
|
+
include ViewComponent::SlotableDefault
|
15
60
|
|
16
|
-
define_parts :
|
61
|
+
define_parts :menu, :menu_item
|
17
62
|
|
18
|
-
renders_one :
|
19
|
-
|
63
|
+
renders_one :activator, LocoMotion::BasicComponent.build(html: { role: "button", tabindex: 0 })
|
64
|
+
renders_one :button, Daisy::Actions::ButtonComponent
|
65
|
+
renders_many :items
|
20
66
|
|
21
|
-
|
67
|
+
#
|
68
|
+
# Creates a new instance of the DropdownComponent.
|
69
|
+
#
|
70
|
+
# @param title [String] The title of the dropdown. Will be used as the button
|
71
|
+
# text if no custom button or activator is provided.
|
72
|
+
#
|
73
|
+
# @param kws [Hash] The keyword arguments for the component.
|
74
|
+
#
|
75
|
+
# @option kws title [String] The title of the dropdown. You can also pass this
|
76
|
+
# as the first argument.
|
77
|
+
#
|
78
|
+
def initialize(title = nil, **kws, &block)
|
22
79
|
super
|
23
80
|
|
24
|
-
@simple_title = config_option(:title,
|
81
|
+
@simple_title = config_option(:title, title)
|
25
82
|
end
|
26
83
|
|
84
|
+
#
|
85
|
+
# Adds the relevant Daisy classes to the component.
|
86
|
+
#
|
27
87
|
def before_render
|
28
88
|
setup_component
|
29
|
-
setup_title
|
30
89
|
setup_menu
|
31
90
|
end
|
32
91
|
|
92
|
+
#
|
93
|
+
# Add the `dropdown` CSS class to the component.
|
94
|
+
#
|
33
95
|
def setup_component
|
34
96
|
add_css(:component, "dropdown")
|
35
97
|
end
|
36
98
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
add_html(:title, { role: "button", tabindex: 0 })
|
41
|
-
end
|
42
|
-
|
99
|
+
#
|
100
|
+
# Make the menu a `<ul> / <li>` element and add the relevant Daisy classes.
|
101
|
+
#
|
43
102
|
def setup_menu
|
103
|
+
# Setup menu itself
|
44
104
|
set_tag_name(:menu, :ul)
|
45
105
|
add_css(:menu, "dropdown-content menu bg-base-100 rounded-box shadow w-52 p-2 z-[1]")
|
46
|
-
|
106
|
+
|
107
|
+
# Setup menu items
|
108
|
+
set_tag_name(:menu_item, :li)
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Provides a default button if no button or custom activator is provided.
|
113
|
+
#
|
114
|
+
def default_button
|
115
|
+
Daisy::Actions::ButtonComponent.new(title: @simple_title)
|
47
116
|
end
|
48
117
|
end
|
@@ -1,51 +1,81 @@
|
|
1
1
|
#
|
2
2
|
# The Modal component renders a modal dialog that can be opened and closed. It
|
3
|
-
#
|
3
|
+
# provides a structured way to display content that requires user attention or
|
4
|
+
# interaction, such as forms, confirmations, or detailed information.
|
4
5
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# @part close_icon_wrapper The container for the close icon.
|
9
|
-
# @part close_icon The default close icon.
|
10
|
-
# @part backdrop The backdrop that covers the rest of the screen.
|
11
|
-
# @part title Container for the default title for the modal.
|
12
|
-
# @part actions Container for all modal actions.
|
13
|
-
# @part start_actions Container for the left (start) aligned actions for the modal.
|
14
|
-
# @part end_actions The end actions for the modal.
|
6
|
+
# Note that the modal uses the HTML `<dialog>` element and its native methods
|
7
|
+
# (`showModal()` and `close()`). This provides better accessibility and keyboard
|
8
|
+
# navigation compared to div-based modals.
|
15
9
|
#
|
16
|
-
# @
|
17
|
-
# @
|
18
|
-
# @
|
19
|
-
#
|
20
|
-
# @
|
10
|
+
# @part dialog The main `<dialog>` container that wraps the modal content.
|
11
|
+
# @part box The container for the modal content, providing padding and layout.
|
12
|
+
# @part close_icon_wrapper The container for the close icon, positioned in the
|
13
|
+
# top-right corner.
|
14
|
+
# @part close_icon The default close icon button.
|
15
|
+
# @part backdrop The semi-transparent backdrop that covers and dims the main
|
16
|
+
# content.
|
17
|
+
# @part title Container for the modal title, styled for prominence.
|
18
|
+
# @part actions Container for all modal action buttons.
|
19
|
+
# @part start_actions Container for left (start) aligned action buttons.
|
20
|
+
# @part end_actions Container for right (end) aligned action buttons.
|
21
21
|
#
|
22
|
-
# @
|
22
|
+
# @slot activator A custom element that opens the modal. Automatically adds
|
23
|
+
# `role="button"` and `tabindex="0"` attributes for accessibility.
|
24
|
+
# @slot button The button that opens the modal. Defaults to a standard Daisy
|
25
|
+
# button with the modal's title.
|
26
|
+
# @slot close_icon A custom close button to replace the default 'X' icon.
|
27
|
+
# @slot title Custom title content, replacing the default text title.
|
28
|
+
# @slot start_actions Left (start) aligned buttons, typically for secondary actions
|
29
|
+
# like "Cancel".
|
30
|
+
# @slot end_actions Right (end) aligned buttons, typically for primary actions
|
31
|
+
# like "Submit" or "Save".
|
32
|
+
#
|
33
|
+
# @loco_example Basic Modal
|
23
34
|
# = daisy_modal(title: "Simple Modal") do |modal|
|
35
|
+
# - modal.with_button(css: "btn-primary") { "Open Modal" }
|
36
|
+
# %p This is a basic modal with some content.
|
37
|
+
# - modal.with_end_actions do
|
38
|
+
# %form{ method: :dialog }
|
39
|
+
# = daisy_button { "Close" }
|
40
|
+
#
|
41
|
+
# @loco_example Form Modal
|
42
|
+
# = daisy_modal(title: "Edit Profile") do |modal|
|
43
|
+
# - modal.with_button { "Edit Profile" }
|
44
|
+
# = form_with(model: @user) do |f|
|
45
|
+
# .space-y-4
|
46
|
+
# = f.text_field :name, class: "input input-bordered w-full"
|
47
|
+
# = f.email_field :email, class: "input input-bordered w-full"
|
48
|
+
# - modal.with_start_actions do
|
49
|
+
# %form{ method: :dialog }
|
50
|
+
# = daisy_button { "Cancel" }
|
51
|
+
# - modal.with_end_actions do
|
52
|
+
# = daisy_button(css: "btn-primary", type: "submit") { "Save Changes" }
|
53
|
+
#
|
54
|
+
# @loco_example Custom Activator
|
55
|
+
# = daisy_modal(title: "User Details") do |modal|
|
24
56
|
# - modal.with_activator do
|
25
|
-
# -
|
26
|
-
#
|
27
|
-
#
|
57
|
+
# .flex.items-center.gap-2.cursor-pointer
|
58
|
+
# = heroicon_tag "user-circle"
|
59
|
+
# %span View Details
|
28
60
|
#
|
29
|
-
#
|
30
|
-
#
|
61
|
+
# %dl.space-y-2
|
62
|
+
# %dt Name
|
63
|
+
# %dd John Doe
|
64
|
+
# %dt Email
|
65
|
+
# %dd john@example.com
|
31
66
|
#
|
32
|
-
# - modal.with_end_actions
|
67
|
+
# - modal.with_end_actions do
|
33
68
|
# %form{ method: :dialog }
|
34
|
-
# = daisy_button
|
35
|
-
# Cancel
|
36
|
-
# %form{ action: "", method: :get }
|
37
|
-
# %input{ type: "hidden", name: "submitted", value: "true" }
|
38
|
-
# = daisy_button(css: "btn-primary") do
|
39
|
-
# Submit
|
69
|
+
# = daisy_button { "Close" }
|
40
70
|
#
|
41
71
|
class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
|
42
72
|
set_component_name :modal
|
43
73
|
|
44
|
-
define_parts :dialog, :box, :actions,
|
45
|
-
:activator, :close_icon_wrapper, :close_icon,
|
74
|
+
define_parts :dialog, :box, :actions, :close_icon_wrapper, :close_icon,
|
46
75
|
:backdrop, :title, :start_actions, :end_actions
|
47
76
|
|
48
|
-
renders_one :activator
|
77
|
+
renders_one :activator, LocoMotion::BasicComponent.build(html: { role: "button", tabindex: 0 })
|
78
|
+
renders_one :button, Daisy::Actions::ButtonComponent
|
49
79
|
renders_one :close_icon
|
50
80
|
renders_one :title
|
51
81
|
renders_one :start_actions
|
@@ -63,33 +93,35 @@ class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
|
|
63
93
|
attr_reader :simple_title
|
64
94
|
|
65
95
|
#
|
66
|
-
#
|
67
|
-
#
|
96
|
+
# Creates a new instance of the ModalComponent.
|
97
|
+
#
|
98
|
+
# @param title [String] The title of the modal. Used in both the modal header
|
99
|
+
# and the default trigger button.
|
68
100
|
#
|
69
|
-
# @param args [Array] Currently unused and passed through to the
|
70
|
-
# BaseComponent.
|
71
101
|
# @param kws [Hash] The keyword arguments for the component.
|
72
102
|
#
|
73
|
-
# @option kws
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
# component to render above the main content of the modal (see
|
79
|
-
# {simple_title}).
|
103
|
+
# @option kws title [String] The title of the modal. You can also pass this as
|
104
|
+
# the first argument.
|
105
|
+
#
|
106
|
+
# @option kws closable [Boolean] If true (default), shows a close icon in the
|
107
|
+
# top-right corner.
|
80
108
|
#
|
81
|
-
|
109
|
+
# @option kws dialog_id [String] A custom ID for the dialog element. If not
|
110
|
+
# provided, a unique ID will be generated.
|
111
|
+
#
|
112
|
+
def initialize(title = nil, **kws, &block)
|
82
113
|
super
|
83
114
|
|
84
115
|
@dialog_id = config_option(:dialog_id, SecureRandom.uuid)
|
85
116
|
@closable = config_option(:closable, true)
|
86
|
-
@simple_title = config_option(:title)
|
117
|
+
@simple_title = config_option(:title, title)
|
87
118
|
end
|
88
119
|
|
89
120
|
#
|
90
121
|
# Sets up the component with various CSS classes and HTML attributes.
|
91
122
|
#
|
92
123
|
def before_render
|
124
|
+
setup_activator_or_button
|
93
125
|
setup_component
|
94
126
|
setup_backdrop
|
95
127
|
setup_box
|
@@ -100,6 +132,18 @@ class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
|
|
100
132
|
|
101
133
|
private
|
102
134
|
|
135
|
+
def setup_activator_or_button
|
136
|
+
onclick = "document.getElementById('#{dialog_id}').showModal()"
|
137
|
+
|
138
|
+
element = if activator?
|
139
|
+
activator
|
140
|
+
else
|
141
|
+
button || default_button
|
142
|
+
end
|
143
|
+
|
144
|
+
element.add_html(:component, { onclick: onclick })
|
145
|
+
end
|
146
|
+
|
103
147
|
def setup_component
|
104
148
|
set_tag_name(:component, :dialog)
|
105
149
|
add_html(:component, id: dialog_id)
|
@@ -131,4 +175,9 @@ class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent
|
|
131
175
|
def setup_actions
|
132
176
|
add_css(:actions, "mt-2 flex flex-row items-center justify-between")
|
133
177
|
end
|
178
|
+
|
179
|
+
# Provide a default button if no button is supplied.
|
180
|
+
def default_button
|
181
|
+
with_button(simple_title)
|
182
|
+
end
|
134
183
|
end
|