flowbite-components 0.1.2 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afc7f639fa9f28b2310d7f68cd3d8939e3eaa526ba80ee028c471664597e4581
4
- data.tar.gz: 1b4e73f0bd471b9b3d36db8aba2e614e28f5573cbf7fd214de360a985767eade
3
+ metadata.gz: 0013a87a4e4924d4ca2fe6f3ba8eff3f9f266be23a15b07cbddd25164d436805
4
+ data.tar.gz: d50dd418f1403dc2375754f4b0d295c9c2d4f1a09c0904bffce88fc76268135b
5
5
  SHA512:
6
- metadata.gz: 6d56824ba5b7d0c13bca6b31e4dac90a1859ec35c3c50478b90a4f67aae2cd7e7efcfb53dc29ddfcae9f4839695610ea5602e0f29b2ddd53c64a00b34562806d
7
- data.tar.gz: efe21d27318e44196ecd0024663a143ba577ab8b2ca0a2b9e085263d4be3d7f472c22c68c5442d802c58717306a575d320325c4d9d8bb3d5f8b5e48fb444c992
6
+ metadata.gz: e410ab1f18d6264c18cae8e5c0322c612422e33aa4136ab99ff21e6b0564ceaeb95decd262a265d72b9029022ff76965c19eeb0438d3d295c85cd2962986a3ab
7
+ data.tar.gz: 168b101505fbddfc952c334cc169c1e12e5f129beb8c3f884ffd32047c0548bd22655fd03a6da3589f9ff5071c94850d727761c7aacb96b2712c09420657147c
data/CHANGELOG.md CHANGED
@@ -7,15 +7,43 @@ This project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
8
  ### Added
9
9
 
10
- * Button component (first component, wee!)
11
- * Input components
12
- * InputField components
13
- * Basic Card component
10
+ ### Changed
11
+
12
+ ### Removed
14
13
 
15
- ### Changes
16
14
 
17
- *
15
+ ## [0.1.4]
16
+
17
+ ### Added
18
+
19
+ * Flowbite::Link component to render links.
20
+ * Flowbite::Card now displays a title via the title argument/slot.
21
+ * Improved error message when an unknown style is requested.
22
+ * Input-elements now support forms without an object; ie forms built with `form_tag` - not `form_for` or `form_with`.
23
+
24
+ ### Changed
25
+
26
+ * [BREAKING] All components now use Flowbite 4 style classes. This adds the option for easier styling, uses semantic variant names, and keeps us up to date with Flowbite proper.
27
+ * Extra CSS classes passed to components in the `class` argument are now added to the default classes from the component. This optimizes for minor tweaks and additions, which is likely to be the most common use case. If you need to replace all classes on the root element of the component, pass them in `options[:class]` instead.
18
28
 
19
29
  ### Removed
20
30
 
21
- *
31
+ * [BREAKING] Color-specific styles from Flowbite::Button, ie `alternative`, `green`, `light`, `purple`, `red`, `yellow`.
32
+
33
+
34
+ ## [0.1.3]
35
+
36
+ ### Added
37
+
38
+ * Options to Flowbite::InputField::Checkbox and Flowbite::Input::Checkbox that allow you to change the submitted value.
39
+ * Options added for Flowbite::Input::Select - :multiple and :include_blank. These can now be passed to either the input itself or Flowbite::InputField::Select
40
+
41
+
42
+ ## [0.1.2]
43
+
44
+ ### Added
45
+
46
+ * Button component (first component, wee!)
47
+ * Input components
48
+ * InputField components
49
+ * Basic Card component
data/README.md CHANGED
@@ -22,7 +22,7 @@ Flowbite Components provides a comprehensive library of UI components following
22
22
  Add the gem to your application's Gemfile:
23
23
 
24
24
  ```ruby
25
- gem 'flowbite-components'
25
+ gem "flowbite-components"
26
26
  ```
27
27
 
28
28
  Then execute:
@@ -31,9 +31,9 @@ Then execute:
31
31
  bundle install
