bs5_expandable_list_group 0.1.0 → 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 (22) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +124 -20
  3. data/app/components/bs5/expandable_list/group_component.html.erb +9 -0
  4. data/app/components/bs5/expandable_list/group_component.rb +43 -0
  5. data/app/components/bs5/expandable_list/group_item_component.html.erb +15 -0
  6. data/app/components/bs5/expandable_list/group_item_component.rb +100 -0
  7. data/app/components/bs5/{expandable_list_item_header_actions_component.html.erb → expandable_list/group_item_header/actions_component.html.erb} +1 -1
  8. data/app/components/bs5/expandable_list/group_item_header/actions_component.rb +18 -0
  9. data/app/components/bs5/{expandable_list_item_header_title_component.html.erb → expandable_list/group_item_header/title_component.html.erb} +2 -2
  10. data/app/components/bs5/expandable_list/group_item_header/title_component.rb +27 -0
  11. data/app/helpers/bs5_expandable_list_group/view_components_helper.rb +15 -0
  12. data/lib/bs5_expandable_list_group/engine.rb +5 -0
  13. data/lib/bs5_expandable_list_group/version.rb +1 -1
  14. data/lib/generators/bs5_expandable_list_group/install/templates/controllers/stretchable_item_controller.js +1 -2
  15. data/lib/generators/bs5_expandable_list_group/install/templates/stylesheets/_expandable-items.scss +15 -7
  16. metadata +17 -13
  17. data/app/components/bs5/expandable_list_group_component.html.erb +0 -5
  18. data/app/components/bs5/expandable_list_group_component.rb +0 -33
  19. data/app/components/bs5/expandable_list_item_component.html.erb +0 -9
  20. data/app/components/bs5/expandable_list_item_component.rb +0 -52
  21. data/app/components/bs5/expandable_list_item_header_actions_component.rb +0 -14
  22. data/app/components/bs5/expandable_list_item_header_title_component.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b3cf656df05f0efc37c63c574dc62e39dfc143911398bc3346f5641a1ac14400
4
- data.tar.gz: 1122074157406c6c4a52aa579d59c64fe8162e3c320c5bb03d6dc56b8e5f9b12
3
+ metadata.gz: d0fe287158fb9bd8dc214ab834588e700e6a1c87c13410afa2761f6200a34dc8
4
+ data.tar.gz: 20e7875417d6b574f86c92e6c70595cad7cfd555ebbbde4f68e9c7bdf082d661
5
5
  SHA512:
6
- metadata.gz: 2e225cb6367f28f3e31123bf1a9af9d6735bf441ef64e5d2276f04ebbfbf6d6b7545f7e00fc64741ca81b293b6273a9363cb802832f39fbc426a7a22998b819e
7
- data.tar.gz: 3294f3b18925ebf3f7317bf07f67816e03e4fe54c700a8156de928675c88ec7183a1175de4aeebf738e0ecab9cda4bb0d5f8d971f0651e733121c67135671c3a
6
+ metadata.gz: 9ae2e083544567258691eb1a6d0b60b4c43de0bc7c9bbe4dbabb98d46e9df9c7d06c67b9febbd2daa156bee4a863a63f1a1e05fa31649ab11f960867ebd22fe7
7
+ data.tar.gz: 80aee9b9c941a123cde3190788c6d1e528ea65aff3eea285197edddb3627818ae8f86ab3daeb8cf0d1da5f5ba833caa779dad6a7a9eca090cfcef48c7f51bbbf
data/README.md CHANGED
@@ -1,15 +1,16 @@
1
1
  # Bootstrap 5 expandable list group
2
2
 
