bulma-phlex 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 66aad611632ef1e130fd898e589c7a5c6548673f3bad6efcc9c0fd3e3ee35931
4
+ data.tar.gz: 665413567403f62d159300df558a62f15aad11ef254e963a75904ea72b77ed67
5
+ SHA512:
6
+ metadata.gz: f1e1684e053b1d1fc0fd3f2b0013f448f317ce764f544be465ab48e3b474f491cfe9080c45164262d0389657511429ec5d6396a0f4cb8b2887dad122a7b83ec0
7
+ data.tar.gz: 0a5ffbaf9f9a703b70b304f7d66b9b44789326ce270d84fdbca0da4739a3c29acd38c5f40eeb5647061d2d2854895cd9e3f6888a4160d69ac48e0bfafa19c97d
data/README.md ADDED
@@ -0,0 +1,176 @@
1
+ [![Gem Version](https://badge.fury.io/rb/bulma-phlex.svg)](https://badge.fury.io/rb/bulma-phlex)
2
+ [![Tests](https://github.com/RockSolt/bulma-phlex/actions/workflows/test.yml/badge.svg)](https://github.com/RockSolt/bulma-phlex/actions/workflows/test.yml)
3
+ [![RuboCop](https://github.com/RockSolt/bulma-phlex/actions/workflows/rubocop.yml/badge.svg)](https://github.com/RockSolt/bulma-phlex/actions/workflows/rubocop.yml)
4
+
5
+ # Bulma Components Built with Phlex
6
+
7
+ This gem provides a set of ready-to-use components [Phlex](https://github.com/phlex-ruby/phlex) 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
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem "bulma-phlex"
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ ```bash
20
+ bundle install
21
+ ```
22
+
23
+ Or install it yourself as:
24
+
25
+ ```bash
26
+ gem install bulma-phlex
27
+ ```
28
+
29
+ ### Dependencies
30
+
31
+ This gem requires:
32
+
33
+ - Ruby 3.4 or higher
34
+ - Phlex 2.0.2 or higher
35
+ - Bulma CSS (which you'll need to include in your application)
36
+
37
+ ### Required Setup
38
+
39
+ 1. Include Bulma CSS in your application. You can add it via npm/yarn, CDN, or the [bulma-rails](https://github.com/joshuajansen/bulma-rails) gem.
40
+
41
+ 2. Require the gem in your code:
42
+
43
+ ```ruby
44
+ require "bulma-phlex"
45
+ ```
46
+
47
+
48
+ ## Usage
49
+
50
+ Use the Phlex components in your Rails views or any Ruby application that supports Phlex components.
51
+
52
+ ### Card
53
+
54
+ [Cards](https://bulma.io/documentation/components/card/) are flexible containers that can display various types of content including headers and content sections.
55
+
56
+ ```ruby
57
+ render Components::Bulma::Card.new do |card|
58
+ card.head("Card Title")
59
+ card.content do
60
+ "This is some card content"
61
+ end
62
+ end
63
+ ```
64
+
65
+ ### Level
66
+
67
+ The [Level](https://bulma.io/documentation/layout/level/) component provides a flexible horizontal layout system with left and right alignment.
68
+
69
+ ```ruby
70
+ render Components::Bulma::Level.new do |level|
71
+ level.left do
72
+ button(class: "button") { "Left" }
73
+ end
74
+
75
+ level.right do
76
+ button(class: "button") { "Right" }
77
+ end
78
+ level.right do
79
+ button(class: "button") { "Right 2" }
80
+ end
81
+ end
82
+ ```
83
+
84
+ ### NavigationBar
85
+
86
+ The [NavigationBar](https://bulma.io/documentation/components/navbar/) component provides a responsive navigation header with support for branding, navigation links, and dropdown menus.
87
+
88
+ ```ruby
89
+ render Components::Bulma::NavigationBar.new do |navbar|
90
+ navbar.brand_item "My App", "/"
91
+
92
+ navbar.left do |menu|
93
+ menu.item "Home", "/"
94
+ menu.item "Products", "/products"
95
+ end
96
+
97
+ navbar.right do |menu|
98
+ menu.item "About", "/about"
99
+ menu.dropdown "Account" do |dropdown|
100
+ dropdown.header "User"
101
+ dropdown.item "Profile", "/profile"
102
+ dropdown.item "Settings", "/settings"
103
+ dropdown.divider
104
+ dropdown.item "Sign Out", "/logout"
105
+ end
106
+ end
107
+ end
108
+ ```
109
+
110
+ ### Pagination
111
+
112
+ The [Pagination](https://bulma.io/documentation/components/pagination/) component provides navigation controls for paginated content, including previous/next links, page number links, and a summary of items being displayed.
113
+
114
+ ```ruby
115
+ # In a controller action:
116
+ @products = Product.page(params[:page]).per(20)
117
+
118
+ # In the view:
119
+ render Components::Bulma::Pagination.new(@products, ->(page) { products_path(page: page) })
120
+ ```
121
+
122
+ ### Table
123
+
124
+ 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.
125
+
126
+ ```ruby
127
+ users = User.all
128
+
129
+ render Components::Bulma::Table.new(users) do |table|
130
+ table.column "Name" do |user|
131
+ user.full_name
132
+ end
133
+
134
+ table.column "Email" do |user|
135
+ user.email
136
+ end
137
+
138
+ table.column "Actions" do |user|
139
+ link_to "Edit", edit_user_path(user), class: "button is-small"
140
+ end
141
+ end
142
+ ```
143
+
144
+ ### Tabs
145
+
146
+ 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.
147
+
148
+ ```ruby
149
+ render Components::Bulma::Tabs.new do |tabs|
150
+ tabs.tab(id: "profile", title: "Profile", active: true) do
151
+ "Profile content goes here"
152
+ end
153
+
154
+ tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
155
+ "Settings content goes here"
156
+ end
157
+
158
+ tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
159
+ "Notifications content goes here"
160
+ end
161
+ end
162
+ ```
163
+
164
+ ## Development
165
+
166
+ 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.
167
+
168
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
169
+
170
+ ## Contributing
171
+
172
+ Bug reports and pull requests are welcome on GitHub at https://github.com/RockSolt/bulma-phlex.
173
+
174
+ ## License
175
+
176
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "phlex"
4
+ require "bulma_phlex/version"
5
+
6
+ require "components/bulma"
7
+ require "components/bulma/base"
8
+ require "components/bulma/card"
9
+ require "components/bulma/level"
10
+ require "components/bulma/navigation_bar_dropdown"
11
+ require "components/bulma/navigation_bar"
12
+ require "components/bulma/pagination"
13
+ require "components/bulma/table"
14
+ require "components/bulma/tabs"
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaPhlex
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Base component for all Bulma components
6
+ #
7
+ # This is the parent class for all Bulma components in this library.
8
+ # It provides common utility methods and inherits from `Phlex::HTML`.
9
+ #
10
+ class Base < Phlex::HTML
11
+ private
12
+
13
+ def icon_span(icon, additional_classes = nil)
14
+ span(class: "icon #{additional_classes}".strip) do
15
+ i(class: icon)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Card component for content display
6
+ #
7
+ # This component implements the [Bulma card](https://bulma.io/documentation/components/card/)
8
+ # interface. Cards are flexible containers that can display various types of content
9
+ # including headers, content sections, and more.
10
+ #
11
+ # ## Example
12
+ #
13
+ # ```ruby
14
+ # render Components::Bulma::Card.new do |card|
15
+ # card.head("Card Title")
16
+ # card.content do
17
+ # "This is some card content"
18
+ # end
19
+ # end
20
+ # ```
21
+ #
22
+ class Card < Components::Bulma::Base
23
+ def view_template(&)
24
+ div(class: "card", &)
25
+ end
26
+
27
+ def head(title, classes: nil)
28
+ header(class: "card-header #{classes}") do
29
+ p(class: "card-header-title") { plain title }
30
+ end
31
+ end
32
+
33
+ def content(&)
34
+ div(class: "card-content") do
35
+ div(class: "content", &)
36
+ end
37
+ 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
+ end
57
+ end
58
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Level component for responsive horizontal layouts
6
+ #
7
+ # This component implements the [Bulma level](https://bulma.io/documentation/layout/level/)
8
+ # interface, providing a flexible horizontal layout system with left and right alignment.
9
+ #
10
+ # ## Example:
11
+ #
12
+ # ```ruby
13
+ # render Components::Bulma::Level.new do |level|
14
+ # level.left do
15
+ # button(class: "button") { "Left" }
16
+ # end
17
+ #
18
+ # level.right do
19
+ # button(class: "button") { "Right" }
20
+ # end
21
+ # level.right do
22
+ # button(class: "button") { "Right 2" }
23
+ # end
24
+ # end
25
+ # ```
26
+ #
27
+ class Level < Components::Bulma::Base
28
+ def initialize
29
+ @items = []
30
+ @left = []
31
+ @right = []
32
+ end
33
+
34
+ def view_template(&)
35
+ vanish(&)
36
+
37
+ div(class: "level") do
38
+ div(class: "level-left") do
39
+ @left.each { level_item(it) }
40
+ end
41
+
42
+ @items.each { level_item(it) }
43
+
44
+ div(class: "level-right") do
45
+ @right.each { level_item(it) }
46
+ end
47
+ end
48
+ end
49
+
50
+ def item(&content)
51
+ @items << content
52
+ end
53
+
54
+ def left(&content)
55
+ @left << content
56
+ end
57
+
58
+ def right(&content)
59
+ @right << content
60
+ end
61
+
62
+ private
63
+
64
+ def level_item(content)
65
+ div(class: "level-item") { content.call }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Navigation bar component for site navigation
6
+ #
7
+ # This component implements the [Bulma navbar](https://bulma.io/documentation/components/navbar/)
8
+ # interface. It provides a responsive navigation header with support for branding, navigation
9
+ # links, and dropdown menus, automatically collapsing on mobile devices.
10
+ #
11
+ # ## Example
12
+ #
13
+ # ```ruby
14
+ # render Components::Bulma::NavigationBar.new do |navbar|
15
+ # navbar.brand do
16
+ # a(href: "/", class: "navbar-item") { "My App" }
17
+ # end
18
+ #
19
+ # navbar.left do
20
+ # a(href: "/", class: "navbar-item") { "Home" }
21
+ # a(href: "/products", class: "navbar-item") { "Products" }
22
+ # end
23
+ #
24
+ # navbar.right do
25
+ # a(href: "/about", class: "navbar-item") { "About" }
26
+ #
27
+ # div(class: "navbar-item has-dropdown is-hoverable") do
28
+ # a(class: "navbar-link") { "Account" }
29
+ # render Components::Bulma::NavigationBarDropdown do |dropdown|
30
+ # dropdown.item "Sign In", "/login"
31
+ # dropdown.item "Register", "/register"
32
+ # end
33
+ # end
34
+ # end
35
+ # end
36
+ # ```
37
+ #
38
+ class NavigationBar < Components::Bulma::Base
39
+ def initialize
40
+ @brand = []
41
+ @left = []
42
+ @right = []
43
+ end
44
+
45
+ def view_template(&)
46
+ vanish(&)
47
+
48
+ nav(class: "navbar is-light block",
49
+ role: "navigation",
50
+ aria_label: "main navigation",
51
+ data: { controller: "bulma--navigation-bar" }) do
52
+ div(class: "container") do
53
+ div(class: "navbar-brand") do
54
+ @brand.each(&:call)
55
+
56
+ a(class: "navbar-burger",
57
+ role: "button",
58
+ aria_label: "menu",
59
+ aria_expanded: "false",
60
+ data: {
61
+ action: "bulma--navigation-bar#toggle",
62
+ "bulma--navigation-bar-target": "burger"
63
+ }) do
64
+ 4.times { span(aria_hidden: "true") }
65
+ end
66
+ end
67
+
68
+ div(class: "navbar-menu",
69
+ data: { "bulma--navigation-bar-target": "menu" }) do
70
+ div(class: "navbar-start") do
71
+ @left.each(&:call)
72
+ end
73
+
74
+ div(class: "navbar-end") do
75
+ @right.each(&:call)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def brand(&block)
83
+ @brand << block
84
+ end
85
+
86
+ def left(&block)
87
+ @left << block
88
+ end
89
+
90
+ def right(&block)
91
+ @right << block
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Dropdown component for the Bulma navigation bar
6
+ #
7
+ # This component implements the dropdown portion of the [Bulma navbar](https://bulma.io/documentation/components/navbar/#dropdown-menu).
8
+ # It provides a structured way to add dropdown menus to a navigation bar with headers, items, and dividers.
9
+ #
10
+ # ## Example
11
+ #
12
+ # ```ruby
13
+ # render Components::Bulma::NavigationBar.new do |navbar|
14
+ # navbar.brand_item "My App", "/"
15
+ #
16
+ # navbar.right do |menu|
17
+ # menu.dropdown "Account" do |dropdown|
18
+ # dropdown.header "User"
19
+ # dropdown.item "Profile", "/profile"
20
+ # dropdown.item "Settings", "/settings"
21
+ # dropdown.divider
22
+ # dropdown.item "Sign Out", "/logout"
23
+ # end
24
+ # end
25
+ # end
26
+ # ```
27
+ #
28
+ class NavigationBarDropdown < Components::Bulma::Base
29
+ def view_template(&)
30
+ div(class: "navbar-dropdown is-right", &)
31
+ end
32
+
33
+ def header(label)
34
+ div(class: "navbar-item header has-text-weight-medium") { label }
35
+ end
36
+
37
+ def item(label, path)
38
+ a(class: "navbar-item", href: path) { label }
39
+ end
40
+
41
+ def divider
42
+ hr(class: "navbar-divider")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Pagination component for navigating through multi-page content
6
+ #
7
+ # This component implements the [Bulma pagination](https://bulma.io/documentation/components/pagination/)
8
+ # interface, providing navigation controls for paginated content. It shows:
9
+ # - Previous/next page links
10
+ # - First/last page links when appropriate
11
+ # - Current page indicator
12
+ # - Ellipses for skipped page ranges
13
+ # - Summary of items being displayed
14
+ #
15
+ # ## Example
16
+ #
17
+ # ```ruby
18
+ # # In a controller action:
19
+ # @products = Product.page(params[:page]).per(20)
20
+ #
21
+ # # In the view:
22
+ # render Components::Bulma::Pagination.new(@products, ->(page) { products_path(page: page) })
23
+ # ```
24
+ #
25
+ class Pagination < Components::Bulma::Base
26
+ attr_reader :pager, :path_builder
27
+
28
+ # Initializes the pagination component
29
+ #
30
+ # @param pager [Object] An object that responds to:
31
+ # - `current_page` - Integer representing the current page number
32
+ # - `total_pages` - Integer representing the total number of pages
33
+ # - `per_page` - Integer representing the number of items per page
34
+ # - `total_count` - Integer representing the total number of items
35
+ # - `previous_page` - Integer or nil representing the previous page number
36
+ # - `next_page` - Integer or nil representing the next page number
37
+ # @param path_builder [Proc] A callable that takes a page number and returns a URL string
38
+ def initialize(pager, path_builder)
39
+ @pager = pager
40
+ @path_builder = path_builder
41
+ end
42
+
43
+ def view_template
44
+ return unless pager.total_pages > 1
45
+
46
+ div(class: "pagination-container mt-5") do
47
+ nav(class: "pagination", role: "navigation", aria_label: "pagination") do
48
+ # Previous page link
49
+ if pager.previous_page
50
+ a(class: "pagination-previous", href: page_url(pager.previous_page)) { "Previous" }
51
+ else
52
+ a(class: "pagination-previous", disabled: true) { "Previous" }
53
+ end
54
+
55
+ # Next page link
56
+ if pager.next_page
57
+ a(class: "pagination-next", href: page_url(pager.next_page)) { "Next" }
58
+ else
59
+ a(class: "pagination-next", disabled: true) { "Next" }
60
+ end
61
+
62
+ # Page number links
63
+ ul(class: "pagination-list") do
64
+ # First page and ellipsis if needed
65
+ if pager.current_page > 3
66
+ render_page_item(1)
67
+ render_ellipsis if pager.current_page > 4
68
+ end
69
+
70
+ # Pages around current page
71
+ page_window.each do |page_number|
72
+ render_page_item(page_number)
73
+ end
74
+
75
+ # Ellipsis and last page if needed
76
+ if pager.current_page < pager.total_pages - 2
77
+ render_ellipsis if pager.current_page < pager.total_pages - 3
78
+ render_page_item(pager.total_pages)
79
+ end
80
+ end
81
+ end
82
+
83
+ div(class: "has-text-centered mt-2 is-size-7") do
84
+ start_item = ((pager.current_page - 1) * pager.per_page) + 1
85
+ end_item = [start_item + pager.per_page - 1, pager.total_count].min
86
+
87
+ plain "Showing #{start_item}-#{end_item} of #{pager.total_count} items"
88
+ end
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def render_page_item(page_number)
95
+ li do
96
+ if page_number == pager.current_page
97
+ a(class: "pagination-link is-current",
98
+ aria_label: "Page #{page_number}",
99
+ aria_current: "page") { page_number.to_s }
100
+ else
101
+ a(class: "pagination-link",
102
+ href: page_url(page_number),
103
+ aria_label: "Go to page #{page_number}") { page_number.to_s }
104
+ end
105
+ end
106
+ end
107
+
108
+ def render_ellipsis
109
+ li { span(class: "pagination-ellipsis") { "…" } }
110
+ end
111
+
112
+ def page_window
113
+ start_page = [pager.current_page - 2, 1].max
114
+ end_page = [pager.current_page + 2, pager.total_pages].min
115
+ (start_page..end_page).to_a
116
+ end
117
+
118
+ def page_url(page_number)
119
+ @path_builder.call(page_number)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Table component for data display
6
+ #
7
+ # This component implements the [Bulma table](https://bulma.io/documentation/elements/table/)
8
+ # interface, providing a way to display data in rows and columns with customizable
9
+ # headers and formatting options.
10
+ #
11
+ # ## Example
12
+ #
13
+ # ```ruby
14
+ # users = User.all
15
+ #
16
+ # render Components::Bulma::Table.new(users) do |table|
17
+ # table.column "Name" do |user|
18
+ # user.full_name
19
+ # end
20
+ #
21
+ # table.column "Email" do |user|
22
+ # user.email
23
+ # end
24
+ #
25
+ # table.column "Actions" do |user|
26
+ # link_to "Edit", edit_user_path(user), class: "button is-small"
27
+ # end
28
+ # end
29
+ # ```
30
+ #
31
+ class Table < Components::Bulma::Base
32
+ def initialize(rows, id = nil)
33
+ @id = id || rows.first&.model_name&.plural
34
+ @rows = rows
35
+ @columns = []
36
+ end
37
+
38
+ def view_template(&)
39
+ vanish(&)
40
+
41
+ table(id: @id, class: "table is-fullwidth") do
42
+ thead do
43
+ @columns.each do |column|
44
+ table_header(column)
45
+ end
46
+ end
47
+
48
+ tbody do
49
+ @rows.each do |row|
50
+ tr do
51
+ @columns.each do |column|
52
+ td(**column[:html_attributes]) { column[:content].call(row) }
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ pagination
59
+ end
60
+ end
61
+
62
+ def column(header, **html_attributes, &content)
63
+ @columns << { header:, html_attributes:, content: }
64
+ end
65
+
66
+ def paginate(&path_builder)
67
+ @path_builder = path_builder
68
+ end
69
+
70
+ private
71
+
72
+ # this derives a th class from the column html attributes
73
+ # perhaps a better way would be pre-defined pairs?
74
+ def table_header(column)
75
+ attributes = {}
76
+ attributes[:class] = header_alignment(column[:html_attributes])
77
+ th(**attributes) { column[:header] }
78
+ end
79
+
80
+ def header_alignment(html_attributes)
81
+ classes = html_attributes[:class]
82
+ return if classes.nil?
83
+
84
+ if classes&.include?("has-text-right") || classes&.include?("amount-display")
85
+ "has-text-right"
86
+ elsif classes&.include?("has-text-centered")
87
+ "has-text-centered"
88
+ end
89
+ end
90
+
91
+ def pagination
92
+ return unless @path_builder
93
+
94
+ tfoot do
95
+ tr do
96
+ td(class: "py-0", colspan: @columns.size) do
97
+ Pagination(@rows, @path_builder)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Components
4
+ module Bulma
5
+ # Tabs component for toggling between different content sections
6
+ #
7
+ # This component implements the [Bulma tabs](https://bulma.io/documentation/components/tabs/)
8
+ # interface, providing a way to toggle between different content sections using
9
+ # tabbed navigation. Includes support for icons and active state management.
10
+ #
11
+ # ## Example
12
+ #
13
+ # ```ruby
14
+ # render Components::Bulma::Tabs.new do |tabs|
15
+ # tabs.tab(id: "profile", title: "Profile", active: true) do
16
+ # "Profile content goes here"
17
+ # end
18
+ #
19
+ # tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
20
+ # "Settings content goes here"
21
+ # end
22
+ #
23
+ # tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
24
+ # "Notifications content goes here"
25
+ # end
26
+ # end
27
+ # ```
28
+ #
29
+ class Tabs < Components::Bulma::Base
30
+ Tab = Data.define(:id, :title, :icon, :active)
31
+ Content = Data.define(:id, :block, :active)
32
+
33
+ def initialize
34
+ @tabs = []
35
+ @contents = []
36
+ end
37
+
38
+ def tab(id:, title:, icon: nil, active: false, &block)
39
+ @tabs << Tab.new(id:, title:, icon:, active:)
40
+ @contents << Content.new(id:, block:, active:)
41
+ end
42
+
43
+ def view_template(&)
44
+ vanish(&)
45
+
46
+ div(data: { controller: "tabs" }) do
47
+ div(class: "tabs is-boxed") do
48
+ ul do
49
+ @tabs.each do |tab|
50
+ li(
51
+ data: {
52
+ tabs_target: "tab",
53
+ tab_content: tab.id,
54
+ action: "click->tabs#showTabContent"
55
+ },
56
+ class: tab.active ? "is-active" : ""
57
+ ) do
58
+ a do
59
+ icon_span(tab.icon, "mr-1") if tab.icon
60
+ span { tab.title }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ @contents.each do |content|
68
+ div(id: content.id,
69
+ class: content.active ? "" : "hidden",
70
+ data: { tabs_target: "content" }) do
71
+ content.block.call
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A collection of Bulma components built with Phlex
4
+ #
5
+ # This module provides a set of components that implement the [Bulma CSS framework](https://bulma.io/)
6
+ # using the Phlex view component library. These components make it easy to build
7
+ # Bulma-styled applications with a Ruby-focused component API.
8
+ #
9
+ module Components
10
+ module Bulma
11
+ extend Phlex::Kit
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bulma-phlex
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Todd Kummer
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: phlex
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 2.0.2
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 2.0.2
26
+ - !ruby/object:Gem::Dependency
27
+ name: actionpack
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: actionview
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: activesupport
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: minitest-difftastic
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ description: Add Bulma components including Card, Level, NavigationBar, Pagination,
83
+ Table, and Tabs to your Phlex application.
84
+ email:
85
+ - todd@rockridgesolutions.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - Rakefile
92
+ - lib/bulma-phlex.rb
93
+ - lib/bulma_phlex/version.rb
94
+ - lib/components/bulma.rb
95
+ - lib/components/bulma/base.rb
96
+ - lib/components/bulma/card.rb
97
+ - lib/components/bulma/level.rb
98
+ - lib/components/bulma/navigation_bar.rb
99
+ - lib/components/bulma/navigation_bar_dropdown.rb
100
+ - lib/components/bulma/pagination.rb
101
+ - lib/components/bulma/table.rb
102
+ - lib/components/bulma/tabs.rb
103
+ homepage: https://github.com/RockSolt/bulma-phlex
104
+ licenses:
105
+ - MIT
106
+ metadata:
107
+ rubygems_mfa_required: 'true'
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: 3.4.0
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubygems_version: 3.6.7
123
+ specification_version: 4
124
+ summary: Build Bulma components with Phlex.
125
+ test_files: []