bs5_expandable_list_group 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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