3
3
  [![Build Status](https://travis-ci.org/bazzel/Bs5ExpandableListGroup.svg?branch=main)](https://travis-ci.org/bazzel/Bs5ExpandableListGroup)
4
+ [![Gem Version](https://badge.fury.io/rb/bs5_expandable_list_group.svg)](https://badge.fury.io/rb/bs5_expandable_list_group)
4
5
 
5
- **Bootstrap 5 expandable list group** gives you a simple API for creating expandable and stretchable list groups. A bit like [Bootstrap 5](https://getbootstrap.com/)'s [Accordion](https://getbootstrap.com/docs/5.0/components/accordion/), [Collapse](https://getbootstrap.com/docs/5.0/components/collapse/) and [List group](https://getbootstrap.com/docs/5.0/components/list-group/) components combined.
6
+ **Bootstrap 5 expandable list group** is a Ruby on Rails engine and gives you a simple API for creating expandable and stretchable list groups. A bit like [Bootstrap 5](https://getbootstrap.com/)'s [Accordion](https://getbootstrap.com/docs/5.0/components/accordion/), [Collapse](https://getbootstrap.com/docs/5.0/components/collapse/) and [List group](https://getbootstrap.com/docs/5.0/components/list-group/) components combined.
6
7
 
7
8
  https://user-images.githubusercontent.com/7672/120296188-27170580-c2c8-11eb-936a-a93c16326acb.mp4
8
9
 
9
10
  ## TL;DR
10
11
 
11
12
  ```erb
12
- <%= render(Bs5::ExpandableListGroupComponent.new) do |c| %>
13
+ <%= bs5_expandable_list_group do |c| %>
13
14
  <% @posts.each do |post| %>
14
15
  <% c.item do |i| %>
15
16
  <%= i.title { post.title } %>
@@ -55,7 +56,7 @@ $ bin/rails generate bs5_expandable_list_group:install
55
56
 
56
57
  This copies the required assets to your application directory:
57
58
 
58
- Stylesheets are copied to `app/javascript/stylesheets`. If needed, you can the following line to your `application.scss` to import them:
59
+ Stylesheets are copied to `app/javascript/stylesheets`. If needed, you can add the following line to your `application.scss` to import them:
59
60
 
60
61
  ```scss
61
62
  @import "bootstrap";
@@ -63,16 +64,14 @@ Stylesheets are copied to `app/javascript/stylesheets`. If needed, you can the f
63
64
  @import "stylesheets/stretchable-items";
64
65
  ```
65
66
 
66
- When you use Webpacker for your CSS, you should move these added stylesheets to the proper location (propably somewhere in `app/javascript` and import them in `application.scss` (or alike) located there.
67
-
68
67
  ## Usage
69
68
 
70
- To render a **Bootstrap 5 expandable list group** you use `render(Bs5::ExpandableListGroupComponent.new)` and pass it a block for rendering every list item.
69
+ To render a **Bootstrap 5 expandable list group** you use `bs5_expandable_list_group` and pass it a block for rendering every list item.
71
70
 
72
- Let's say, in the `index` action of your `PostsController`, you have assigned `@posts` that contains a list of `Post` instances. To render these `@posts` in a **Bootstrap 5 expandable list group**, you put the following code in your `index.html.erb` template:
71
+ Given that you have assigned a list of `Post` instances to `@posts`, to render these `@posts` in a **Bootstrap 5 expandable list group**, you put the following code in your template:
73
72
 
74
73
  ```erb
75
- <%= render(Bs5::ExpandableListGroupComponent.new) do |c| %>
74
+ <%= bs5_expandable_list_group do |c| %>
76
75
  <% @posts.each do |post| %>
77
76
  <% c.item do |i| %>
78
77
  <%= i.title { post.title } %>
@@ -127,11 +126,11 @@ To show one set:
127
126
  ...
128
127
  <% c.item do |i| %>
129
128
  <%= i.title do |t| %>
130
- ...
129
+ ...
131
130
  <% end %>
132
131
  <% i.actions do %>
133
132
  <%= link_to 'Delete', post, method: :delete, class: 'btn btn-sm btn-outline-danger' %>
134
- <%= link_to 'Edit', edit_post_path(post), class: 'btn btn-sm btn-outline-secondary' %>
133
+ <%= link_to 'Edit', edit_post_path(post), class: 'btn btn-sm btn-outline-secondary' %>
135
134
  <% end %>
136
135
  <%= i.body { ... } %>
137
136
  <% end %>
@@ -143,14 +142,14 @@ To show a different set on hovering:
143
142
  ...
144
143
  <% c.item do |i| %>
145
144
  <%= i.title do |t| %>
146
- ...
145
+ ...
147
146
  <% end %>
148
147
  <% i.actions do |a| %>
149
- <% a.collapsed %>
148
+ <% a.collapsed do %>
150
149
  <%= link_to 'Delete', post, method: :delete, class: 'btn btn-sm btn-outline-danger' %>
151
150
  <%= link_to 'Edit', edit_post_path(post), class: 'btn btn-sm btn-outline-secondary' %>
152
151
  <% end %>
153
- <% a.expanded %>
152
+ <% a.expanded do %>
154
153
  <%= link_to 'Details', post_path(post), class: 'btn btn-sm btn-outline-secondary' %>
155
154
  <%= link_to 'Comment' ... %>
156
155
  <%= link_to 'Delete', post, method: :delete, class: 'btn btn-sm btn-outline-danger' %>
@@ -161,26 +160,131 @@ To show a different set on hovering:
161
160
  <% end %>
162
161
  ```
163
162
 
164
- ### Passing options
163
+ #### Bypassing the hover behaviour
164
+
165
+ By default, when an item is collapsed, actions only show when you hover your mouse over the item. Since we use the `visibility` CSS property for this, you can bypass this behaviour one or more actions by setting its `visibility` property to `visible`. The following example uses the [`visible` utility](https://getbootstrap.com/docs/5.0/utilities/visibility/) from Bootstrap 5, but of course you can also use CSS:
166
+
167
+ ```erb
168
+ ...
169
+ <% c.item do |i| %>
170
+ <%= i.title do |t| %>
171
+ ...
172
+ <% end %>
173
+ <% i.actions do |a| %>
174
+ <%= link_to 'Not so important link', ... %>
175
+ <%= link_to 'Very important link', ..., class: 'visible` %>
176
+ <% end %>
177
+ <%= i.body { ... } %>
178
+ <% end %>
179
+ ```
180
+
181
+ ### Omitting the `item`'s methods
182
+
183
+ Instead of using the `item`'s methods `title`, `body` and/or `actions` you can just use (HTML-) text as a block.
184
+ This will render just a [list group item](https://getbootstrap.com/docs/5.0/components/list-group/#basic-example), but will come in handy when you, i.e. show the first 25 items of a longer list and want to present a "Load more" link as last item of the list (for simplicity sake the sample uses a non-working `link_to_next_page` although this is [part of Kaminari](https://github.com/kaminari/kaminari#the-link_to_next_page-and-link_to_previous_page-aliased-to-link_to_prev_page-helper-methods)):
185
+
186
+ ```erb
187
+ <%= bs5_expandable_list_group do |c| %>
188
+ <% @posts.each do |post| %>
189
+ <% c.item do |i| %>
190
+ <%= i.title { post.title } %>
191
+ <%= i.body { post.text } %>
192
+ <% end %>
193
+ <% end %>
194
+ <% if @posts.next_page %>
195
+ <% c.item do %>
196
+ <%= link_to_next_page @posts "Load more" %>
197
+ <% end %>
198
+ <% end %>
199
+ <% end %>
200
+ ```
201
+
202
+ ### Omitting the `item`
203
+
204
+ Instead of calling the `item` method on the yielded component, when you pass a block, it's rendered wrapped in the container element:
205
+
206
+ ```erb
207
+ <%= bs5_expandable_list_group do %>
208
+ <%= render @posts %>
209
+ <% end %>
210
+ ```
211
+
212
+ This will give you the same results as wrapping the posts in a `div` with the class **list-group**, but you can still pass other options to the `bs5_expandable_list_group` (although not all of them will be effective).
213
+
214
+ ### Rendering a single item
165
215
 
166
- The following options can be passed to `Bs5::ExpandableListGroupComponent.new`:
216
+ By calling the `item` method on the passed component you can render an item. But this can also be achieved outside the block by using the `bs5_expandable_list_group_item` helper method. The following snippet has the same result as other examples, but it does not use the `bs5_expandable_list_group` method:
217
+
218
+ ```erb
219
+ <div id="posts" class="list-group">
220
+ <% @posts.each do |post| %>
221
+ <% bs5_expandable_list_group_item(parent_id: 'posts') do |i| %>
222
+ <%= i.title { post.title } %>
223
+ <%= i.body { post.text } %>
224
+ <% end %>
225
+ <% end %>
226
+ </div>
227
+ ```
228
+
229
+ An application for rendering a single item is when you want to update an item without doing a full page reload by sending a response that contains only the list item and use JavaScript or (preferably) [Turbo](https://turbo.hotwire.dev/) to update the page.
230
+
231
+ #### Passing options
232
+
233
+ The following options can be passed to `bs5_expandable_list_group_item`:
167
234
 
168
235
  | name | default | description |
169
236
  |---|---|---|
170
- | `id` | | is used to assign an id HTML attribute to the rendered container |
171
- | `class` | | is added to the class attribute of the rendered container |
172
- | `accordion` | `false` | Behaves as an Bootstrap [accordion](https://getbootstrap.com/docs/5.0/components/accordion/) by having only 1 item expanded |
173
- | `expandable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit|
237
+ | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the list item. |
238
+ | `parent_id` | | ID of a parent element to add accordion-like behaviour. |
239
+ | `stretchable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit. |
240
+
174
241
 
242
+ ### Wrap an item in an extra element
243
+
244
+ Every list item is a `div` (or the element specified with `tag`) with one or more CSS classes and, dependent on block passed, some `data` attributes.
245
+ However, you can wrap a list item in a extra element by passing a `wrapper_html` option to the `item` method:
246
+
247
+ ```erb
248
+ ...
249
+ <% c.item(wrapper_html: { tag: :turbo_frame, id: dom_id(post) }) do |i| %>
250
+ <%= i.title do |t| %>
251
+ <%= t.collapsed { 'Collapsed title' } %>
252
+ <%= t.expanded { 'Expanded title' } %>
253
+ <% end %>
254
+ <%= i.body { ... } %>
255
+ <% end %>
256
+ ```
257
+
258
+ All options passed to the item method are used as HTML attributes of the wrapper, expect for the following:
259
+
260
+ | name | default | description |
261
+ |---|---|---|
262
+ | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the wrapper |
263
+
264
+ ### Passing options
265
+
266
+ The following options can be passed to `bs5_expandable_list_group`:
267
+
268
+ | name | default | description |
269
+ |---|---|---|
270
+ | `tag` | `:div` | A symbol or string of a valid HTML tag that is used for the tag of the list group. |
271
+ | `id` | | is used to assign an id HTML attribute to the rendered container. |
272
+ | `class` | | is added to the class attribute of the rendered container. |
273
+ | `accordion` | `false` | Behaves as an Bootstrap [accordion](https://getbootstrap.com/docs/5.0/components/accordion/) by having only 1 item expanded (only effective when used with `item` in the passed block). |
274
+ | `stretchable` | `false` | Expanded items are shown a little bit bigger as if they come out a bit. |
275
+ | `expanded` | `false` | Show the item expanded. |
175
276
 
176
277
  Example:
177
278
 
178
279
  ```erb
179
- <%= render(Bs5::ExpandableListGroupComponent.new(accordion: true, expandable: true) do |c| %>
280
+ <%= bs5_expandable_list_group(accordion: true, stretchable: true) do |c| %>
180
281
  ...
181
282
  <% end %>
182
283
  ```
183
284
 
285
+ Other options are used as HTML attributes of the list group element.
286
+
287
+
184
288
  ## Running tests
185
289
 
186
290
  ```bash
@@ -0,0 +1,9 @@
1
+ <%= tag.send(tag_name, **component_attributes) do %>
2
+ <% if items.any? %>
3
+ <% items.each do |item| %>
4
+ <%= item %>
5
+ <% end %>
6
+ <% else %>
7
+ <%= content %>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ class GroupComponent < ViewComponent::Base
6
+ renders_many :items, lambda { |options = {}|
7
+ options.merge!(parent_id: id, stretchable: stretchable?)
8
+ GroupItemComponent.new(**options)
9
+ }
10
+
11
+ attr_reader :options, :is_accordion, :is_stretchable, :tag_name
12
+
13
+ DEFAULT_TAG_NAME = :div
14
+
15
+ def initialize(options = {})
16
+ @is_accordion = options.delete(:accordion)
17
+ @is_stretchable = options.delete(:stretchable)
18
+ @id = options.delete(:id)
19
+ @tag_name = options.delete(:tag) || DEFAULT_TAG_NAME
20
+ @options = options
21
+ end
22
+
23
+ private
24
+
25
+ def id
26
+ @id || (accordion? && "list-group-#{object_id}")
27
+ end
28
+
29
+ def component_class
30
+ ['list-group'].tap do |arr|
31
+ arr << @options[:class]
32
+ end
33
+ end
34
+
35
+ def component_attributes
36
+ options.merge(id: id, class: component_class)
37
+ end
38
+
39
+ alias accordion? is_accordion
40
+ alias stretchable? is_stretchable
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,15 @@
1
+ <%= wrapper do %>
2
+ <% if simple_content? %>
3
+ <%= tag.send(tag_name, content, **component_attributes) %>
4
+ <% else %>
5
+ <%= tag.send(tag_name, **component_attributes) do %>
6
+ <div class="expandable-item-header">
7
+ <%= title %>
8
+ <%= actions %>
9
+ </div>
10
+ <%= tag.div(id: target_id, class: body_class, data: body_data_options) do %>
11
+ <%= body %>
12
+ <% end %>
13
+ <% end %>
14
+ <% end %>
15
+ <% end %>
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ class GroupItemComponent < ViewComponent::Base
6
+ DEFAULT_WRAPPER_TAG = :div
7
+ DEFAULT_TAG_NAME = :div
8
+ renders_one :title, lambda {
9
+ GroupItemHeader::TitleComponent.new(target_id: target_id, expanded: expanded?)
10
+ }
11
+ renders_one :actions, GroupItemHeader::ActionsComponent
12
+ renders_one :body
13
+
14
+ attr_reader :parent_id, :is_stretchable, :is_expanded, :tag_name, :wrapper_html, :options
15
+
16
+ def initialize(options = {})
17
+ @parent_id = options.delete(:parent_id)
18
+ @is_stretchable = options.delete(:stretchable)
19
+ @is_expanded = options.delete(:expanded)
20
+ @tag_name = options.delete(:tag) || DEFAULT_TAG_NAME
21
+ @wrapper_html = options.delete(:wrapper_html)
22
+ @options = options
23
+ end
24
+
25
+ private
26
+
27
+ def wrapper_html?
28
+ @wrapper_html.present?
29
+ end
30
+
31
+ def wrapper_tag
32
+ @wrapper_html.delete(:tag) || DEFAULT_WRAPPER_TAG
33
+ end
34
+
35
+ def wrapper(&block)
36
+ if wrapper_html?
37
+ tag.send(wrapper_tag, **wrapper_html, &block)
38
+ else
39
+ capture { block.call }
40
+ end
41
+ end
42
+
43
+ def simple_content?
44
+ title.blank? && body.blank? && actions.blank?
45
+ end
46
+
47
+ def target_id
48
+ "expandable-list-item-#{object_id}"
49
+ end
50
+
51
+ def body_data_options
52
+ {}.tap do |h|
53
+ h['bs-parent'] = "##{parent_id}" if parent_id
54
+ end
55
+ end
56
+
57
+ def component_data_options
58
+ {}.tap do |h|
59
+ h.merge!(stimulus_attributes) if stretchable?
60
+ end
61
+ end
62
+
63
+ def component_class
64
+ ['list-group-item'].tap do |arr|
65
+ arr << 'expandable-item' unless simple_content?
66
+ arr << 'stretchable-item'
67
+ arr << 'stretched' if !simple_content? && expanded?
68
+ end
69
+ end
70
+
71
+ def body_class
72
+ %w[expandable-item-body collapse].tap do |arr|
73
+ arr << 'show' if expanded?
74
+ end
75
+ end
76
+
77
+ def component_attributes
78
+ options.tap do |h|
79
+ h[:class] = component_class
80
+ h[:data] = component_data_options unless simple_content?
81
+ end
82
+ end
83
+
84
+ def stimulus_attributes
85
+ {
86
+ controller: stimulus_controller,
87
+ "#{stimulus_controller}-target": 'container',
88
+ "#{stimulus_controller}-stretched-class": 'stretched'
89
+ }
90
+ end
91
+
92
+ def stimulus_controller
93
+ 'stretchable-item'
94
+ end
95
+
96
+ alias stretchable? is_stretchable
97
+ alias expanded? is_expanded
98
+ end
99
+ end
100
+ end
@@ -1,6 +1,6 @@
1
1
  <div class="expandable-item-header-actions">
2
2
  <% if variable_actions? %>
3
- <%= tag.div(class: "expandable-item-header-actions-collaped") do %>
3
+ <%= tag.div(class: "expandable-item-header-actions-collapsed") do %>
4
4
  <%= collapsed %>
5
5
  <% end %>
6
6
  <%= tag.div(class: "expandable-item-header-actions-expanded") do %>
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ module GroupItemHeader
6
+ class ActionsComponent < ViewComponent::Base
7
+ renders_one :collapsed
8
+ renders_one :expanded
9
+
10
+ private
11
+
12
+ def variable_actions?
13
+ collapsed || expanded
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,6 +1,6 @@
1
- <%= tag.div(class: "expandable-item-header-title", data: { "bs-toggle": :collapse, "bs-target": "##{target_id}" } ) do %>
1
+ <%= tag.div(class: "expandable-item-header-title", data: { "bs-toggle": :collapse, "bs-target": "##{target_id}" }, aria: { expanded: expanded? } ) do %>
2
2
  <% if variable_title? %>
3
- <%= tag.div(class: "expandable-item-header-title-collaped") do %>
3
+ <%= tag.div(class: "expandable-item-header-title-collapsed") do %>
4
4
  <%= collapsed %>
5
5
  <% end %>
6
6
  <%= tag.div(class: "expandable-item-header-title-expanded") do %>
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bs5
4
+ module ExpandableList
5
+ module GroupItemHeader
6
+ class TitleComponent < ViewComponent::Base
7
+ renders_one :collapsed
8
+ renders_one :expanded
9
+
10
+ attr_reader :target_id, :is_expanded
11
+
12
+ def initialize(target_id:, expanded: false)
13
+ @target_id = target_id
14
+ @is_expanded = expanded
15
+ end
16
+
17
+ private
18
+
19
+ def variable_title?
20
+ collapsed || expanded
21
+ end
22
+
23
+ alias expanded? is_expanded
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ module Bs5ExpandableListGroup
2
+ module ViewComponentsHelper
3
+ def bs5_expandable_list_group(*args)
4
+ render ::Bs5::ExpandableList::GroupComponent.new(*args) do |c|
5
+ yield c if block_given?
6
+ end
7
+ end
8
+
9
+ def bs5_expandable_list_group_item(*args)
10
+ render ::Bs5::ExpandableList::GroupItemComponent.new(*args) do |c|
11
+ yield c if block_given?
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,6 +2,11 @@ module Bs5ExpandableListGroup
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Bs5ExpandableListGroup
4
4
 
5
+ # We don't want the developer to add the helper so we 'automate' this:
6
+ config.to_prepare do
7
+ ActionController::Base.helper(ViewComponentsHelper)
8
+ end
9
+
5
10
  config.generators do |g|
6
11
  g.test_framework :rspec
7
12
  g.assets false
@@ -1,3 +1,3 @@
1
1
  module Bs5ExpandableListGroup
2
- VERSION = '0.1.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -5,7 +5,7 @@ const HIDE_EVENT = "hide.bs.collapse";
5
5
 
6
6
  export default class extends Controller {
7
7
  static targets = ["container"];
8
- static classes = ["item", "stretched"];
8
+ static classes = ["stretched"];
9
9
 
10
10
  initialize() {
11
11
  this.onShow = this._onShow.bind(this);
@@ -14,7 +14,6 @@ export default class extends Controller {
14
14
  }
15
15
 
16
16
  connect() {
17
- this.containerTarget.classList.add(this.itemClass);
18
17
  this.contentNode.addEventListener(SHOW_EVENT, this.onShow);
19
18
  this.contentNode.addEventListener(HIDE_EVENT, this.onHide);
20
19
  }
@@ -3,7 +3,14 @@
3
3
  position: relative;
4
4
  cursor: pointer;
5
5
 
6
- &-actions {
6
+ &-title-expanded {
7
+ position: absolute;
8
+ top: 0;
9
+ right: 0;
10
+ left: 0;
11
+ }
12
+
13
+ &-actions-collapsed, &-actions-expanded {
7
14
  position: absolute;
8
15
  top: 0;
9
16
  right: 0;
@@ -12,17 +19,18 @@
12
19
 
13
20
  &:hover &-header-actions,
14
21
  &-header-title[aria-expanded="true"] &-header-title-expanded,
15
- &-header-title:not([aria-expanded="true"]) &-header-title-collaped,
22
+ &-header-title:not([aria-expanded="true"]) &-header-title-collapsed,
16
23
  &-header-title[aria-expanded="true"] + &-header-actions,
17
- &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-expanded {
18
- display: revert;
24
+ &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-expanded,
25
+ &-header-actions :focus-within {
26
+ visibility: visible;
19
27
  }
20
28
 
21
29
  &-header &-header-actions,
22
- &-header-title[aria-expanded="true"] &-header-title-collaped,
30
+ &-header-title[aria-expanded="true"] &-header-title-collapsed,
23
31
  &-header-title:not([aria-expanded="true"]) &-header-title-expanded,
24
32
  &-header-actions-expanded,
25
- &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-collaped {
26
- display: none;
33
+ &-header-title[aria-expanded="true"] + &-header-actions &-header-actions-collapsed {
34
+ visibility: hidden;
27
35
  }
28
36
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bs5_expandable_list_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Baselier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-01 00:00:00.000000000 Z
11
+ date: 2021-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -86,7 +86,9 @@ dependencies:
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
- description: Description of Bs5ExpandableListGroup.
89
+ description: Bootstrap 5 expandable list group is a Ruby on Rails engine and gives
90
+ you a simple API for creating expandable and stretchable list groups. A bit like
91
+ Bootstrap 5's Accordion, Collapse and List group components combined.
90
92
  email:
91
93
  - patrick.baselier@gmail.com
92
94
  executables: []
@@ -98,16 +100,17 @@ files:
98
100
  - Rakefile
99
101
  - app/assets/config/bs5_expandable_list_group_manifest.js
100
102
  - app/assets/stylesheets/bs5_expandable_list_group/application.css
101
- - app/components/bs5/expandable_list_group_component.html.erb
102
- - app/components/bs5/expandable_list_group_component.rb
103
- - app/components/bs5/expandable_list_item_component.html.erb
104
- - app/components/bs5/expandable_list_item_component.rb
105
- - app/components/bs5/expandable_list_item_header_actions_component.html.erb
106
- - app/components/bs5/expandable_list_item_header_actions_component.rb
107
- - app/components/bs5/expandable_list_item_header_title_component.html.erb
108
- - app/components/bs5/expandable_list_item_header_title_component.rb
103
+ - app/components/bs5/expandable_list/group_component.html.erb
104
+ - app/components/bs5/expandable_list/group_component.rb
105
+ - app/components/bs5/expandable_list/group_item_component.html.erb
106
+ - app/components/bs5/expandable_list/group_item_component.rb
107
+ - app/components/bs5/expandable_list/group_item_header/actions_component.html.erb
108
+ - app/components/bs5/expandable_list/group_item_header/actions_component.rb
109
+ - app/components/bs5/expandable_list/group_item_header/title_component.html.erb
110
+ - app/components/bs5/expandable_list/group_item_header/title_component.rb
109
111
  - app/controllers/bs5_expandable_list_group/application_controller.rb
110
112
  - app/helpers/bs5_expandable_list_group/application_helper.rb
113
+ - app/helpers/bs5_expandable_list_group/view_components_helper.rb
111
114
  - app/jobs/bs5_expandable_list_group/application_job.rb
112
115
  - app/mailers/bs5_expandable_list_group/application_mailer.rb
113
116
  - app/models/bs5_expandable_list_group/application_record.rb
@@ -129,7 +132,7 @@ licenses:
129
132
  metadata:
130
133
  homepage_uri: https://github.com/bazzel/Bs5ExpandableListGroup
131
134
  source_code_uri: https://github.com/bazzel/Bs5ExpandableListGroup
132
- changelog_uri: https://github.com/bazzel/Bs5ExpandableListGroup/CHANGELOG.md
135
+ changelog_uri: https://github.com/bazzel/Bs5ExpandableListGroup/blob/main/CHANGELOG.md
133
136
  post_install_message:
134
137
  rdoc_options: []
135
138
  require_paths:
@@ -148,5 +151,6 @@ requirements: []
148
151
  rubygems_version: 3.2.3
149
152
  signing_key:
150
153
  specification_version: 4
151
- summary: Summary of Bs5ExpandableListGroup.
154
+ summary: Rails engine for creating expandable and stretchable list groups with Bootstrap
155
+ 5
152
156
  test_files: []
@@ -1,5 +0,0 @@
1
- <%= tag.div(id: accordion? && id, class: component_class) do %>
2
- <% items.each do |item| %>
3
- <%= item %>
4
- <% end %>
5
- <% end %>
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListGroupComponent < ViewComponent::Base
5
- renders_many :items, lambda {
6
- ExpandableListItemComponent.new(parent_id: accordion? && id, stretchable: stretchable?)
7
- }
8
-
9
- attr_reader :accordion, :stretchable
10
-
11
- def initialize(options = {})
12
- @accordion = options.delete(:accordion)
13
- @stretchable = options.delete(:stretchable)
14
- @id = options[:id]
15
- @options = options
16
- end
17
-
18
- private
19
-
20
- def id
21
- @id || "list-group-#{object_id}"
22
- end
23
-
24
- def component_class
25
- class_names = ['list-group']
26
- class_names << @options[:class]
27
- class_names
28
- end
29
-
30
- alias accordion? accordion
31
- alias stretchable? stretchable
32
- end
33
- end
@@ -1,9 +0,0 @@
1
- <%= tag.div(class: "list-group-item expandable-item", data: component_data_options) do %>
2
- <div class="expandable-item-header">
3
- <%= title %>
4
- <%= actions %>
5
- </div>
6
- <%= tag.div(id: target_id, class: "expandable-item-body collapse", data: body_data_options) do %>
7
- <%= body %>
8
- <% end %>
9
- <% end %>
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemComponent < ViewComponent::Base
5
- renders_one :title, lambda {
6
- ExpandableListItemHeaderTitleComponent.new(target_id: target_id)
7
- }
8
- renders_one :actions, ExpandableListItemHeaderActionsComponent
9
- renders_one :body
10
-
11
- attr_reader :parent_id, :stretchable
12
-
13
- def initialize(options = {})
14
- @parent_id = options.delete(:parent_id)
15
- @stretchable = options.delete(:stretchable)
16
- @options = options
17
- end
18
-
19
- private
20
-
21
- def target_id
22
- "expandable-list-item-#{object_id}"
23
- end
24
-
25
- def body_data_options
26
- {}.tap do |h|
27
- h['bs-parent'] = "##{parent_id}" if parent_id
28
- end
29
- end
30
-
31
- def component_data_options
32
- {}.tap do |h|
33
- h.merge!(stimulus_attributes) if stretchable?
34
- end
35
- end
36
-
37
- def stimulus_attributes
38
- {
39
- controller: stimulus_controller,
40
- "#{stimulus_controller}-target": 'container',
41
- "#{stimulus_controller}-item-class": 'stretchable-item',
42
- "#{stimulus_controller}-stretched-class": 'stretched'
43
- }
44
- end
45
-
46
- def stimulus_controller
47
- 'stretchable-item'
48
- end
49
-
50
- alias stretchable? stretchable
51
- end
52
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemHeaderActionsComponent < ViewComponent::Base
5
- renders_one :collapsed
6
- renders_one :expanded
7
-
8
- private
9
-
10
- def variable_actions?
11
- collapsed || expanded
12
- end
13
- end
14
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bs5
4
- class ExpandableListItemHeaderTitleComponent < ViewComponent::Base
5
- renders_one :collapsed
6
- renders_one :expanded
7
-
8
- attr_reader :target_id
9
-
10
- def initialize(target_id:)
11
- @target_id = target_id
12
- end
13
-
14
- private
15
-
16
- def variable_title?
17
- collapsed || expanded
18
- end
19
- end
20
- end