32
32
  ```
33
33
 
34
- ### Configuration
34
+ ### tailwindcss-rails
35
35
 
36
- Make sure you have Tailwind CSS installed in your Rails application. We recommend using the [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) gem:
36
+ Tailwind needs to be able to look through your code in order to generate the final CSS file with the class names you actually use. To allow Tailwind to find CSS class names inside flowbite-components you need to use [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) gem:
37
37
 
38
38
  ```ruby
39
39
  gem "tailwindcss-rails", ">= 4.3.0"
@@ -44,17 +44,19 @@ gem "tailwindcss-rails", ">= 4.3.0"
44
44
  Install Flowbite as an npm dependency:
45
45
 
46
46
  ```bash
47
- npm install flowbite
47
+ yarn add flowbite
48
48
  ```
49
49
 
50
50
  Add Flowbite to your Tailwind CSS configuration. In your `app/assets/tailwind/application.css`:
51
51
 
52
52
  ```css
53
- @import "flowbite/src/themes/default";
54
53
  @plugin "flowbite/plugin";
54
+ @import "flowbite/src/themes/default";
55
55
  @import "../builds/tailwind/flowbite_components";
56
56
  ```
57
57
 
58
+ If you want to use one of the other [Flowbite themes](https://flowbite.com/docs/customize/theming/), change `@import "flowbite/src/themes/default";` accordingly.
59
+
58
60
  ## Usage examples
59
61
 
60
62
  ### Basic Form Field
@@ -217,6 +219,33 @@ renders
217
219
  - **Outline Button**: `Flowbite::Button::Outline`
218
220
  - **Pill Button**: `Flowbite::Button::Pill`
219
221
 
222
+ #### Cards
223
+ - **Card**: `Flowbite::Card` (default card with content and title)
224
+
225
+ #### Navigation
226
+ - **Link**: `Flowbite::Link` (default link styling)
227
+
228
+
229
+ ## Principles
230
+
231
+ ### CSS classes are additive
232
+
233
+ Passing classes via the `class` argument to a component adds the classes to the
234
+ default ones instead of replacing them.
235
+
236
+ ```ruby
237
+ render(Component.new(class: "these are added"))
238
+ ```
239
+
240
+ This makes for easier customization of components, where you don't have to
241
+ recreate the entire classlist, ie in order to increase sizes or add margins or
242
+ whatever.
243
+
244
+ If you want to replace the entire class attribute for a component, pass it as part of the `options` hash, ie
245
+
246
+ ```ruby
247
+ render(Component.new(options: {class: "these replace the classes"}))
248
+ ```
220
249
 
221
250
  ## Development
222
251
 
@@ -242,11 +271,12 @@ bundle exec rake install
242
271
 
243
272
  ### Component Previews
244
273
 
245
- This library includes Lookbook previews for all components. To view them:
274
+ This library includes a demo application with previews for all components. To view them:
246
275
 
247
- 1. Add Lookbook to your development dependencies
248
- 2. Run `rails server`
249
- 3. Visit `/rails/lookbook`
276
+ 1. cd demo
277
+ 2. Run `bundle && npm install`
278
+ 3. Run `rails server`
279
+ 4. Visit `http://localhost:3000/rails/lookbook`
250
280
 
251
281
  ## Contributing
252
282
 
@@ -4,18 +4,33 @@ module Flowbite
4
4
  class Button
5
5
  class Outline < Flowbite::Button
6
6
  class << self
7
- # rubocop:disable Layout/LineLength
7
+ # rubocop:disable Layout/LineLength, Metrics/MethodLength
8
8
  def styles
9
- {
10
- default: Flowbite::Style.new(
11
- default: ["text-blue-700", "hover:text-white", "border", "border-blue-700", "hover:bg-blue-800", "focus:ring-4", "focus:outline-none", "focus:ring-blue-300", "font-medium", "rounded-lg", "text-center", "me-2", "mb-2", "dark:border-blue-500", "dark:text-blue-500", "dark:hover:text-white", "dark:hover:bg-blue-500", "dark:focus:ring-blue-800"]
12
- ),
13
- green: Flowbite::Style.new(
14
- default: ["text-green-700", "hover:text-white", "border", "border-green-700", "hover:bg-green-800", "focus:ring-4", "focus:outline-none", "focus:ring-green-300", "font-medium", "rounded-lg", "text-center", "me-2", "mb-2", "dark:border-green-500", "dark:text-green-500", "dark:hover:text-white", "dark:hover:bg-green-600", "dark:focus:ring-green-800"]
15
- )
16
- }
9
+ Flowbite::Styles.from_hash({
10
+ danger: {
11
+ default: ["focus:outline-none", "text-danger", "bg-transparent", "box-border", "border", "border-danger", "hover:text-white", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
12
+ },
13
+ dark: {
14
+ default: ["focus:outline-none", "text-dark", "bg-transparent", "box-border", "border", "border-dark", "hover:text-white", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
15
+ },
16
+ default: {
17
+ default: ["focus:outline-none", "text-brand", "bg-transparent", "box-border", "border", "border-brand", "hover:text-white", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
18
+ },
19
+ secondary: {
20
+ default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
21
+ },
22
+ success: {
23
+ default: ["focus:outline-none", "text-success", "bg-transparent", "box-border", "border", "border-success", "hover:text-white", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
24
+ },
25
+ tertiary: {
26
+ default: ["focus:outline-none", "text-body", "bg-transparent", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
27
+ },
28
+ warning: {
29
+ default: ["focus:outline-none", "text-warning", "bg-transparent", "box-border", "border", "border-warning", "hover:text-white", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base", "text-center", "me-2", "mb-2"]
30
+ }
31
+ }.freeze)
17
32
  end
18
- # rubocop:enable Layout/LineLength
33
+ # rubocop:enable Layout/LineLength, Metrics/MethodLength
19
34
  end
20
35
  end
21
36
  end
@@ -6,32 +6,32 @@ module Flowbite
6
6
  class << self
7
7
  # rubocop:disable Layout/LineLength, Metrics/MethodLength
8
8
  def styles
9
- {
10
- alternative: Flowbite::Style.new(
11
- default: ["text-sm", "font-medium", "text-gray-900", "focus:outline-none", "bg-white", "rounded-full", "border", "border-gray-200", "hover:bg-gray-100", "hover:text-blue-700", "focus:z-10", "focus:ring-4", "focus:ring-gray-100", "dark:focus:ring-gray-700", "dark:bg-gray-800", "dark:text-gray-400", "dark:border-gray-600", "dark:hover:text-white", "dark:hover:bg-gray-700"]
12
- ),
13
- dark: Flowbite::Style.new(
14
- default: ["text-white", "bg-gray-800", "hover:bg-gray-900", "focus:outline-none", "focus:ring-4", "focus:ring-gray-300", "font-medium", "rounded-full", "dark:bg-gray-800", "dark:hover:bg-gray-700", "dark:focus:ring-gray-700", "dark:border-gray-700"]
15
- ),
16
- default: Flowbite::Style.new(
17
- default: ["text-white", "bg-blue-700", "hover:bg-blue-800", "focus:outline-none", "focus:ring-4", "focus:ring-blue-300", "font-medium", "rounded-full", "text-center", "dark:bg-blue-600", "dark:hover:bg-blue-700", "dark:focus:ring-blue-800"]
18
- ),
19
- green: Flowbite::Style.new(
20
- default: ["text-white", "bg-green-700", "hover:bg-green-800", "focus:outline-none", "focus:ring-4", "focus:ring-green-300", "font-medium", "rounded-full", "text-center", "dark:bg-green-600", "dark:hover:bg-green-700", "dark:focus:ring-green-800"]
21
- ),
22
- light: Flowbite::Style.new(
23
- default: ["text-gray-900", "bg-white", "border", "border-gray-300", "focus:outline-none", "hover:bg-gray-100", "focus:ring-4", "focus:ring-gray-100", "font-medium", "rounded-full", "dark:bg-gray-800", "dark:text-white", "dark:border-gray-600", "dark:hover:bg-gray-700", "dark:hover:border-gray-600", "dark:focus:ring-gray-700"]
24
- ),
25
- purple: Flowbite::Style.new(
26
- default: ["text-white", "bg-purple-700", "hover:bg-purple-800", "focus:outline-none", "focus:ring-4", "focus:ring-purple-300", "font-medium", "rounded-full", "text-center", "dark:bg-purple-600", "dark:hover:bg-purple-700", "dark:focus:ring-purple-900"]
27
- ),
28
- red: Flowbite::Style.new(
29
- default: ["text-white", "bg-red-700", "hover:bg-red-800", "focus:outline-none", "focus:ring-4", "focus:ring-red-300", "font-medium", "rounded-full", "text-center", "dark:bg-red-600", "dark:hover:bg-red-700", "dark:focus:ring-red-900"]
30
- ),
31
- yellow: Flowbite::Style.new(
32
- default: ["text-white", "bg-yellow-400", "hover:bg-yellow-500", "focus:outline-none", "focus:ring-4", "focus:ring-yellow-300", "font-medium", "rounded-full", "text-center", "dark:focus:ring-yellow-900"]
33
- )
34
- }
9
+ Flowbite::Styles.from_hash({
10
+ danger: {
11
+ default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
12
+ },
13
+ dark: {
14
+ default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
15
+ },
16
+ default: {
17
+ default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
18
+ },
19
+ ghost: {
20
+ default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-full", "text-center"]
21
+ },
22
+ secondary: {
23
+ default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
24
+ },
25
+ success: {
26
+ default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
27
+ },
28
+ tertiary: {
29
+ default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
30
+ },
31
+ warning: {
32
+ default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-full", "text-center"]
33
+ }
34
+ }.freeze)
35
35
  end
36
36
  # rubocop:enable Layout/LineLength, Metrics/MethodLength
37
37
  end
@@ -11,9 +11,9 @@ module Flowbite
11
11
  # as HTML attributes.
12
12
  class Button < ViewComponent::Base
13
13
  SIZES = {
14
- xs: ["text-xs", "px-3", "py-2"],
14
+ xs: ["text-xs", "px-3", "py-1.5"],
15
15
  sm: ["text-sm", "px-3", "py-2"],
16
- default: ["text-sm", "px-5", "py-2.5"],
16
+ default: ["text-sm", "px-4", "py-2.5"],
17
17
  lg: ["text-base", "px-5", "py-3"],
18
18
  xl: ["text-base", "px-6", "py-3.5"]
19
19
  }.freeze
@@ -31,39 +31,42 @@ module Flowbite
31
31
 
32
32
  # rubocop:disable Layout/LineLength
33
33
  def styles
34
- {
35
- alternative: Flowbite::Style.new(
36
- default: ["font-medium", "text-gray-900", "focus:outline-none", "bg-white", "rounded-lg", "border", "border-gray-200", "hover:bg-gray-100", "hover:text-blue-700", "focus:z-10", "focus:ring-4", "focus:ring-gray-100", "dark:focus:ring-gray-700", "dark:bg-gray-800", "dark:text-gray-400", "dark:border-gray-600", "dark:hover:text-white", "dark:hover:bg-gray-700"]
37
- ),
38
- dark: Flowbite::Style.new(
39
- default: ["text-white", "bg-gray-800", "hover:bg-gray-900", "focus:ring-4", "focus:ring-gray-300", "font-medium", "rounded-lg", "dark:bg-gray-800", "dark:hover:bg-gray-700", "dark:focus:ring-gray-700", "dark:border-gray-700"]
40
- ),
41
- default: Flowbite::Style.new(
42
- default: ["text-white", "bg-blue-700", "hover:bg-blue-800", "focus:ring-4", "focus:ring-blue-300", "font-medium", "rounded-lg", "dark:bg-blue-600", "dark:hover:bg-blue-700", "focus:outline-none", "dark:focus:ring-blue-800"]
43
- ),
44
- green: Flowbite::Style.new(
45
- default: ["focus:outline-none", "text-white", "bg-green-700", "hover:bg-green-800", "focus:ring-4", "focus:ring-green-300", "font-medium", "rounded-lg", "dark:bg-green-600", "dark:hover:bg-green-700", "dark:focus:ring-green-800"]
46
- ),
47
- light: Flowbite::Style.new(
48
- default: ["text-gray-900", "bg-white", "border", "border-gray-300", "hover:bg-gray-100", "focus:ring-4", "focus:ring-gray-100", "font-medium", "rounded-lg", "dark:bg-gray-800", "dark:text-white", "dark:border-gray-600", "dark:hover:bg-gray-700", "dark:hover:border-gray-600", "dark:focus:ring-gray-700"]
49
- ),
50
- purple: Flowbite::Style.new(
51
- default: ["focus:outline-none", "text-white", "bg-purple-700", "hover:bg-purple-800", "focus:ring-4", "focus:ring-purple-300", "font-medium", "rounded-lg", "dark:bg-purple-600", "dark:hover:bg-purple-700", "dark:focus:ring-purple-900"]
52
- ),
53
- red: Flowbite::Style.new(
54
- default: ["focus:outline-none", "text-white", "bg-red-700", "hover:bg-red-800", "focus:ring-4", "focus:ring-red-300", "font-medium", "rounded-lg", "dark:bg-red-600", "dark:hover:bg-red-700", "dark:focus:ring-red-900"]
55
- ),
56
- yellow: Flowbite::Style.new(
57
- default: ["focus:outline-none", "text-white", "bg-yellow-400", "hover:bg-yellow-500", "focus:ring-4", "focus:ring-yellow-300", "font-medium", "rounded-lg", "dark:focus:ring-yellow-900"]
58
- )
59
- }.freeze
34
+ Flowbite::Styles.from_hash(
35
+ {
36
+ danger: {
37
+ default: ["focus:outline-none", "text-white", "bg-danger", "box-border", "border", "border-transparent", "hover:bg-danger-strong", "focus:ring-4", "focus:ring-danger-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
38
+ },
39
+ dark: {
40
+ default: ["focus:outline-none", "text-white", "bg-dark", "box-border", "border", "border-transparent", "hover:bg-dark-strong", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
41
+ },
42
+ default: {
43
+ default: ["focus:outline-none", "text-white", "bg-brand", "box-border", "border", "border-transparent", "hover:bg-brand-strong", "focus:ring-4", "focus:ring-brand-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
44
+ },
45
+ ghost: {
46
+ default: ["focus:outline-none", "text-heading", "bg-transparent", "box-border", "border", "border-transparent", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "font-medium", "leading-5", "rounded-base"]
47
+ },
48
+ secondary: {
49
+ default: ["focus:outline-none", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "focus:ring-4", "focus:ring-neutral-tertiary", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
50
+ },
51
+ success: {
52
+ default: ["focus:outline-none", "text-white", "bg-success", "box-border", "border", "border-transparent", "hover:bg-success-strong", "focus:ring-4", "focus:ring-success-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
53
+ },
54
+ tertiary: {
55
+ default: ["focus:outline-none", "text-body", "bg-neutral-primary-soft", "box-border", "border", "border-default", "hover:bg-neutral-secondary-medium", "focus:ring-4", "focus:ring-neutral-tertiary-soft", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
56
+ },
57
+ warning: {
58
+ default: ["focus:outline-none", "text-white", "bg-warning", "box-border", "border", "border-transparent", "hover:bg-warning-strong", "focus:ring-4", "focus:ring-warning-medium", "shadow-xs", "font-medium", "leading-5", "rounded-base"]
59
+ }
60
+ }.freeze
61
+ )
60
62
  end
61
63
  # rubocop:enable Layout/LineLength
62
64
  end
63
65
 
64
66
  attr_reader :button_attributes, :size, :style
65
67
 
66
- def initialize(size: :default, style: :default, **button_attributes)
68
+ def initialize(class: nil, size: :default, style: :default, **button_attributes)
69
+ @class = Array.wrap(binding.local_variable_get(:class))
67
70
  @size = size
68
71
  @style = style
69
72
  @button_attributes = button_attributes
@@ -80,7 +83,7 @@ module Flowbite
80
83
  private
81
84
 
82
85
  def classes
83
- self.class.classes(size: size, state: :default, style: style)
86
+ self.class.classes(size: size, state: :default, style: style) + @class
84
87
  end
85
88
 
86
89
  def options
@@ -0,0 +1,7 @@
1
+ <%= content_tag(:div, card_options) do %>
2
+ <%= title %>
3
+
4
+ <% if content.present? %>
5
+ <div class="font-normal text-body"><%= content %></div>
6
+ <% end %>
7
+ <% end %>
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Flowbite
4
+ class Card
5
+ # Renders the title of a card element.
6
+ class Title < ViewComponent::Base
7
+ class << self
8
+ def classes(state: :default, style: :default)
9
+ style = styles.fetch(style)
10
+ style.fetch(state)
11
+ end
12
+
13
+ # rubocop:disable Layout/LineLength
14
+ def styles
15
+ Flowbite::Styles.from_hash(
16
+ {
17
+ default: {
18
+ default: ["mb-2", "text-2xl", "font-semibold", "tracking-tight", "text-heading"]
19
+ }
20
+ }.freeze
21
+ )
22
+ end
23
+ # rubocop:enable Layout/LineLength
24
+ end
25
+
26
+ def call
27
+ title_options = {
28
+ class: self.class.classes
29
+ }.merge(@options)
30
+
31
+ content_tag(:h5, content, **title_options)
32
+ end
33
+
34
+ def initialize(**options)
35
+ @options = options || {}
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flowbite
2
4
  # Renders a card element.
3
5
  #
4
6
  # See https://flowbite.com/docs/components/cards/
5
7
  class Card < ViewComponent::Base
8
+ renders_one :title
9
+
6
10
  class << self
7
11
  def classes(state: :default, style: :default)
8
12
  style = styles.fetch(style)
@@ -11,33 +15,72 @@ module Flowbite
11
15
 
12
16
  # rubocop:disable Layout/LineLength
13
17
  def styles
14
- {
15
- default: Flowbite::Style.new(
16
- default: ["p-6", "bg-white", "border", "border-gray-200", "rounded-lg", "shadow-sm", "dark:bg-gray-800", "dark:border-gray-700"]
17
- )
18
- }.freeze
18
+ Flowbite::Styles.from_hash(
19
+ {
20
+ default: {
21
+ default: ["p-6", "bg-neutral-primary-soft", "border", "border-default", "rounded-base", "shadow-xs"]
22
+ }
23
+ }.freeze
24
+ )
19
25
  end
20
26
  # rubocop:enable Layout/LineLength
21
27
  end
22
28
 
23
- def call
24
- card_options = {}
25
- card_options[:class] = self.class.classes + @class
26
-
27
- content_tag(:div, card_options.merge(@options)) do
28
- concat(content_tag(:div, content, class: "font-normal text-gray-700 dark:text-gray-400"))
29
- end
30
- end
31
-
32
29
  # @param class [Array<String>] Additional CSS classes for the card
33
30
  # container.
34
31
  #
35
32
  # @param options [Hash] Additional HTML options for the card container
36
33
  # (e.g., custom classes, data attributes). These options are merged into
37
34
  # the card's root element.
38
- def initialize(class: [], options: {})
35
+ #
36
+ # @param title [Hash] An optional title for the card. If provided,
37
+ # it will be rendered at the top of the card in a h5 tag using the
38
+ # Card::Title component. The hash can contain:
39
+ # - `content`: The text content of the title
40
+ # - `options`: Additional HTML options to pass to the title element
41
+ # Alternatively, you can use the `title` slot to provide the entire
42
+ # title element yourself.
43
+ def initialize(class: [], options: {}, title: {})
39
44
  @class = Array(binding.local_variable_get(:class)) || []
40
45
  @options = options || {}
46
+ @title = title
47
+ end
48
+
49
+ protected
50
+
51
+ def card_options
52
+ card_options = {}
53
+ card_options[:class] = self.class.classes + @class
54
+ card_options.merge(@options)
55
+ end
56
+
57
+ # Returns the HTML to use for the title element if any
58
+ def default_title
59
+ component = Flowbite::Card::Title.new(**default_title_options)
60
+
61
+ if default_title_content
62
+ component.with_content(default_title_content)
63
+ else
64
+ component
65
+ end
66
+
67
+ render(component)
68
+ end
69
+
70
+ def default_title_content
71
+ return nil unless @title
72
+
73
+ @title[:content]
74
+ end
75
+
76
+ # @return [Hash] The options to pass to the default title component
77
+ def default_title_options
78
+ title_options = @title.dup
79
+ title_options[:options] || {}
80
+ end
81
+
82
+ def title?
83
+ @title.present?
41
84
  end
42
85
  end
43
86
  end
@@ -9,6 +9,9 @@ module Flowbite
9
9
  #
10
10
  # https://flowbite.com/docs/forms/checkbox/
11
11
  class Checkbox < Field
12
+ DEFAULT_CHECKED_VALUE = "1"
13
+ DEFAULT_UNCHECKED_VALUE = "0"
14
+
12
15
  class << self
13
16
  # Checkboxes only have their default size.
14
17
  def sizes
@@ -19,19 +22,54 @@ module Flowbite
19
22
 
20
23
  # rubocop:disable Layout/LineLength
21
24
  def styles
22
- {
23
- default: Flowbite::Style.new(
24
- default: ["text-blue-600", "bg-gray-100", "border-gray-300", "rounded-sm", "focus:ring-blue-500", "dark:focus:ring-blue-600", "dark:ring-offset-gray-800", "focus:ring-2", "dark:bg-gray-700", "dark:border-gray-600"],
25
- disabled: ["text-blue-600", "bg-gray-100", "border-gray-300", "rounded-sm", "focus:ring-blue-500", "dark:focus:ring-blue-600", "dark:ring-offset-gray-800", "focus:ring-2", "dark:bg-gray-700", "dark:border-gray-600"],
26
- error: ["text-red-600", "bg-red-50", "border-red-500", "rounded-sm", "focus:ring-red-500", "dark:focus:ring-red-600", "dark:ring-offset-gray-800", "focus:ring-2", "dark:bg-gray-700", "dark:border-red-500"]
27
- )
28
- }.freeze
25
+ Flowbite::Styles.from_hash(
26
+ {
27
+ default: {
28
+ default: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "rounded-sm", "focus:ring-brand", "focus:ring-2"],
29
+ disabled: ["text-brand", "bg-neutral-secondary-medium", "border-default-medium", "rounded-sm", "focus:ring-brand", "focus:ring-2", "cursor-not-allowed"],
30
+ error: ["text-danger", "bg-danger-soft", "border-danger-subtle", "rounded-sm", "focus:ring-danger", "focus:ring-2"]
31
+ }
32
+ }.freeze
33
+ )
29
34
  end
30
35
  end
31
36
 
37
+ # Returns the HTML to use for the actual input field element.
38
+ def call
39
+ @form.send(
40
+ input_field_type,
41
+ @attribute,
42
+ input_options,
43
+ checked_value,
44
+ unchecked_value
45
+ )
46
+ end
47
+
48
+ def initialize(attribute:, form:, class: nil, disabled: false, options: {}, size: :default, unchecked_value: DEFAULT_UNCHECKED_VALUE, value: DEFAULT_CHECKED_VALUE)
49
+ super(attribute: attribute, class: binding.local_variable_get(:class), form: form, disabled: disabled, options: options, size: size)
50
+ @unchecked_value = unchecked_value
51
+ @value = value
52
+ end
53
+
32
54
  def input_field_type
33
55
  :check_box
34
56
  end
57
+
58
+ # Returns the options argument for the input field
59
+ def input_options
60
+ {
61
+ class: classes,
62
+ disabled: disabled?
63
+ }.merge(options)
64
+ end
65
+
66
+ private
67
+
68
+ def checked_value
69
+ @value
70
+ end
71
+
72
+ attr_reader :unchecked_value
35
73
  end
36
74
  end
37
75
  end