bulma-phlex 0.15.0 → 0.17.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 +65 -23
- data/lib/bulma_phlex/breadcrumb.rb +82 -0
- data/lib/bulma_phlex/card.rb +37 -7
- data/lib/bulma_phlex/dropdown.rb +15 -7
- data/lib/bulma_phlex/icon.rb +16 -4
- data/lib/bulma_phlex/image.rb +48 -0
- data/lib/bulma_phlex/media_object.rb +118 -0
- data/lib/bulma_phlex/navigation_bar_dropdown.rb +5 -2
- data/lib/bulma_phlex/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a4e33701b1ed15897b743789cc3fb1923fdaf70fd065035f8342836058927ed
|
|
4
|
+
data.tar.gz: 772252cf5d5660a0a926f4d24a2ffd73898947a6db4ce3f8ea880978acdda0bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7ec1799752698497e06b075b7378d18a3b820e80ec9e95c7448eb1999ac93514c785d6a61f95434ba02962edb103aa398bd6994506a0954804af52becb56f9ac
|
|
7
|
+
data.tar.gz: 4071dd6000764651b7a677d1ab6ac94c15b59043692602be997924ec094977f41eaf704222554e89ce33f0a49feadc65eeb680ef8c3d36963034995c7b867570
|
data/README.md
CHANGED
|
@@ -10,6 +10,7 @@ This gem provides a set of ready-to-use [Phlex](https://github.com/phlex-ruby/ph
|
|
|
10
10
|
|
|
11
11
|
- [Installation](#installation)
|
|
12
12
|
- [Usage](#usage)
|
|
13
|
+
- [Breadcrumb](#breadcrumb)
|
|
13
14
|
- [Button](#button)
|
|
14
15
|
- [Card](#card)
|
|
15
16
|
- [Columns](#columns)
|
|
@@ -19,7 +20,9 @@ This gem provides a set of ready-to-use [Phlex](https://github.com/phlex-ruby/ph
|
|
|
19
20
|
- [Grid](#grid)
|
|
20
21
|
- [Hero](#hero)
|
|
21
22
|
- [Icon](#icon)
|
|
23
|
+
- [Image](#image)
|
|
22
24
|
- [Level](#level)
|
|
25
|
+
- [Media Object](#media-object)
|
|
23
26
|
- [Message](#message)
|
|
24
27
|
- [Modal](#modal)
|
|
25
28
|
- [NavigationBar](#navigationbar)
|
|
@@ -73,11 +76,24 @@ This gem requires:
|
|
|
73
76
|
require "bulma-phlex"
|
|
74
77
|
```
|
|
75
78
|
|
|
76
|
-
|
|
77
79
|
## Usage
|
|
78
80
|
|
|
79
81
|
Use the Phlex components in your Rails views or any Ruby application that supports Phlex components.
|
|
80
82
|
|
|
83
|
+
### Breadcrumb
|
|
84
|
+
|
|
85
|
+
Renders a [Bulma breadcrumb](https://bulma.io/documentation/components/breadcrumb/) navigation element. Each breadcrumb item is added via the `item` method on the yielded component.
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
render BulmaPhlex::Breadcrumb.new do |bc|
|
|
89
|
+
bc.item("Bulma", href: "/")
|
|
90
|
+
bc.item("Components", href: "/components")
|
|
91
|
+
bc.item("Breadcrumb")
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
It supports options for **alignment** (centered, right-aligned), **separator** style (arrow, bullet, dot, or succeeds), and **size** (small, medium, large). Items also support an optional `icon` argument.
|
|
96
|
+
|
|
81
97
|
### Button
|
|
82
98
|
|
|
83
99
|
Renders a [Bulma button](https://bulma.io/documentation/elements/button/) element with support for color, size, style modifiers, and left/right icons.
|
|
@@ -94,11 +110,12 @@ The button label can be passed in as a string or in a block.
|
|
|
94
110
|
|
|
95
111
|
### Card
|
|
96
112
|
|
|
97
|
-
Renders a [Bulma card](https://bulma.io/documentation/components/card/) with an optional header, content area, and footer links. Each section is populated via builder methods on the yielded component.
|
|
113
|
+
Renders a [Bulma card](https://bulma.io/documentation/components/card/) with an optional header, image, content area, and footer links. Each section is populated via builder methods on the yielded component.
|
|
98
114
|
|
|
99
115
|
```ruby
|
|
100
116
|
render BulmaPhlex::Card.new do |card|
|
|
101
|
-
card.
|
|
117
|
+
card.header("Card Title")
|
|
118
|
+
card.image(src: "image.jpg", alt: "Card image")
|
|
102
119
|
card.content do
|
|
103
120
|
"This is some card content"
|
|
104
121
|
end
|
|
@@ -107,9 +124,10 @@ render BulmaPhlex::Card.new do |card|
|
|
|
107
124
|
end
|
|
108
125
|
```
|
|
109
126
|
|
|
110
|
-
|
|
111
|
-
of the block.
|
|
127
|
+
The `header` method accepts a string, for a simple title, or a block for custom content.
|
|
112
128
|
|
|
129
|
+
Use method `footer_item` for full control of the footer items. Class `footer-item` must be on the outer element
|
|
130
|
+
of the block.
|
|
113
131
|
|
|
114
132
|
### Columns
|
|
115
133
|
|
|
@@ -125,7 +143,6 @@ end
|
|
|
125
143
|
|
|
126
144
|
The `gap:` option accepts either an integer (0–8) or a hash keyed by breakpoint for responsive gap sizes.
|
|
127
145
|
|
|
128
|
-
|
|
129
146
|
### Dropdown
|
|
130
147
|
|
|
131
148
|
Renders a [Bulma dropdown](https://bulma.io/documentation/components/dropdown/) menu. Supports click-to-toggle (default, via a Stimulus controller) and hoverable (no JavaScript) modes.
|
|
@@ -142,6 +159,11 @@ end
|
|
|
142
159
|
|
|
143
160
|
Set `click: false` to use hover mode instead of the Stimulus controller.
|
|
144
161
|
|
|
162
|
+
Use method `header` to add a non-clickable header item. The method takes an optional `divider` argument. (This is not in the Bulma library.)
|
|
163
|
+
|
|
164
|
+
```ruby
|
|
165
|
+
dropdown.header("Actions", divider: true)
|
|
166
|
+
```
|
|
145
167
|
|
|
146
168
|
### File Upload
|
|
147
169
|
|
|
@@ -155,7 +177,6 @@ end
|
|
|
155
177
|
|
|
156
178
|
Set `name: true` to include a file name display element. When enabled, Stimulus data attributes are wired up automatically. The controller is not included in this gem; an [example implementation](https://github.com/RockSolt/bulma-phlex-rails/blob/main/app/javascript/controllers/bulma_phlex/file_input_display_controller.js) is available in the `bulma-phlex-rails` gem.
|
|
157
179
|
|
|
158
|
-
|
|
159
180
|
### Form Field
|
|
160
181
|
|
|
161
182
|
Renders a [Bulma form field](https://bulma.io/documentation/form/general/#form-field) grouping a label, control, and optional help text. Set the label via the `label` method (string or block) and the input via the `control` method.
|
|
@@ -169,7 +190,6 @@ end
|
|
|
169
190
|
|
|
170
191
|
The `column:` and `grid:` options integrate the field into Bulma's column and grid layout systems. Both accept `true`, a size string, or a breakpoint hash.
|
|
171
192
|
|
|
172
|
-
|
|
173
193
|
### Grid
|
|
174
194
|
|
|
175
195
|
Renders a [Bulma smart grid](https://bulma.io/documentation/grid/smart-grid/) layout. Supports fixed column counts, auto-count, minimum column width, and independent gap control.
|
|
@@ -182,7 +202,6 @@ render BulmaPhlex::Grid.new(minimum_column_width: 16) do
|
|
|
182
202
|
end
|
|
183
203
|
```
|
|
184
204
|
|
|
185
|
-
|
|
186
205
|
### Hero
|
|
187
206
|
|
|
188
207
|
Renders a [Bulma hero](https://bulma.io/documentation/layout/hero/) section with support for color and size options.
|
|
@@ -199,7 +218,6 @@ render BulmaPhlex::Hero.new(color: "info", size: "large") do |hero|
|
|
|
199
218
|
end
|
|
200
219
|
```
|
|
201
220
|
|
|
202
|
-
|
|
203
221
|
### Icon
|
|
204
222
|
|
|
205
223
|
Renders a [Bulma icon](https://bulma.io/documentation/elements/icon/) element. Supports color, size, optional text alongside the icon, and left/right positioning for use inside form controls.
|
|
@@ -209,6 +227,21 @@ render BulmaPhlex::Icon.new("fas fa-user")
|
|
|
209
227
|
render BulmaPhlex::Icon.new("fas fa-home", size: :large, color: :primary, text_right: "Home")
|
|
210
228
|
```
|
|
211
229
|
|
|
230
|
+
### Image
|
|
231
|
+
|
|
232
|
+
Renders a [Bulma image](https://bulma.io/documentation/elements/image/) element. Supports size, ratio, rounded, and additional HTML attributes (on either the wrapping `figure` element or the `img` element).
|
|
233
|
+
|
|
234
|
+
```ruby
|
|
235
|
+
render BulmaPhlex::Image.new(src: "image.jpg", size: 64)
|
|
236
|
+
|
|
237
|
+
render BulmaPhlex::Image.new(
|
|
238
|
+
src: "image.jpg",
|
|
239
|
+
alt: "An image",
|
|
240
|
+
rounded: true,
|
|
241
|
+
ratio: "16by9",
|
|
242
|
+
img_attributes: { class: "custom-img-class", id: "image-id" },
|
|
243
|
+
class: "custom-class", id: "figure-image-id")
|
|
244
|
+
```
|
|
212
245
|
|
|
213
246
|
### Level
|
|
214
247
|
|
|
@@ -221,6 +254,26 @@ render BulmaPhlex::Level.new do |level|
|
|
|
221
254
|
end
|
|
222
255
|
```
|
|
223
256
|
|
|
257
|
+
### Media Object
|
|
258
|
+
|
|
259
|
+
Renders a [Bulma media object](https://bulma.io/documentation/layout/media-object/) with an optional left image/icon, right content, and main body content. Each section is populated via builder methods on the yielded component.
|
|
260
|
+
|
|
261
|
+
```ruby
|
|
262
|
+
render BulmaPhlex::MediaObject.new do |media|
|
|
263
|
+
media.left { img(src: "/avatar.png", alt: "Avatar") }
|
|
264
|
+
media.content { "This is the main content of the media object." }
|
|
265
|
+
media.right { button(class: "button is-small") { "Action" } }
|
|
266
|
+
end
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
If the left content is an image, method `image` can be used instead of `left` to automatically build the supporting HTML structure.
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
render BulmaPhlex::MediaObject.new do |media|
|
|
273
|
+
media.image(src: "/avatar.png", alt: "Avatar", size: 64, rounded: true)
|
|
274
|
+
media.content { "This is the main content of the media object." }
|
|
275
|
+
end
|
|
276
|
+
```
|
|
224
277
|
|
|
225
278
|
### Message
|
|
226
279
|
|
|
@@ -232,7 +285,6 @@ render BulmaPhlex::Message.new("Hello World", color: "info", delete: true) do
|
|
|
232
285
|
end
|
|
233
286
|
```
|
|
234
287
|
|
|
235
|
-
|
|
236
288
|
### Modal
|
|
237
289
|
|
|
238
290
|
Renders a [Bulma modal](https://bulma.io/documentation/components/modal/) dialog overlay with a background, content area, and close button. Content is provided via a block.
|
|
@@ -248,7 +300,6 @@ end
|
|
|
248
300
|
|
|
249
301
|
The modal is shown by adding the `is-active` class to the container — nothing in the component does this automatically. The default Stimulus controller (`bulma-phlex--modal`) handles open/close behavior. Pass a custom `data_attributes_builder:` to integrate with a different JavaScript setup.
|
|
250
302
|
|
|
251
|
-
|
|
252
303
|
### NavigationBar
|
|
253
304
|
|
|
254
305
|
Renders a [Bulma navbar](https://bulma.io/documentation/components/navbar/) with support for branding, left/right nav links, and dropdown menus. Collapses automatically on mobile via the `bulma-phlex--navigation-bar` Stimulus controller (provided by the `bulma-phlex-rails` gem).
|
|
@@ -271,7 +322,6 @@ end
|
|
|
271
322
|
> [!NOTE]
|
|
272
323
|
> Setting `container: true` (or a constraint string like `"is-max-desktop"`) wraps the navbar content in a Bulma container for fixed-width layout. The navbar's background color still spans the full viewport width.
|
|
273
324
|
|
|
274
|
-
|
|
275
325
|
### Notification
|
|
276
326
|
|
|
277
327
|
Renders a [Bulma notification](https://bulma.io/documentation/elements/notification/) alert box with support for color and mode options.
|
|
@@ -290,7 +340,6 @@ render BulmaPhlex::Notification.new(color: "warning", delete: { data: { action:
|
|
|
290
340
|
end
|
|
291
341
|
```
|
|
292
342
|
|
|
293
|
-
|
|
294
343
|
### Pagination
|
|
295
344
|
|
|
296
345
|
Renders the [Bulma pagination](https://bulma.io/documentation/components/pagination/) component with previous/next links, numbered page links, ellipses for skipped ranges, and an item count summary. Only renders when there is more than one page of results.
|
|
@@ -301,7 +350,6 @@ render BulmaPhlex::Pagination.new(@products, ->(page) { products_path(page: page
|
|
|
301
350
|
|
|
302
351
|
The first argument must be a pager object responding to `current_page`, `total_pages`, `per_page`, `total_count`, `previous_page`, and `next_page`.
|
|
303
352
|
|
|
304
|
-
|
|
305
353
|
### Progress Bar
|
|
306
354
|
|
|
307
355
|
Renders a [Bulma progress bar](https://bulma.io/documentation/elements/progress/) element. Supports color and size options.
|
|
@@ -312,7 +360,6 @@ render BulmaPhlex::ProgressBar.new(color: "success", size: "large", value: 75, m
|
|
|
312
360
|
|
|
313
361
|
Omitting `value:` and `max:` produces an indeterminate (animated) progress bar.
|
|
314
362
|
|
|
315
|
-
|
|
316
363
|
### Table
|
|
317
364
|
|
|
318
365
|
Renders a [Bulma table](https://bulma.io/documentation/elements/table/) for a collection of records. Columns are defined via builder methods on the yielded component.
|
|
@@ -338,7 +385,7 @@ To add pagination to the table, call `paginate` with a block that returns a path
|
|
|
338
385
|
table.paginate { |page| products_path(page: page) }
|
|
339
386
|
```
|
|
340
387
|
|
|
341
|
-
Pass HTML attributes to the `tr` elements via the `row` method, using either keyword arguments or a block
|
|
388
|
+
Pass HTML attributes to the `tr` elements via the `row` method, using either keyword arguments or a block
|
|
342
389
|
that receives the record for the row:
|
|
343
390
|
|
|
344
391
|
```ruby
|
|
@@ -351,7 +398,6 @@ Hide columns on smaller screens with the column `hidden` option:
|
|
|
351
398
|
table.column("Email", hidden: { mobile: true }) { |user| user.email }
|
|
352
399
|
```
|
|
353
400
|
|
|
354
|
-
|
|
355
401
|
### Tabs
|
|
356
402
|
|
|
357
403
|
Renders a [Bulma tabs](https://bulma.io/documentation/components/tabs/) component with tabbed navigation and associated content panels. Supports alignment, size, and style options (boxed, toggle, rounded, fullwidth).
|
|
@@ -367,7 +413,6 @@ Tab switching is handled by the `bulma-phlex--tabs` Stimulus controller. The con
|
|
|
367
413
|
|
|
368
414
|
An optional right-side element (e.g. a button) can be placed alongside the tab bar via `right_content`.
|
|
369
415
|
|
|
370
|
-
|
|
371
416
|
### Tag
|
|
372
417
|
|
|
373
418
|
Renders the [Bulma tag](https://bulma.io/documentation/elements/tag/) component. Supports color, size, rounded, and an optional inline delete button.
|
|
@@ -379,7 +424,6 @@ render BulmaPhlex::Tag.new("Sale", light: "danger")
|
|
|
379
424
|
|
|
380
425
|
The element type is inferred from the attributes: an `href:` produces an `<a>`, a `data-action` or `delete: true` produces a `<button>`, and otherwise a `<span>` is used.
|
|
381
426
|
|
|
382
|
-
|
|
383
427
|
### Title and Subtitle
|
|
384
428
|
|
|
385
429
|
Renders a [Bulma title](https://bulma.io/documentation/elements/title/) with an optional subtitle. Supports sizes 1–6 for both elements and a `spaced:` option to increase the gap between them.
|
|
@@ -391,13 +435,12 @@ render BulmaPhlex::Title.new("Dr. Strangelove", size: 2, subtitle: "Or: How I Le
|
|
|
391
435
|
|
|
392
436
|
When `size:` is set but `subtitle_size:` is not, the subtitle size defaults to `size + 2`.
|
|
393
437
|
|
|
394
|
-
|
|
395
438
|
## Upgrading to 0.8
|
|
396
439
|
|
|
397
440
|
> [!IMPORTANT]
|
|
398
441
|
> The 0.8.0 release includes breaking changes. The namespace for the components has been changed from `Components::Bulma` to `Components::BulmaPhlex`.
|
|
399
442
|
|
|
400
|
-
This can generally be handled with a
|
|
443
|
+
This can generally be handled with a _Find-and-Replace_:
|
|
401
444
|
|
|
402
445
|
**Find:** `Bulma::`
|
|
403
446
|
**Replace:** `BulmaPhlex::`
|
|
@@ -406,7 +449,6 @@ Note that this change was also applied to the expected Stimulus controllers. Ref
|
|
|
406
449
|
|
|
407
450
|
Finally, the optional Rails extensions for the Card and Table components have been moved to the `bulma-phlex-rails` gem. If you are using this with Rails, you should use [the `bulma-phlex-rails` gem](https://github.com/RockSolt/bulma-phlex-rails). It provides both the component extensions as well as JavaScript for the Dropdown, Navigation Bar, and Tabs components.
|
|
408
451
|
|
|
409
|
-
|
|
410
452
|
## Development
|
|
411
453
|
|
|
412
454
|
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.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Renders a [Bulma breadcrumb](https://bulma.io/documentation/components/breadcrumb/) component.
|
|
5
|
+
# It supports options for **alignment** (centered, right-aligned), **separator** style (arrow,
|
|
6
|
+
# bullet, dot, or succeeds (greater than)), and **size** (small, medium, large).
|
|
7
|
+
class Breadcrumb < Base
|
|
8
|
+
# **Parameters**
|
|
9
|
+
#
|
|
10
|
+
# - `align` — Breadcrumb alignment: `"centered"` or `"right"`
|
|
11
|
+
# - `separator` — Breadcrumb separator style: `"arrow"`, `"bullet"`, `"dot"`, or `"succeeds"`
|
|
12
|
+
# - `size` — Alternate size: `"small"`, `"medium"`, or `"large"`
|
|
13
|
+
# - `**html_attributes` — Additional HTML attributes for the `<nav>` element
|
|
14
|
+
def self.new(align: nil, separator: nil, size: nil, **html_attributes)
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(align: nil, separator: nil, size: nil, **html_attributes)
|
|
19
|
+
@align = align
|
|
20
|
+
@separator = separator
|
|
21
|
+
@size = size
|
|
22
|
+
@html_attributes = html_attributes
|
|
23
|
+
|
|
24
|
+
@items = []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def view_template(&)
|
|
28
|
+
vanish(&)
|
|
29
|
+
return if @items.empty?
|
|
30
|
+
|
|
31
|
+
nav(**mix(@html_attributes, class: nav_classes, aria: { label: "breadcrumbs" })) do
|
|
32
|
+
ul do
|
|
33
|
+
@items[0...-1].each do |item|
|
|
34
|
+
render_item(item)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
render_last_item
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Adds a breadcrumb item to the component. The last item added will be rendered as the active item.
|
|
43
|
+
#
|
|
44
|
+
# **Parameters**
|
|
45
|
+
# - `label` (positional) — The text label for the breadcrumb item
|
|
46
|
+
# - `href` — URL for the breadcrumb item; not required on last item / current page
|
|
47
|
+
# - `icon` — Optional icon class for the breadcrumb item (e.g. `"fa-solid fa-home"`)
|
|
48
|
+
def item(label, href: nil, icon: nil)
|
|
49
|
+
@items << { label:, icon:, html_attributes: { href: href } }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def nav_classes
|
|
55
|
+
classes = ["breadcrumb"]
|
|
56
|
+
classes << "is-#{@align}" if @align
|
|
57
|
+
classes << "has-#{@separator}-separator" if @separator
|
|
58
|
+
classes << "is-#{@size}" if @size
|
|
59
|
+
classes
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def render_item(item, list_item_attributes: {})
|
|
63
|
+
li(**list_item_attributes) do
|
|
64
|
+
a(**item[:html_attributes]) do
|
|
65
|
+
if item[:icon]
|
|
66
|
+
render BulmaPhlex::Icon.new(item[:icon], size: "small", icon_attributes: { aria: { hidden: "true" } })
|
|
67
|
+
span { item[:label] }
|
|
68
|
+
else
|
|
69
|
+
plain item[:label]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def render_last_item
|
|
76
|
+
item = @items.last
|
|
77
|
+
|
|
78
|
+
item[:html_attributes] = mix(item[:html_attributes], aria: { current: "page" })
|
|
79
|
+
render_item(item, list_item_attributes: { class: "is-active" })
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/bulma_phlex/card.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module BulmaPhlex
|
|
4
4
|
# Renders a [Bulma card](https://bulma.io/documentation/components/card/) component.
|
|
5
5
|
#
|
|
6
|
-
# Supports an optional **header** (with title and custom classes), a **content** area, and a
|
|
6
|
+
# Supports an optional **header** (with title and custom classes), an **image**, a **content** area, and a
|
|
7
7
|
# **footer** with one or more link items (which can include icons). Each section is populated
|
|
8
8
|
# via builder methods on the yielded component.
|
|
9
9
|
#
|
|
@@ -32,8 +32,9 @@ module BulmaPhlex
|
|
|
32
32
|
def view_template(&)
|
|
33
33
|
vanish(&)
|
|
34
34
|
|
|
35
|
-
div(**mix(class: "card", **@html_attributes)) do
|
|
35
|
+
div(**mix({ class: "card" }, **@html_attributes)) do
|
|
36
36
|
card_header
|
|
37
|
+
card_image
|
|
37
38
|
card_content
|
|
38
39
|
card_footer
|
|
39
40
|
end
|
|
@@ -44,8 +45,28 @@ module BulmaPhlex
|
|
|
44
45
|
# - `title` — The text to display in the card header
|
|
45
46
|
# - `classes` — Optional additional CSS classes for the header element
|
|
46
47
|
def head(title, classes: nil)
|
|
48
|
+
warn "[DEPRECATION] `BulmaPhlex::Card#head` is deprecated. Use `header` instead.", category: :deprecated
|
|
49
|
+
|
|
50
|
+
header(title, class: classes)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# in order to use the method name `header`, we need to grab a reference to the method on the base class
|
|
54
|
+
# so it is still available to us
|
|
55
|
+
alias html_header header
|
|
56
|
+
|
|
57
|
+
# Sets the card header. Pass in the title as a string and/or provide a block to render custom content
|
|
58
|
+
# in the header.
|
|
59
|
+
#
|
|
60
|
+
# - `title` — The text to display in the card header (optional)
|
|
61
|
+
# - `**html_attributes` — Additional HTML attributes for the header element (optional)
|
|
62
|
+
def header(title = nil, **html_attributes, &block)
|
|
47
63
|
@header_title = title
|
|
48
|
-
@
|
|
64
|
+
@header_attributes = html_attributes
|
|
65
|
+
@header_content = block
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def image(src:, alt: nil, size: nil, rounded: false)
|
|
69
|
+
@image = BulmaPhlex::Image.new(src:, alt:, size:, rounded:)
|
|
49
70
|
end
|
|
50
71
|
|
|
51
72
|
# Sets the card body content.
|
|
@@ -74,10 +95,19 @@ module BulmaPhlex
|
|
|
74
95
|
private
|
|
75
96
|
|
|
76
97
|
def card_header
|
|
77
|
-
return if @header_title.nil?
|
|
98
|
+
return if @header_title.nil? && @header_content.nil?
|
|
99
|
+
|
|
100
|
+
html_header(**mix({ class: "card-header" }, @header_attributes)) do
|
|
101
|
+
p(class: "card-header-title") { plain @header_title } if @header_title
|
|
102
|
+
@header_content&.call
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def card_image
|
|
107
|
+
return if @image.nil?
|
|
78
108
|
|
|
79
|
-
|
|
80
|
-
|
|
109
|
+
div(class: "card-image") do
|
|
110
|
+
render @image
|
|
81
111
|
end
|
|
82
112
|
end
|
|
83
113
|
|
|
@@ -85,7 +115,7 @@ module BulmaPhlex
|
|
|
85
115
|
return if @card_content.nil?
|
|
86
116
|
|
|
87
117
|
div(class: "card-content") do
|
|
88
|
-
|
|
118
|
+
@card_content.call
|
|
89
119
|
end
|
|
90
120
|
end
|
|
91
121
|
|
data/lib/bulma_phlex/dropdown.rb
CHANGED
|
@@ -61,20 +61,28 @@ module BulmaPhlex
|
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
# Adds a non-clickable header item to the dropdown menu. Optionally add a divider before the header with
|
|
65
|
+
# the `divder: true` parameter.
|
|
66
|
+
def header(label, divider: false)
|
|
67
|
+
self.divider if divider
|
|
68
|
+
div(class: "dropdown-item has-text-weight-semibold is-unselectable") { label }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def item(content = nil, **html_attributes, &)
|
|
72
|
+
attributes = mix({ class: "dropdown-item" }, html_attributes)
|
|
65
73
|
if block_given?
|
|
66
|
-
div(
|
|
74
|
+
div(**attributes, &)
|
|
67
75
|
else
|
|
68
|
-
div(
|
|
76
|
+
div(**attributes) { content }
|
|
69
77
|
end
|
|
70
78
|
end
|
|
71
79
|
|
|
72
|
-
def link(label, path)
|
|
73
|
-
a(class: "dropdown-item", href: path) { label }
|
|
80
|
+
def link(label, path, **html_attributes)
|
|
81
|
+
a(**mix({ class: "dropdown-item" }, html_attributes), href: path) { label }
|
|
74
82
|
end
|
|
75
83
|
|
|
76
|
-
def divider
|
|
77
|
-
hr(class: "dropdown-divider")
|
|
84
|
+
def divider(**html_attributes)
|
|
85
|
+
hr(**mix({ class: "dropdown-divider" }, html_attributes))
|
|
78
86
|
end
|
|
79
87
|
|
|
80
88
|
private
|
data/lib/bulma_phlex/icon.rb
CHANGED
|
@@ -5,7 +5,12 @@ module BulmaPhlex
|
|
|
5
5
|
# form control positioning.
|
|
6
6
|
#
|
|
7
7
|
# Supports **color** and **size** options, optional **text** to the left or right of the icon,
|
|
8
|
-
# and **positioning** helpers (`left`/`right`) for use inside form controls.
|
|
8
|
+
# and **positioning** helpers (`left`/`right`) for use inside form controls. When text is provide,
|
|
9
|
+
# the icon and text are wrapped in a container with the `icon-text` class for proper spacing, and
|
|
10
|
+
# the icon includes `aria-hidden="true"` for accessibility.
|
|
11
|
+
#
|
|
12
|
+
# Additional HTML attributes can be passed to the icon's `<span>` element via `**html_attributes`,
|
|
13
|
+
# and to the inner `<i>` by nested them under `icon_attributes`.
|
|
9
14
|
#
|
|
10
15
|
# ## Example
|
|
11
16
|
#
|
|
@@ -21,7 +26,8 @@ module BulmaPhlex
|
|
|
21
26
|
# - `text_left` — Text to display to the left of the icon
|
|
22
27
|
# - `left` — If `true`, adds the `is-left` class for use in form controls
|
|
23
28
|
# - `right` — If `true`, adds the `is-right` class for use in form controls
|
|
24
|
-
# - `**html_attributes` — Additional HTML attributes for the icon span element
|
|
29
|
+
# - `**html_attributes` — Additional HTML attributes for the icon span element. Nest attributes under
|
|
30
|
+
# `icon_attributes` to apply them to the inner `<i>` element instead.
|
|
25
31
|
def self.new(icon,
|
|
26
32
|
text_right: nil,
|
|
27
33
|
text_left: nil,
|
|
@@ -48,14 +54,15 @@ module BulmaPhlex
|
|
|
48
54
|
@color = color
|
|
49
55
|
@left = left
|
|
50
56
|
@right = right
|
|
51
|
-
@html_attributes = html_attributes
|
|
57
|
+
@html_attributes = html_attributes.clone
|
|
58
|
+
@icon_attributes = @html_attributes.delete(:icon_attributes) || {}
|
|
52
59
|
end
|
|
53
60
|
|
|
54
61
|
def view_template
|
|
55
62
|
optional_text_wrapper do
|
|
56
63
|
span { @text_left } if @text_left
|
|
57
64
|
span(**mix({ class: icon_classes }, @html_attributes)) do
|
|
58
|
-
i(class: @icon)
|
|
65
|
+
i(class: @icon, **@icon_attributes)
|
|
59
66
|
end
|
|
60
67
|
span { @text_right } if @text_right
|
|
61
68
|
end
|
|
@@ -65,12 +72,17 @@ module BulmaPhlex
|
|
|
65
72
|
|
|
66
73
|
def optional_text_wrapper(&)
|
|
67
74
|
if @text_right || @text_left
|
|
75
|
+
add_aria_hidden_to_icon_attributes
|
|
68
76
|
span(class: "icon-text", &)
|
|
69
77
|
else
|
|
70
78
|
yield
|
|
71
79
|
end
|
|
72
80
|
end
|
|
73
81
|
|
|
82
|
+
def add_aria_hidden_to_icon_attributes
|
|
83
|
+
@icon_attributes = mix({ aria: { hidden: "true" } }, @icon_attributes)
|
|
84
|
+
end
|
|
85
|
+
|
|
74
86
|
def icon_classes
|
|
75
87
|
classes = ["icon"]
|
|
76
88
|
classes << "is-#{@size}" if @size
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Renders a [Bulma image](https://bulma.io/documentation/elements/image/) component.
|
|
5
|
+
class Image < BulmaPhlex::Base
|
|
6
|
+
# **Parameters**
|
|
7
|
+
#
|
|
8
|
+
# - `src:` — The image source URL (required)
|
|
9
|
+
# - `alt:` — The image alt text (optional)
|
|
10
|
+
# - `rounded:` — Whether to apply the `is-rounded` class (optional, default: false)
|
|
11
|
+
# - `size:` — The image size (optional, e.g., 64 for `is-64x64`)
|
|
12
|
+
# - `ratio:` — The image ratio (optional, e.g., "1by1", "4by3", "16by9")
|
|
13
|
+
# - `img_attributes:` — Additional HTML attributes for the img element (optional)
|
|
14
|
+
# - `**html_attributes` — Additional HTML attributes for the figure element (optional)
|
|
15
|
+
def self.new(src:, alt: nil, rounded: false, size: nil, ratio: nil, img_attributes: {}, **html_attributes)
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize(src:, alt: nil, rounded: false, size: nil, ratio: nil, img_attributes: {}, **html_attributes)
|
|
20
|
+
@src = src
|
|
21
|
+
@alt = alt
|
|
22
|
+
@rounded = rounded
|
|
23
|
+
@size = size
|
|
24
|
+
@ratio = ratio
|
|
25
|
+
@img_attributes = img_attributes
|
|
26
|
+
@html_attributes = html_attributes
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def view_template
|
|
30
|
+
figure(**mix({ class: figure_classes }, @html_attributes)) do
|
|
31
|
+
img(**mix({ src: @src, alt: @alt, class: img_classes }, @img_attributes))
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def figure_classes
|
|
38
|
+
classes = ["image"]
|
|
39
|
+
classes << "is-#{@size}x#{@size}" if @size
|
|
40
|
+
classes << "is-#{@ratio}" if @ratio
|
|
41
|
+
classes.join(" ")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def img_classes
|
|
45
|
+
"is-rounded" if @rounded
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module BulmaPhlex
|
|
4
|
+
# Renders a [Bulma media object](https://bulma.io/documentation/components/media-object/) component.
|
|
5
|
+
#
|
|
6
|
+
# Optional HTML attributes can be passed to the constructor as well as any of the three block methods,
|
|
7
|
+
# `left`, `content`, and `right`, to customize the rendered HTML elements.
|
|
8
|
+
#
|
|
9
|
+
# ## Example
|
|
10
|
+
#
|
|
11
|
+
# render BulmaPhlex::MediaObject.new do |media|
|
|
12
|
+
# media.left do
|
|
13
|
+
# p(class: "image is-64x64") do
|
|
14
|
+
# img(src: "/assets/images/placeholders/128x128.png")
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# media.content do
|
|
19
|
+
# p { "This is the main content of the media object." }
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# media.right do
|
|
23
|
+
# button(class: "delete")
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
class MediaObject < BulmaPhlex::Base
|
|
27
|
+
# **Parameters**
|
|
28
|
+
#
|
|
29
|
+
# - `**html_attributes` — Additional HTML attributes for the wrapping `article` element
|
|
30
|
+
def self.new(**html_attributes)
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def initialize(**html_attributes)
|
|
35
|
+
@html_attributes = html_attributes
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def view_template(&)
|
|
39
|
+
vanish(&)
|
|
40
|
+
|
|
41
|
+
article(**mix({ class: "media" }, @html_attributes)) do
|
|
42
|
+
render_media_left if @media_left
|
|
43
|
+
render_media_content if @media_content
|
|
44
|
+
render_media_right if @media_right
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Use a block to provide the left content, which will be wrapped in a `figure` element. Additional
|
|
49
|
+
# HTML attributes can be passed to customize the element.
|
|
50
|
+
#
|
|
51
|
+
# <figure class="media-left">
|
|
52
|
+
# <!-- Left content goes here -->
|
|
53
|
+
# </figure>
|
|
54
|
+
def left(**html_attributes, &block)
|
|
55
|
+
@left_attributes = html_attributes
|
|
56
|
+
@media_left = block
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# If the left content is an image, you can use this method to provide the image source,
|
|
60
|
+
# alt text, size, and whether it should be rounded. Additional HTML attributes can be
|
|
61
|
+
# passed to customize the `figure` element.
|
|
62
|
+
def image(src:, alt: nil, size: nil, rounded: false, **html_attributes)
|
|
63
|
+
left(**html_attributes) do
|
|
64
|
+
p(class: image_classes(size:)) do
|
|
65
|
+
img(src:, alt:, class: ("is-rounded" if rounded))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Use a block to provide the main content, which will be wrapped in a `div` element. Additional
|
|
71
|
+
# HTML attributes can be passed to customize the element.
|
|
72
|
+
#
|
|
73
|
+
# <div class="media-content">
|
|
74
|
+
# <!-- Main content goes here -->
|
|
75
|
+
# </div>
|
|
76
|
+
def content(**html_attributes, &block)
|
|
77
|
+
@content_attributes = html_attributes
|
|
78
|
+
@media_content = block
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Use a block to provide the right content, which will be wrapped in a `div` element. Additional
|
|
82
|
+
# HTML attributes can be passed to customize the element.
|
|
83
|
+
#
|
|
84
|
+
# <div class="media-right">
|
|
85
|
+
# <!-- Right content goes here -->
|
|
86
|
+
# </div>
|
|
87
|
+
def right(**html_attributes, &block)
|
|
88
|
+
@right_attributes = html_attributes
|
|
89
|
+
@media_right = block
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
|
|
94
|
+
def render_media_left
|
|
95
|
+
figure(**mix({ class: "media-left" }, @left_attributes)) do
|
|
96
|
+
@media_left.call
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def render_media_content
|
|
101
|
+
div(**mix({ class: "media-content" }, @content_attributes)) do
|
|
102
|
+
@media_content.call
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def render_media_right
|
|
107
|
+
div(**mix({ class: "media-right" }, @right_attributes)) do
|
|
108
|
+
@media_right.call
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def image_classes(size:)
|
|
113
|
+
classes = ["image"]
|
|
114
|
+
classes << "is-#{size}x#{size}" if size
|
|
115
|
+
classes.join(" ")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -26,8 +26,11 @@ module BulmaPhlex
|
|
|
26
26
|
div(class: "navbar-dropdown is-right", &)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
# Adds a non-clickable header item to the dropdown menu. Optionally add a divider before the header with
|
|
30
|
+
# the `divder: true` parameter.
|
|
31
|
+
def header(label, divider: false)
|
|
32
|
+
self.divider if divider
|
|
33
|
+
div(class: "navbar-item has-text-weight-semibold") { label }
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
def item(label, path)
|
data/lib/bulma_phlex/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bulma-phlex
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Todd Kummer
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-07-21 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: phlex
|
|
@@ -65,6 +65,7 @@ files:
|
|
|
65
65
|
- lib/bulma-phlex.rb
|
|
66
66
|
- lib/bulma_phlex.rb
|
|
67
67
|
- lib/bulma_phlex/base.rb
|
|
68
|
+
- lib/bulma_phlex/breadcrumb.rb
|
|
68
69
|
- lib/bulma_phlex/button.rb
|
|
69
70
|
- lib/bulma_phlex/card.rb
|
|
70
71
|
- lib/bulma_phlex/columns.rb
|
|
@@ -75,7 +76,9 @@ files:
|
|
|
75
76
|
- lib/bulma_phlex/grid.rb
|
|
76
77
|
- lib/bulma_phlex/hero.rb
|
|
77
78
|
- lib/bulma_phlex/icon.rb
|
|
79
|
+
- lib/bulma_phlex/image.rb
|
|
78
80
|
- lib/bulma_phlex/level.rb
|
|
81
|
+
- lib/bulma_phlex/media_object.rb
|
|
79
82
|
- lib/bulma_phlex/message.rb
|
|
80
83
|
- lib/bulma_phlex/modal.rb
|
|
81
84
|
- lib/bulma_phlex/navigation_bar.rb
|