bulma-phlex 0.3.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.
- checksums.yaml +4 -4
- data/README.md +132 -13
- data/lib/bulma-phlex.rb +9 -11
- data/lib/bulma_phlex/rails/card_helper.rb +34 -0
- data/lib/bulma_phlex/rails/table_helper.rb +24 -0
- data/lib/bulma_phlex/railtie.rb +17 -0
- data/lib/bulma_phlex/version.rb +1 -1
- data/lib/components/bulma/card.rb +6 -19
- data/lib/components/bulma/dropdown.rb +1 -1
- data/lib/components/bulma/level.rb +1 -1
- data/lib/components/bulma/navigation_bar.rb +2 -2
- data/lib/components/bulma/navigation_bar_dropdown.rb +1 -1
- data/lib/components/bulma/pagination.rb +1 -1
- data/lib/components/bulma/tab_components/content.rb +30 -0
- data/lib/components/bulma/tab_components/tab.rb +44 -0
- data/lib/components/bulma/table.rb +50 -4
- data/lib/components/bulma/tabs.rb +72 -39
- metadata +20 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09f6b84b1564059a0db9f00ee35338b5c1acfc7944fe2a596463ef8c01e22e63'
|
4
|
+
data.tar.gz: e21e0bfd149428895ba829718808185dc37ecb84e796f523fb2d7896540e07be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9da14ce4cb01f3121f7e2cd8fd3ba8dc7e877976c9913e5cfac07a6c3589404bf62a503ae076b139fc30cacf6436f132e78d1dcbc83588372183caf8d9194a27
|
7
|
+
data.tar.gz: 1eb2979a4cfbe5dd020e7260ba999ef0d762b14cc6f26dadef3ba75edabd2d039fe0521c8babdb4204247b6d540e7dca63d5712b408e003b2a88f3f785c5c770
|
data/README.md
CHANGED
@@ -4,7 +4,23 @@
|
|
4
4
|
|
5
5
|
# Bulma Components Built with Phlex
|
6
6
|
|
7
|
-
This gem provides a set of ready-to-use
|
7
|
+
This gem provides a set of ready-to-use [Phlex](https://github.com/phlex-ruby/phlex) components for common [Bulma](https://bulma.io/) components and elements, making it easy to build beautiful, responsive interfaces with a clean, Ruby-focused API.
|
8
|
+
|
9
|
+
## Table of Contents
|
10
|
+
|
11
|
+
- [Installation](#installation)
|
12
|
+
- [Usage](#usage)
|
13
|
+
- [Card](#card)
|
14
|
+
- [Dropdown](#dropdown)
|
15
|
+
- [Level](#level)
|
16
|
+
- [NavigationBar](#navigationbar)
|
17
|
+
- [Pagination](#pagination)
|
18
|
+
- [Table](#table)
|
19
|
+
- [Tabs](#tabs)
|
20
|
+
- [Development](#development)
|
21
|
+
- [Contributing](#contributing)
|
22
|
+
- [License](#license)
|
23
|
+
- [Credits](#credits)
|
8
24
|
|
9
25
|
## Installation
|
10
26
|
|
@@ -54,7 +70,7 @@ Use the Phlex components in your Rails views or any Ruby application that suppor
|
|
54
70
|
[Cards](https://bulma.io/documentation/components/card/) are flexible containers that can display various types of content including headers and content sections.
|
55
71
|
|
56
72
|
```ruby
|
57
|
-
|
73
|
+
Bulma::Card() do |card|
|
58
74
|
card.head("Card Title")
|
59
75
|
card.content do
|
60
76
|
"This is some card content"
|
@@ -62,12 +78,27 @@ render Components::Bulma::Card.new do |card|
|
|
62
78
|
end
|
63
79
|
```
|
64
80
|
|
81
|
+
#### Rails Feature: Turbo Frame Content
|
82
|
+
|
83
|
+
When the `turbo-rails` and `phlex-rails` gems are installed, the Card component also provides method `turbo_frame_content`, which allows the content to be deferred to a turbo frame. The method accepts the same parameters as [the Turbo Rails helper method `turbo_frame_tag`](https://github.com/hotwired/turbo-rails?tab=readme-ov-file#decompose-with-turbo-frames), with the addition of the following two attributes:
|
84
|
+
|
85
|
+
- pending_message (default: "Loading...")
|
86
|
+
- pending_icon (default: "fas fa-spinner fa-pulse")
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
Bulma::Card() do |card|
|
90
|
+
card.head("Product Info")
|
91
|
+
card.turbo_frame_content("product", src: product_path(@product), pending_message: "Loading product...")
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
|
65
96
|
### Dropdown
|
66
97
|
|
67
98
|
The [Dropdown](https://bulma.io/documentation/components/dropdown/) component provides a flexible dropdown menu for navigation or actions. It supports both click-to-toggle (default, requires a Stimulus controller) and hoverable modes, as well as alignment and icon customization.
|
68
99
|
|
69
100
|
```ruby
|
70
|
-
|
101
|
+
Bulma::Dropdown("Next Actions...") do |dropdown|
|
71
102
|
dropdown.link "View Profile", "/profile"
|
72
103
|
dropdown.link "Go to Settings", "/settings"
|
73
104
|
dropdown.divider
|
@@ -96,7 +127,7 @@ end
|
|
96
127
|
The [Level](https://bulma.io/documentation/layout/level/) component provides a flexible horizontal layout system with left and right alignment.
|
97
128
|
|
98
129
|
```ruby
|
99
|
-
|
130
|
+
Bulma::Level() do |level|
|
100
131
|
level.left do
|
101
132
|
button(class: "button") { "Left" }
|
102
133
|
end
|
@@ -115,7 +146,7 @@ end
|
|
115
146
|
The [NavigationBar](https://bulma.io/documentation/components/navbar/) component provides a responsive navigation header with support for branding, navigation links, and dropdown menus.
|
116
147
|
|
117
148
|
```ruby
|
118
|
-
|
149
|
+
Bulma::NavigationBar() do |navbar|
|
119
150
|
navbar.brand_item "My App", "/"
|
120
151
|
|
121
152
|
navbar.left do |menu|
|
@@ -145,26 +176,23 @@ The [Pagination](https://bulma.io/documentation/components/pagination/) componen
|
|
145
176
|
@products = Product.page(params[:page]).per(20)
|
146
177
|
|
147
178
|
# In the view:
|
148
|
-
|
179
|
+
Bulma::Pagination(@products, ->(page) { products_path(page: page) })
|
149
180
|
```
|
150
181
|
|
151
182
|
### Table
|
152
183
|
|
153
184
|
The [Table](https://bulma.io/documentation/elements/table/) component provides a way to display data in rows and columns with customizable headers and formatting options.
|
154
185
|
|
155
|
-
It requires a Hotwired Stimulus controller to manage the tabs and the content. By default, the controller name is assumed to be `bulma--tabs`, but can be overridden with the constructor keyword argument `stimulus_controller`. Stimulus targets and actions are added to the component.
|
156
|
-
|
157
186
|
```ruby
|
158
187
|
users = User.all
|
159
188
|
|
160
|
-
|
189
|
+
Bulma::Table(users, fullwidth: true, hoverable: true) do |table|
|
161
190
|
table.column "Name" do |user|
|
162
191
|
user.full_name
|
163
192
|
end
|
164
193
|
|
165
|
-
|
166
|
-
|
167
|
-
end
|
194
|
+
# use the symbol-to-proc shortcut!
|
195
|
+
table.column "Email", &:email
|
168
196
|
|
169
197
|
table.column "Actions" do |user|
|
170
198
|
link_to "Edit", edit_user_path(user), class: "button is-small"
|
@@ -172,12 +200,85 @@ render Components::Bulma::Table.new(users) do |table|
|
|
172
200
|
end
|
173
201
|
```
|
174
202
|
|
203
|
+
**Constructor Keyword Arguments:**
|
204
|
+
|
205
|
+
- `rows`: the data for the table as an enumerable (anything that responds to `each`)
|
206
|
+
- `id`: the Id for the table element (defaults to "table")
|
207
|
+
- `bordered`: adds the `is-bordered` class (boolean, defaults to false)
|
208
|
+
- `striped`: adds the `is-striped` class (boolean, defaults to false)
|
209
|
+
- `narrow`: adds the `is-narrow` class (boolean, defaults to false)
|
210
|
+
- `hoverable`: adds the `is-hoverable` class (boolean, defaults to false)
|
211
|
+
- `fullwidth`: adds the `is-fullwidth` class (boolean, defaults to false)
|
212
|
+
|
213
|
+
**Arguments for `column` Method:**
|
214
|
+
|
215
|
+
The `column` method takes the column name and any html attributes to be assigned to the table cell element. The block will be called with the row as the parameter.
|
216
|
+
|
217
|
+
#### Additional Column Types
|
218
|
+
|
219
|
+
Instead of calling `column`, you can also invoke the following methods to add amount, date, and icon columns:
|
220
|
+
|
221
|
+
**Arguments for `amount_column` (Rails only):**
|
222
|
+
|
223
|
+
- name: content for the `th` element
|
224
|
+
- `currency` (keyword): options that will be passed to [Rails helper number_to_currency](https://api.rubyonrails.org/classes/ActiveSupport/NumberHelper.html#method-i-number_to_currency, uses Rails defaults)
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
table.amount_column("Payment Amount") { |row| row.payment_amount }
|
228
|
+
table.amount_column("Total", currency: { unit: "€" }, class: "is-bold", &:total)
|
229
|
+
```
|
230
|
+
|
231
|
+
**Arguments for `date_column`:**
|
232
|
+
|
233
|
+
- name: content for the `th` element
|
234
|
+
- `format` (keyword): the formatting options (will be passed to `strftime`, defaults to "%Y-%m-%d")
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
table.date_column("Due Date", format: "%B %d, %Y") { |row| row.due_date }
|
238
|
+
```
|
239
|
+
|
240
|
+
**Arguments for `conditional_icon`:**
|
241
|
+
|
242
|
+
The icon column is intended to show a boolean flag: a yes / no or an on / off. When the value is true the icon shows and when the value is false it does not.
|
243
|
+
|
244
|
+
- name: content for the `th` element
|
245
|
+
- `icon_class` (keyword): the icon to show (defaults to the Font Awesome check mark: "fas fa-check")
|
246
|
+
|
247
|
+
```ruby
|
248
|
+
table.conditional_icon("Completed?", &:complete)
|
249
|
+
table.conditional_icon("Approved?", icon_class: "fas fa-thumbs-up") { |row| row.status == "Approved" }
|
250
|
+
```
|
251
|
+
|
252
|
+
#### Pagination
|
253
|
+
|
254
|
+
If the table should be paginated, invoke method `paginate` with a block that will return a path given a page number.
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
table.paginate do |page_number|
|
258
|
+
products_path(page: { number: page_number })
|
259
|
+
end
|
260
|
+
```
|
261
|
+
|
262
|
+
In order to support pagination, the `rows` argument passed into the constructor must repond with integers to the following:
|
263
|
+
|
264
|
+
- current_page
|
265
|
+
- total_pages
|
266
|
+
- per_page
|
267
|
+
- total_count
|
268
|
+
- previous_page (can be nil)
|
269
|
+
- next_page (can be nil)
|
270
|
+
|
271
|
+
This generates the [Bulma pagination](https://bulma.io/documentation/components/pagination/) component, providing navigation controls for paginated content.
|
272
|
+
|
273
|
+
|
175
274
|
### Tabs
|
176
275
|
|
177
276
|
The [Tabs](https://bulma.io/documentation/components/tabs/) component provides a way to toggle between different content sections using tabbed navigation, with support for icons and active state management.
|
178
277
|
|
278
|
+
Behavior of the tabs can be driven by the data attributes, which are assigned by the object passed in as the `data_attributes_builder`. By default, this will use the `StimulusDataAttributes` class with the controller name `bulma--tabs`. The controller is not provided by this library, but you can create your own Stimulus controller to handle the tab switching logic. Here is [an implementation of a Stimulus controller for Bulma tabs](https://github.com/RockSolt/bulma-rails-helpers/blob/main/app/javascript/controllers/bulma/tabs_controller.js).
|
279
|
+
|
179
280
|
```ruby
|
180
|
-
|
281
|
+
Bulma::Tabs(tabs_class: "is-boxed", contents_class: "ml-4") do |tabs|
|
181
282
|
tabs.tab(id: "profile", title: "Profile", active: true) do
|
182
283
|
"Profile content goes here"
|
183
284
|
end
|
@@ -192,6 +293,20 @@ render Components::Bulma::Tabs.new do |tabs|
|
|
192
293
|
end
|
193
294
|
```
|
194
295
|
|
296
|
+
**Constructor Keyword Arguments:**
|
297
|
+
|
298
|
+
- `tabs_class`: Classes to be added to the tabs div, such as `is-boxed`, `is-medium`, `is-centered`, or `is-toggle`.
|
299
|
+
- `contents_class`: Classes added to the div that wraps the content (no Bulma related tabs functionality here, just a hook).
|
300
|
+
- `data_attributes_builder`: Builder object that responds to `for_container`, `for_tab`, and `for_content` (with the latter two receiving the tab `id`). See the default `StimulusDataAttributes` for an example.
|
301
|
+
|
302
|
+
**Keyword Arguments for `tab` Method:**
|
303
|
+
|
304
|
+
- `id`: The id to be assigned to the content. The tab will be assigned the same id with the suffix `-tab`.
|
305
|
+
- `title`: The name on the tab.
|
306
|
+
- `active`: Adds the `is-active` class to the tab and shows the related content. Non-active content is assigned the `is-hidden` class. Defaults to `false`.
|
307
|
+
- `icon`: Specify an optional icon class.
|
308
|
+
|
309
|
+
|
195
310
|
## Development
|
196
311
|
|
197
312
|
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -205,3 +320,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/RockSo
|
|
205
320
|
## License
|
206
321
|
|
207
322
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
323
|
+
|
324
|
+
## Credits
|
325
|
+
|
326
|
+
This leverages the [Bulma CSS library](https://bulma.io/documentation/) and [Phlex](https://www.phlex.fun/) but is not endorsed or certified by either. We are fans of the both and this makes using them together easier.
|
data/lib/bulma-phlex.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "phlex"
|
4
3
|
require "bulma_phlex/version"
|
4
|
+
require "zeitwerk"
|
5
|
+
require "phlex"
|
6
|
+
|
7
|
+
loader = Zeitwerk::Loader.new
|
8
|
+
loader.tag = "bulma-phlex"
|
9
|
+
loader.push_dir(File.dirname(__FILE__))
|
10
|
+
loader.ignore(__FILE__)
|
11
|
+
loader.setup
|
5
12
|
|
6
|
-
require "
|
7
|
-
require "components/bulma/base"
|
8
|
-
require "components/bulma/card"
|
9
|
-
require "components/bulma/dropdown"
|
10
|
-
require "components/bulma/level"
|
11
|
-
require "components/bulma/navigation_bar_dropdown"
|
12
|
-
require "components/bulma/navigation_bar"
|
13
|
-
require "components/bulma/pagination"
|
14
|
-
require "components/bulma/table"
|
15
|
-
require "components/bulma/tabs"
|
13
|
+
require "bulma_phlex/railtie" if defined?(Rails::Railtie)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BulmaPhlex
|
4
|
+
module Rails
|
5
|
+
# # Card Helper
|
6
|
+
#
|
7
|
+
# This module provides method `turbo_frame_content` to create a card with a turbo frame as its content.
|
8
|
+
module CardHelper
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
13
|
+
end
|
14
|
+
|
15
|
+
# Renders a Bulma-styled card with a Turbo Frame as its content. This uses the same signatures as
|
16
|
+
# `turbo_frame_tag`, with the addition of two optional attributes: `pending_message` and `pending_icon`.
|
17
|
+
#
|
18
|
+
# The two pending attributes have the following defaults:
|
19
|
+
# - pending_message: "Loading..."
|
20
|
+
# - pending_icon: "fas fa-spinner fa-pulse"
|
21
|
+
def turbo_frame_content(*ids, src: nil, target: nil, **attributes)
|
22
|
+
pending_message = attributes.delete(:pending_message) || "Loading..."
|
23
|
+
pending_icon = attributes.delete(:pending_icon) || "fas fa-spinner fa-pulse"
|
24
|
+
|
25
|
+
content do
|
26
|
+
turbo_frame_tag ids, src: src, target: target, **attributes do
|
27
|
+
span(class: "icon") { i class: pending_icon }
|
28
|
+
span { plain pending_message }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BulmaPhlex
|
4
|
+
module Rails
|
5
|
+
# # Table Helper
|
6
|
+
#
|
7
|
+
# This module provides method `amount_column` to create an amount column in a table.
|
8
|
+
module TableHelper
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
include Phlex::Rails::Helpers::NumberToCurrency
|
13
|
+
end
|
14
|
+
|
15
|
+
def amount_column(header, currency: {}, **html_attributes, &content)
|
16
|
+
html_attributes[:class] = [html_attributes[:class], "has-text-right"].compact.join(" ")
|
17
|
+
|
18
|
+
column(header, **html_attributes) do |row|
|
19
|
+
number_to_currency(content.call(row), **currency)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BulmaPhlex
|
4
|
+
# # Railtie for BulmaPhlex
|
5
|
+
#
|
6
|
+
# This Railtie adds Rails-specific features to the BulmaPhlex library.
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
initializer "bulma_phlex" do
|
9
|
+
ActiveSupport.on_load(:action_view) do
|
10
|
+
if defined?(Phlex::Rails)
|
11
|
+
Components::Bulma::Card.include(BulmaPhlex::Rails::CardHelper) if defined?(Turbo)
|
12
|
+
Components::Bulma::Table.include(BulmaPhlex::Rails::TableHelper)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/bulma_phlex/version.rb
CHANGED
@@ -11,7 +11,7 @@ module Components
|
|
11
11
|
# ## Example
|
12
12
|
#
|
13
13
|
# ```ruby
|
14
|
-
#
|
14
|
+
# Bulma::Card() do |card|
|
15
15
|
# card.head("Card Title")
|
16
16
|
# card.content do
|
17
17
|
# "This is some card content"
|
@@ -19,6 +19,11 @@ module Components
|
|
19
19
|
# end
|
20
20
|
# ```
|
21
21
|
#
|
22
|
+
# ## Rails Feature: Turbo Frame Content
|
23
|
+
#
|
24
|
+
# If the project includes Rails and the Phlex::Rails gem, the `BulmaPhlex::Rails::CardHelper` module
|
25
|
+
# provides a `turbo_frame_content` method to create a card with a turbo frame
|
26
|
+
# as its content. This allows for dynamic loading of card content.
|
22
27
|
class Card < Components::Bulma::Base
|
23
28
|
def view_template(&)
|
24
29
|
div(class: "card", &)
|
@@ -35,24 +40,6 @@ module Components
|
|
35
40
|
div(class: "content", &)
|
36
41
|
end
|
37
42
|
end
|
38
|
-
|
39
|
-
if defined?(Phlex::Rails)
|
40
|
-
include Phlex::Rails::Helpers::TurboFrameTag
|
41
|
-
|
42
|
-
# this copies the signature of the turbo_frame_tag helper,
|
43
|
-
# with the addition of a pending_message attribute
|
44
|
-
def turbo_frame_content(*ids, src: nil, target: nil, **attributes)
|
45
|
-
pending_message = attributes.delete(:pending_message) || "Loading..."
|
46
|
-
pending_icon = attributes.delete(:pending_icon) || "fas fa-spinner fa-pulse"
|
47
|
-
|
48
|
-
content do
|
49
|
-
turbo_frame_tag ids, src: src, target: target, **attributes do
|
50
|
-
span(class: "icon") { i class: pending_icon }
|
51
|
-
span { plain pending_message }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
43
|
end
|
57
44
|
end
|
58
45
|
end
|
@@ -25,7 +25,7 @@ module Components
|
|
25
25
|
# ## Example
|
26
26
|
#
|
27
27
|
# ```ruby
|
28
|
-
#
|
28
|
+
# Bulma::Dropdown("Next Actions...") do |dropdown|
|
29
29
|
# dropdown.link "View Profile", "/profile"
|
30
30
|
# dropdown.link "Go to Settings", "/settings"
|
31
31
|
# dropdown.divider
|
@@ -11,7 +11,7 @@ module Components
|
|
11
11
|
# ## Example
|
12
12
|
#
|
13
13
|
# ```ruby
|
14
|
-
#
|
14
|
+
# Bulma::NavigationBar() do |navbar|
|
15
15
|
# navbar.brand do
|
16
16
|
# a(href: "/", class: "navbar-item") { "My App" }
|
17
17
|
# end
|
@@ -26,7 +26,7 @@ module Components
|
|
26
26
|
#
|
27
27
|
# div(class: "navbar-item has-dropdown is-hoverable") do
|
28
28
|
# a(class: "navbar-link") { "Account" }
|
29
|
-
#
|
29
|
+
# Bulma::NavigationBarDropdown() do |dropdown|
|
30
30
|
# dropdown.item "Sign In", "/login"
|
31
31
|
# dropdown.item "Register", "/register"
|
32
32
|
# end
|
@@ -19,7 +19,7 @@ module Components
|
|
19
19
|
# @products = Product.page(params[:page]).per(20)
|
20
20
|
#
|
21
21
|
# # In the view:
|
22
|
-
#
|
22
|
+
# Bulma::Pagination(@products, ->(page) { products_path(page: page) })
|
23
23
|
# ```
|
24
24
|
#
|
25
25
|
class Pagination < Components::Bulma::Base
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
module TabComponents
|
6
|
+
# # Content
|
7
|
+
#
|
8
|
+
# This component represents a single content section within the Bulma Tabs component.
|
9
|
+
#
|
10
|
+
# ## Arguments:
|
11
|
+
# - `id`: Unique identifier for the content.
|
12
|
+
# - `active`: Boolean indicating if the content is currently active.
|
13
|
+
# - `data_attributes_proc`: A proc that generates data attributes for the content.
|
14
|
+
class Content < Components::Bulma::Base
|
15
|
+
def initialize(id:, active:, data_attributes_proc: nil)
|
16
|
+
@id = id
|
17
|
+
@active = active
|
18
|
+
@data_attributes = data_attributes_proc ||
|
19
|
+
Components::Bulma::Tabs::StimulusDataAttributes.new("bulma--tabs").method(:for_content)
|
20
|
+
end
|
21
|
+
|
22
|
+
def view_template(&)
|
23
|
+
div(id: @id,
|
24
|
+
class: @active ? "" : "is-hidden",
|
25
|
+
data: @data_attributes.call(@id), &)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Components
|
4
|
+
module Bulma
|
5
|
+
module TabComponents
|
6
|
+
# # Tab
|
7
|
+
#
|
8
|
+
# This component represents a single tab within the Bulma Tabs component.
|
9
|
+
#
|
10
|
+
# The component can be used if you need to create or update a tab dynamically.
|
11
|
+
#
|
12
|
+
# ## Arguments
|
13
|
+
#
|
14
|
+
# - `id`: Unique identifier for the tab.
|
15
|
+
# - `title`: The text displayed on the tab.
|
16
|
+
# - `icon`: Optional icon to display on the tab.
|
17
|
+
# - `active`: Boolean indicating if the tab is currently active.
|
18
|
+
# - `data_attributes_proc`: A proc that generates data attributes for the tab.
|
19
|
+
class Tab < Components::Bulma::Base
|
20
|
+
def initialize(id:, title:, icon:, active:,
|
21
|
+
data_attributes_proc: Components::Bulma::Tabs::StimulusDataAttributes.new("bulma--tabs").method(:for_tab))
|
22
|
+
@id = id
|
23
|
+
@title = title
|
24
|
+
@icon = icon
|
25
|
+
@active = active
|
26
|
+
@data_attributes_proc = data_attributes_proc
|
27
|
+
end
|
28
|
+
|
29
|
+
def view_template(&)
|
30
|
+
li(
|
31
|
+
id: "#{@id}-tab",
|
32
|
+
data: @data_attributes_proc.call(@id),
|
33
|
+
class: @active ? "is-active" : ""
|
34
|
+
) do
|
35
|
+
a do
|
36
|
+
icon_span(@icon, "mr-1") if @icon
|
37
|
+
span { @title }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -13,7 +13,7 @@ module Components
|
|
13
13
|
# ```ruby
|
14
14
|
# users = User.all
|
15
15
|
#
|
16
|
-
#
|
16
|
+
# Bulma::Table(users) do |table|
|
17
17
|
# table.column "Name" do |user|
|
18
18
|
# user.full_name
|
19
19
|
# end
|
@@ -29,16 +29,16 @@ module Components
|
|
29
29
|
# ```
|
30
30
|
#
|
31
31
|
class Table < Components::Bulma::Base
|
32
|
-
def initialize(rows,
|
33
|
-
@id = id || rows.first&.model_name&.plural
|
32
|
+
def initialize(rows, id_or_options = nil, **options)
|
34
33
|
@rows = rows
|
34
|
+
@id, @table_class = parse_id_and_options(id_or_options, options, rows)
|
35
35
|
@columns = []
|
36
36
|
end
|
37
37
|
|
38
38
|
def view_template(&)
|
39
39
|
vanish(&)
|
40
40
|
|
41
|
-
table(id: @id, class:
|
41
|
+
table(id: @id, class: @table_class) do
|
42
42
|
thead do
|
43
43
|
@columns.each do |column|
|
44
44
|
table_header(column)
|
@@ -63,12 +63,58 @@ module Components
|
|
63
63
|
@columns << { header:, html_attributes:, content: }
|
64
64
|
end
|
65
65
|
|
66
|
+
def date_column(header, format: "%Y-%m-%d", **html_attributes, &content)
|
67
|
+
column(header, **html_attributes) do |row|
|
68
|
+
content.call(row)&.strftime(format)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def conditional_icon(header, icon_class: "fas fa-check", **html_attributes, &content)
|
73
|
+
html_attributes[:class] = [html_attributes[:class], "has-text-centered"].compact.join(" ")
|
74
|
+
|
75
|
+
column(header, **html_attributes) do |row|
|
76
|
+
icon_span(icon_class) if content.call(row)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
66
80
|
def paginate(&path_builder)
|
67
81
|
@path_builder = path_builder
|
68
82
|
end
|
69
83
|
|
70
84
|
private
|
71
85
|
|
86
|
+
def parse_id_and_options(id_or_options, options, rows)
|
87
|
+
if id_or_options.is_a?(String)
|
88
|
+
id = id_or_options
|
89
|
+
opts = options
|
90
|
+
else
|
91
|
+
opts = (id_or_options || {}).merge(options)
|
92
|
+
id = opts.delete(:id) || id_from_array_or_arel(rows)
|
93
|
+
end
|
94
|
+
table_class = "table #{parse_table_classes(opts)}"
|
95
|
+
[id, table_class]
|
96
|
+
end
|
97
|
+
|
98
|
+
def id_from_array_or_arel(rows)
|
99
|
+
if rows.respond_to? :model
|
100
|
+
rows.model.model_name.plural
|
101
|
+
elsif rows.empty?
|
102
|
+
"table"
|
103
|
+
else
|
104
|
+
rows.first.model_name.plural
|
105
|
+
end
|
106
|
+
rescue StandardError
|
107
|
+
"table"
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_table_classes(options)
|
111
|
+
options.slice(*%i[bordered striped narrow hoverable fullwidth])
|
112
|
+
.transform_keys { |key| "is-#{key}" }
|
113
|
+
.select { |_, value| value }
|
114
|
+
.keys
|
115
|
+
.join(" ")
|
116
|
+
end
|
117
|
+
|
72
118
|
# this derives a th class from the column html attributes
|
73
119
|
# perhaps a better way would be pre-defined pairs?
|
74
120
|
def table_header(column)
|
@@ -8,10 +8,20 @@ module Components
|
|
8
8
|
# interface, providing a way to toggle between different content sections using
|
9
9
|
# tabbed navigation. Includes support for icons and active state management.
|
10
10
|
#
|
11
|
+
# Classes can be assigned to either the tabs or contents wrappers. The tabs div is where Bulma
|
12
|
+
# options such as `is-boxed`, `is-centered`, or `is-small` can be added.
|
13
|
+
#
|
14
|
+
# Use method `right_content` to add content to the right of the tabs, such as a button.
|
15
|
+
#
|
16
|
+
# The tabs behavior can be managed by the data attributes provided by the `data_attributes_builder` argument. By
|
17
|
+
# default, this will use the `StimulusDataAttributes` class with the controller name `bulma--tabs`. That controller
|
18
|
+
# is not provided by this library, but you can create your own Stimulus controller to handle the tab switching
|
19
|
+
# logic. Here is [an implementation of a Stimulus controller for Bulma tabs](https://github.com/RockSolt/bulma-rails-helpers/blob/main/app/javascript/controllers/bulma/tabs_controller.js).
|
20
|
+
#
|
11
21
|
# ## Example
|
12
22
|
#
|
13
23
|
# ```ruby
|
14
|
-
#
|
24
|
+
# Bulma::Tabs() do |tabs|
|
15
25
|
# tabs.tab(id: "profile", title: "Profile", active: true) do
|
16
26
|
# "Profile content goes here"
|
17
27
|
# end
|
@@ -27,59 +37,82 @@ module Components
|
|
27
37
|
# ```
|
28
38
|
#
|
29
39
|
class Tabs < Components::Bulma::Base
|
30
|
-
|
31
|
-
|
40
|
+
StimulusDataAttributes = Data.define(:stimulus_controller) do
|
41
|
+
def for_container
|
42
|
+
{ controller: stimulus_controller }
|
43
|
+
end
|
32
44
|
|
33
|
-
|
34
|
-
|
45
|
+
def for_tab(id)
|
46
|
+
{
|
47
|
+
target_key => "tab",
|
48
|
+
tab_content: id,
|
49
|
+
action: "click->#{stimulus_controller}#showTabContent"
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def for_content(_id)
|
54
|
+
{ target_key => "content" }
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def target_key
|
60
|
+
"#{stimulus_controller}-target"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize(id: nil, tabs_class: nil, contents_class: nil,
|
65
|
+
data_attributes_builder: StimulusDataAttributes.new("bulma--tabs"))
|
66
|
+
@id = id || "tabs"
|
67
|
+
@tabs_class = tabs_class
|
68
|
+
@contents_class = contents_class
|
69
|
+
@data_attributes_builder = data_attributes_builder
|
35
70
|
@tabs = []
|
36
71
|
@contents = []
|
37
72
|
end
|
38
73
|
|
39
|
-
def tab(id:, title:, icon: nil, active: false, &
|
40
|
-
@tabs << Tab.new(id:, title:, icon:, active
|
41
|
-
|
74
|
+
def tab(id:, title:, icon: nil, active: false, &)
|
75
|
+
@tabs << TabComponents::Tab.new(id:, title:, icon:, active:,
|
76
|
+
data_attributes_proc: @data_attributes_builder.method(:for_tab))
|
77
|
+
@contents << TabComponents::Content.new(id:, active:,
|
78
|
+
data_attributes_proc: @data_attributes_builder.method(:for_content),
|
79
|
+
&)
|
80
|
+
end
|
81
|
+
|
82
|
+
def right_content(&content)
|
83
|
+
@right_content = content
|
42
84
|
end
|
43
85
|
|
44
86
|
def view_template(&)
|
45
87
|
vanish(&)
|
46
88
|
|
47
|
-
div(
|
48
|
-
|
49
|
-
|
50
|
-
@tabs.each do |tab|
|
51
|
-
li(
|
52
|
-
id: "#{tab.id}-tab",
|
53
|
-
data: {
|
54
|
-
target_key => "tab",
|
55
|
-
tab_content: tab.id,
|
56
|
-
action: "click->#{@stimulus_controller}#showTabContent"
|
57
|
-
},
|
58
|
-
class: tab.active ? "is-active" : ""
|
59
|
-
) do
|
60
|
-
a do
|
61
|
-
icon_span(tab.icon, "mr-1") if tab.icon
|
62
|
-
span { tab.title }
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
@contents.each do |content|
|
70
|
-
div(id: content.id,
|
71
|
-
class: content.active ? "" : "is-hidden",
|
72
|
-
data: { target_key => "content" }) do
|
73
|
-
content.block.call
|
74
|
-
end
|
75
|
-
end
|
89
|
+
div(id: @id, data: @data_attributes_builder.for_container) do
|
90
|
+
build_tabs_with_optional_right_content
|
91
|
+
div(id: "#{@id}-content", class: @contents_class) { build_content }
|
76
92
|
end
|
77
93
|
end
|
78
94
|
|
79
95
|
private
|
80
96
|
|
81
|
-
def
|
82
|
-
|
97
|
+
def build_tabs_with_optional_right_content
|
98
|
+
return build_tabs if @right_content.nil?
|
99
|
+
|
100
|
+
div(class: "columns") do
|
101
|
+
div(class: "column") { build_tabs }
|
102
|
+
div(class: "column is-narrow") { @right_content.call }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_tabs
|
107
|
+
div(class: "tabs #{@tabs_class}".strip) do
|
108
|
+
ul(id: "#{@id}-tabs") do
|
109
|
+
@tabs.each { render it }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_content
|
115
|
+
@contents.each { render it }
|
83
116
|
end
|
84
117
|
end
|
85
118
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulma-phlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Todd Kummer
|
@@ -23,6 +23,20 @@ dependencies:
|
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: 2.0.2
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: zeitwerk
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.7'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '2.7'
|
26
40
|
- !ruby/object:Gem::Dependency
|
27
41
|
name: actionpack
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +104,9 @@ files:
|
|
90
104
|
- README.md
|
91
105
|
- Rakefile
|
92
106
|
- lib/bulma-phlex.rb
|
107
|
+
- lib/bulma_phlex/rails/card_helper.rb
|
108
|
+
- lib/bulma_phlex/rails/table_helper.rb
|
109
|
+
- lib/bulma_phlex/railtie.rb
|
93
110
|
- lib/bulma_phlex/version.rb
|
94
111
|
- lib/components/bulma.rb
|
95
112
|
- lib/components/bulma/base.rb
|
@@ -99,6 +116,8 @@ files:
|
|
99
116
|
- lib/components/bulma/navigation_bar.rb
|
100
117
|
- lib/components/bulma/navigation_bar_dropdown.rb
|
101
118
|
- lib/components/bulma/pagination.rb
|
119
|
+
- lib/components/bulma/tab_components/content.rb
|
120
|
+
- lib/components/bulma/tab_components/tab.rb
|
102
121
|
- lib/components/bulma/table.rb
|
103
122
|
- lib/components/bulma/tabs.rb
|
104
123
|
homepage: https://github.com/RockSolt/bulma-phlex
|