tramway 3.0.4.2 → 3.1
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 +20 -9
- data/app/assets/javascripts/tramway/ui_checkbox_controller.js +36 -0
- data/app/components/tailwind_component.rb +21 -24
- data/app/components/tramway/button_component.rb +33 -21
- data/app/components/tramway/chat_component.html.haml +6 -6
- data/app/components/tramway/chats/message_component.html.haml +2 -2
- data/app/components/tramway/chats/message_component.rb +2 -2
- data/app/components/tramway/chats/messages/container_component.html.haml +3 -3
- data/app/components/tramway/chats/messages/container_component.rb +4 -9
- data/app/components/tramway/chats/messages/table_component.html.haml +1 -1
- data/app/components/tramway/colors_methods.rb +3 -3
- data/app/components/tramway/containers/main_component.rb +1 -1
- data/app/components/tramway/containers/narrow_component.rb +2 -2
- data/app/components/tramway/flash_component.html.haml +0 -1
- data/app/components/tramway/flash_component.rb +25 -10
- data/app/components/tramway/form/builder.rb +1 -1
- data/app/components/tramway/form/checkbox_component.html.haml +26 -4
- data/app/components/tramway/form/checkbox_component.rb +32 -1
- data/app/components/tramway/form/label_component.html.haml +1 -1
- data/app/components/tramway/form/label_component.rb +2 -3
- data/app/components/tramway/form/tramway_select/dropdown_container_component.rb +2 -5
- data/app/components/tramway/form/tramway_select/item_container_component.rb +1 -3
- data/app/components/tramway/form/tramway_select/select_as_input_component.rb +1 -4
- data/app/components/tramway/form/tramway_select/selected_item_template_component.rb +4 -4
- data/app/components/tramway/nav/item_component.rb +2 -5
- data/app/components/tramway/navbar_component.html.haml +6 -6
- data/app/components/tramway/navbar_component.rb +19 -15
- data/app/components/tramway/pagination/base.rb +6 -6
- data/app/components/tramway/pagination/gap_component.rb +1 -3
- data/app/components/tramway/pagination/page_component.rb +2 -3
- data/app/components/tramway/table/cell_component.rb +1 -3
- data/app/components/tramway/table/header_component.html.haml +1 -1
- data/app/components/tramway/table/header_component.rb +2 -4
- data/app/components/tramway/table/row_component.html.haml +1 -1
- data/app/components/tramway/table/row_component.rb +7 -12
- data/app/components/tramway/table_component.rb +1 -3
- data/app/views/tramway/entities/_form.html.haml +1 -2
- data/app/views/tramway/layouts/application.html.haml +1 -1
- data/config/tailwind.config.js +278 -70
- data/lib/generators/tramway/install/install_generator.rb +44 -4
- data/lib/tramway/engine.rb +1 -1
- data/lib/tramway/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d6347854d4ed5eb627a0adb496c8f6ffd7d5f5d4948c510586af26f42bc7a3f
|
|
4
|
+
data.tar.gz: 52d08842b5fd4a6cb025d23e5faf8de44b699e4ed471b8c24049955bfab1a93f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b92182b455ad051e1e08e7020674ff3079acb09afba3e6845ad53b284cdf3fbe6844855b1b948a9066a990e3d669833a70d1cac04b62c15bf6fca22b27b0cbb9
|
|
7
|
+
data.tar.gz: 0b9a66a185ab03f7f345ff966b16c6b65558e6487356c4b4a7c580decf1c579f7a1e3d8ac9ca2e05fe8859da40abc284c06ea5a43aff7f758b332d618514ef1a
|
data/README.md
CHANGED
|
@@ -100,8 +100,9 @@ end
|
|
|
100
100
|
|
|
101
101
|
**Step 4**
|
|
102
102
|
|
|
103
|
-
If you ran `bin/rails g tramway:install`, the
|
|
104
|
-
|
|
103
|
+
If you ran `bin/rails g tramway:install`, the install generator already copied the Tailwind safelist to
|
|
104
|
+
`config/tailwind.config.js`.
|
|
105
|
+
Otherwise, copy this file from the gem:
|
|
105
106
|
`config/tailwind.config.js`.
|
|
106
107
|
|
|
107
108
|
|
|
@@ -870,9 +871,10 @@ end
|
|
|
870
871
|
|
|
871
872
|
### Tramway Flash
|
|
872
873
|
|
|
873
|
-
`tramway_flash` renders the
|
|
874
|
-
the helper will resolve the proper
|
|
875
|
-
custom HTML options directly (e.g., `class:`, `data:`) and
|
|
874
|
+
`tramway_flash` renders the dark shadcn-style flash component that Tramway uses in its layouts. Pass the flash text and type,
|
|
875
|
+
and the helper will resolve the proper dark semantic accent (for example `:success` -> green, `:warning` -> orange). Tramway
|
|
876
|
+
does not render a separate light flash theme. You can also provide custom HTML options directly (e.g., `class:`, `data:`) and
|
|
877
|
+
they will be merged into the flash container.
|
|
876
878
|
|
|
877
879
|
```haml
|
|
878
880
|
-# Haml example
|
|
@@ -887,7 +889,7 @@ custom HTML options directly (e.g., `class:`, `data:`) and they will be merged i
|
|
|
887
889
|
```
|
|
888
890
|
|
|
889
891
|
Use the `type` argument is compatible to [Lantern Color Palette](https://github.com/TrinityMonsters/tramway/blob/main/README.md#lantern-color-palette) or provide a `color:` keyword to set
|
|
890
|
-
the
|
|
892
|
+
the semantic accent explicitly.
|
|
891
893
|
|
|
892
894
|
### Tramway Chat
|
|
893
895
|
|
|
@@ -1122,6 +1124,12 @@ Example 3: rendering button
|
|
|
1122
1124
|
|
|
1123
1125
|
The `type` option maps semantic intent to [Lantern Color Palette](https://github.com/TrinityMonsters/tramway/blob/main/README.md#lantern-color-palette).
|
|
1124
1126
|
|
|
1127
|
+
Use `size:` to select one of the built-in button sizes: `:small`, `:medium`, or `:large`. The default is `:medium`.
|
|
1128
|
+
|
|
1129
|
+
```erb
|
|
1130
|
+
<%= tramway_button path: '/projects', text: 'Projects', size: :small %>
|
|
1131
|
+
```
|
|
1132
|
+
|
|
1125
1133
|
* `tramway_badge` renders a Tailwind-styled badge with the provided `text`. Pass a semantic `type` (for example, `:success` or
|
|
1126
1134
|
`:danger`) to use the built-in color mappings, or supply a custom Tailwind color family with `color:`. When you opt into a
|
|
1127
1135
|
custom color, ensure the corresponding background utilities are available in your Tailwind safelist.
|
|
@@ -1152,7 +1160,9 @@ Tramway uses [Tailwind](https://tailwindcss.com/) by default. All UI helpers are
|
|
|
1152
1160
|
|
|
1153
1161
|
#### tramway_form_for
|
|
1154
1162
|
|
|
1155
|
-
Tramway provides `tramway_form_for` helper that renders Tailwind-styled forms by default.
|
|
1163
|
+
Tramway provides `tramway_form_for` helper that renders Tailwind-styled forms by default. Form inputs use hardcoded
|
|
1164
|
+
dark shadcn-style classes; Tramway does not render a separate light form theme.
|
|
1165
|
+
Checkboxes render dark while unchecked and use the light primary checked state.
|
|
1156
1166
|
|
|
1157
1167
|
```erb
|
|
1158
1168
|
<%= tramway_form_for @user do |f| %>
|
|
@@ -1170,8 +1180,8 @@ Tramway provides `tramway_form_for` helper that renders Tailwind-styled forms by
|
|
|
1170
1180
|
|
|
1171
1181
|
will render [this](https://play.tailwindcss.com/xho3LfjKkK)
|
|
1172
1182
|
|
|
1173
|
-
Use `size:` to control the
|
|
1174
|
-
within the form will use the same size value.
|
|
1183
|
+
Use `size:` to control the input sizing (`:small`, `:medium`, or `:large`). The default is `:medium`, and supported inputs
|
|
1184
|
+
rendered within the form will use the same size value.
|
|
1175
1185
|
|
|
1176
1186
|
```erb
|
|
1177
1187
|
<%= tramway_form_for @user, size: :large do |f| %>
|
|
@@ -1298,6 +1308,7 @@ With `remote: true`, Tramway submits the form on each input `change` via inline
|
|
|
1298
1308
|
### Tailwind-styled pagination for Kaminari
|
|
1299
1309
|
|
|
1300
1310
|
Tramway uses [Tailwind](https://tailwindcss.com/) by default. It has tailwind-styled pagination for [kaminari](https://github.com/kaminari/kaminari).
|
|
1311
|
+
Pagination components use hardcoded dark shadcn-style classes and do not render a separate light theme.
|
|
1301
1312
|
|
|
1302
1313
|
#### How to use
|
|
1303
1314
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class UiCheckbox extends Controller {
|
|
4
|
+
static targets = ["input", "button", "indicator"]
|
|
5
|
+
|
|
6
|
+
connect() {
|
|
7
|
+
this.sync()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
toggle(event) {
|
|
11
|
+
event.preventDefault()
|
|
12
|
+
|
|
13
|
+
if (this.inputTarget.disabled) return
|
|
14
|
+
|
|
15
|
+
this.inputTarget.click()
|
|
16
|
+
this.sync()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
sync() {
|
|
20
|
+
const checked = this.inputTarget.checked
|
|
21
|
+
const state = checked ? "checked" : "unchecked"
|
|
22
|
+
|
|
23
|
+
this.buttonTarget.setAttribute("aria-checked", checked.toString())
|
|
24
|
+
this.buttonTarget.dataset.state = state
|
|
25
|
+
this.buttonTarget.classList.toggle("border-zinc-50", checked)
|
|
26
|
+
this.buttonTarget.classList.toggle("bg-zinc-50", checked)
|
|
27
|
+
this.buttonTarget.classList.toggle("text-zinc-950", checked)
|
|
28
|
+
this.buttonTarget.classList.toggle("border-zinc-800", !checked)
|
|
29
|
+
this.buttonTarget.classList.toggle("bg-zinc-950", !checked)
|
|
30
|
+
this.buttonTarget.classList.toggle("text-zinc-50", !checked)
|
|
31
|
+
this.indicatorTarget.classList.toggle("hidden", !checked)
|
|
32
|
+
this.buttonTarget.toggleAttribute("disabled", this.inputTarget.disabled)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { UiCheckbox }
|
|
@@ -42,45 +42,42 @@ class TailwindComponent < Tramway::BaseComponent
|
|
|
42
42
|
private
|
|
43
43
|
|
|
44
44
|
def text_input_base_classes
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
'w-full rounded-md border border-zinc-800 bg-zinc-950 text-zinc-50 shadow-sm transition-colors ' \
|
|
46
|
+
'placeholder:text-zinc-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-300 ' \
|
|
47
|
+
'focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed ' \
|
|
48
|
+
'disabled:opacity-50'
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def select_base_classes
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
)
|
|
52
|
+
'w-full rounded-md border border-zinc-800 bg-zinc-950 text-zinc-50 shadow-sm transition-colors ' \
|
|
53
|
+
'appearance-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-300 ' \
|
|
54
|
+
'focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed ' \
|
|
55
|
+
'disabled:opacity-50'
|
|
57
56
|
end
|
|
58
57
|
|
|
59
58
|
def file_button_base_classes
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
'inline-flex items-center justify-center rounded-md border border-zinc-800 bg-zinc-950 text-zinc-50 ' \
|
|
60
|
+
'font-medium shadow-sm transition-colors hover:bg-zinc-900 focus-visible:outline-none ' \
|
|
61
|
+
'focus-visible:ring-2 focus-visible:ring-zinc-300 focus-visible:ring-offset-2 ' \
|
|
62
|
+
'focus-visible:ring-offset-zinc-950 disabled:pointer-events-none disabled:opacity-50 cursor-pointer mt-4'
|
|
64
63
|
end
|
|
65
64
|
|
|
66
65
|
def submit_button_base_classes
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
)
|
|
66
|
+
'font-medium rounded-md border border-zinc-800 bg-zinc-950 text-zinc-50 shadow-sm transition-colors ' \
|
|
67
|
+
'hover:bg-zinc-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-300 ' \
|
|
68
|
+
'focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 cursor-pointer'
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
def checkbox_base_classes
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
'shrink-0 rounded-sm border border-zinc-800 bg-zinc-950 text-zinc-50 shadow-sm ' \
|
|
73
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-300 ' \
|
|
74
|
+
'focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:cursor-not-allowed ' \
|
|
75
|
+
'disabled:opacity-50'
|
|
78
76
|
end
|
|
79
77
|
|
|
80
78
|
def form_label_classes
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
)
|
|
79
|
+
'block text-sm font-medium leading-none mb-2 text-zinc-200 peer-disabled:cursor-not-allowed ' \
|
|
80
|
+
'peer-disabled:opacity-70'
|
|
84
81
|
end
|
|
85
82
|
|
|
86
83
|
def default_container_classes
|
|
@@ -4,6 +4,12 @@ module Tramway
|
|
|
4
4
|
# Default Tramway button
|
|
5
5
|
#
|
|
6
6
|
class ButtonComponent < BaseComponent
|
|
7
|
+
DEFAULT_BUTTON_CLASSES = %w[
|
|
8
|
+
inline-flex items-center justify-center rounded-md font-medium ring-offset-background transition-colors
|
|
9
|
+
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
|
|
10
|
+
disabled:pointer-events-none disabled:opacity-50
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
7
13
|
option :text, optional: true, default: -> {}
|
|
8
14
|
option :path, optional: true, default: -> { '#' }
|
|
9
15
|
option :color, optional: true
|
|
@@ -29,42 +35,44 @@ module Tramway
|
|
|
29
35
|
end
|
|
30
36
|
|
|
31
37
|
def size_classes
|
|
32
|
-
unless
|
|
38
|
+
unless normalized_size.in?(%i[small medium large])
|
|
33
39
|
raise ArgumentError, "Invalid size: #{size}. Valid sizes are :small, :medium, :large."
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
{
|
|
37
43
|
small: 'text-sm py-1 px-2 rounded',
|
|
38
|
-
medium: 'py-2 px-4 h-10',
|
|
44
|
+
medium: 'text-sm py-2 px-4 h-10',
|
|
39
45
|
large: 'text-xl px-5 py-3 h-12'
|
|
40
|
-
}[
|
|
46
|
+
}[normalized_size]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def default_button_classes
|
|
50
|
+
DEFAULT_BUTTON_CLASSES
|
|
41
51
|
end
|
|
42
52
|
|
|
43
53
|
def classes
|
|
44
|
-
(
|
|
54
|
+
(default_button_classes +
|
|
55
|
+
size_classes.split +
|
|
45
56
|
color_classes +
|
|
46
|
-
(@tag == :a ? %w[px-1 h-fit w-fit] : [cursor_class])
|
|
57
|
+
(@tag == :a ? %w[px-1 h-fit w-fit] : [cursor_class]) +
|
|
58
|
+
options[:class].to_s.split).compact.join(' ')
|
|
47
59
|
end
|
|
48
60
|
|
|
49
|
-
def
|
|
50
|
-
|
|
51
|
-
classic: %w[btn btn-primary flex flex-row font-semibold rounded-xl whitespace-nowrap items-center gap-1
|
|
52
|
-
shadow-md]
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
base_classes + [size_classes.to_s, options[:class].to_s]
|
|
61
|
+
def color_classes
|
|
62
|
+
theme_classes classic: color_classes_collection
|
|
56
63
|
end
|
|
57
64
|
|
|
58
|
-
def
|
|
59
|
-
if disabled?
|
|
60
|
-
%w[bg-gray-800 text-gray-500 shadow-inner]
|
|
61
|
-
else
|
|
62
|
-
[
|
|
63
|
-
"bg-#{resolved_color}-700", "hover:bg-#{resolved_color}-800", 'text-white'
|
|
64
|
-
]
|
|
65
|
-
end => classes_collection
|
|
65
|
+
def color_classes_collection
|
|
66
|
+
return %w[bg-gray-800 text-gray-500 shadow-inner] if disabled?
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
case normalized_type
|
|
69
|
+
when :default, :life, :secondary
|
|
70
|
+
['hover:bg-zinc-250', 'bg-zinc-50', 'text-zinc-950']
|
|
71
|
+
when :inverse
|
|
72
|
+
['hover:bg-zinc-800', 'bg-zinc-950', 'text-zinc-50', 'border', 'border-zinc-800']
|
|
73
|
+
else
|
|
74
|
+
["hover:bg-#{resolved_color}-900 bg-#{resolved_color}-900/30 text-#{resolved_color}-400"]
|
|
75
|
+
end
|
|
68
76
|
end
|
|
69
77
|
|
|
70
78
|
def disabled?
|
|
@@ -98,6 +106,10 @@ module Tramway
|
|
|
98
106
|
end
|
|
99
107
|
end
|
|
100
108
|
|
|
109
|
+
def normalized_size
|
|
110
|
+
size || :medium
|
|
111
|
+
end
|
|
112
|
+
|
|
101
113
|
def tag_button?
|
|
102
114
|
options[:type] == :submit
|
|
103
115
|
end
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
= helpers.turbo_stream_from chat_id, 'messages'
|
|
2
2
|
|
|
3
3
|
#chat.flex.flex-1.h-full.w-full.min-h-0.min-w-0.flex-col
|
|
4
|
-
#messages.flex.flex-col.flex-1.min-h-0.overflow-y-auto.overflow-x-hidden.p-2.
|
|
4
|
+
#messages.flex.flex-col.flex-1.min-h-0.overflow-y-auto.overflow-x-hidden.rounded-xl.rounded-b-none.border.border-zinc-800.p-2.text-zinc-50.space-y-2.md:p-6.md:space-y-4{ data: { scroll_to_bottom_on_update: scroll_to_bottom_on_update }, class: 'bg-zinc-950/80' }
|
|
5
5
|
- messages.each do |message|
|
|
6
6
|
= component "tramway/chats/message", **message
|
|
7
7
|
- if disabled?
|
|
8
|
-
= inline_svg 'icons/dots.svg', class: '
|
|
8
|
+
= inline_svg 'icons/dots.svg', class: 'mx-auto my-4 h-8 w-8 text-zinc-500'
|
|
9
9
|
|
|
10
10
|
- if message_form.present?
|
|
11
|
-
.shrink-0.border-
|
|
12
|
-
= form_for message_form, url: send_message_path, as: :message, method: :post, html: { class: 'flex items-center md:gap-1' } do |f|
|
|
11
|
+
.shrink-0.border-t.border-zinc-800.pt-2
|
|
12
|
+
= form_for message_form, url: send_message_path, as: :message, method: :post, html: { class: 'flex items-center gap-2 md:gap-1' } do |f|
|
|
13
13
|
- waiting_placeholder = t('tramway.chat.placeholders.waiting')
|
|
14
14
|
- typing_placeholder = t('tramway.chat.placeholders.type')
|
|
15
15
|
= f.text_field :text,
|
|
16
|
-
class: 'flex-1
|
|
16
|
+
class: 'flex-1 appearance-none rounded-md border border-zinc-800 bg-zinc-900 px-4 py-2 text-sm text-zinc-50 shadow-sm outline-none placeholder:text-zinc-500 focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 disabled:cursor-not-allowed',
|
|
17
17
|
placeholder: send_messages_enabled ? typing_placeholder : waiting_placeholder,
|
|
18
18
|
disabled: !send_messages_enabled
|
|
19
19
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
= f.hidden_field key, value: value
|
|
24
24
|
|
|
25
25
|
= f.submit '🡩',
|
|
26
|
-
class: '
|
|
26
|
+
class: 'inline-flex items-center justify-center rounded-md bg-zinc-50 px-4 py-2 text-sm font-medium text-zinc-950 shadow-sm transition-colors hover:bg-zinc-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950 disabled:pointer-events-none disabled:opacity-50'
|
|
27
27
|
|
|
28
28
|
:javascript
|
|
29
29
|
(() => {
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
- if pending?
|
|
18
18
|
.pb-1
|
|
19
|
-
-# = inline_svg 'icons/spinner.svg', class: '
|
|
19
|
+
-# = inline_svg 'icons/spinner.svg', class: 'h-4 w-4 animate-spin text-zinc-50'
|
|
20
20
|
|
|
21
21
|
- if failed?
|
|
22
22
|
.pb-1
|
|
23
|
-
-# = inline_svg 'icons/cross.svg', class: '
|
|
23
|
+
-# = inline_svg 'icons/cross.svg', class: 'h-6 w-6 text-red-400'
|
|
24
24
|
|
|
25
25
|
- if data_view == :table
|
|
26
26
|
= component 'tramway/chats/messages/table', data:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.flex.flex-col.gap-1{ class: position_classes }
|
|
2
2
|
- if text.present?
|
|
3
|
-
.max-w-lg.rounded-2xl.px-4.py-3.text-sm.shadow-sm
|
|
4
|
-
= component 'tramway/native_text', text:, klass: 'text-
|
|
3
|
+
.max-w-lg.rounded-2xl.px-4.py-3.text-sm.shadow-sm{ class: color_classes }
|
|
4
|
+
= component 'tramway/native_text', text:, klass: 'text-zinc-50'
|
|
5
5
|
|
|
6
6
|
- if sent_at.present?
|
|
7
|
-
.mt-2.text-right.text-xs.text-
|
|
7
|
+
.mt-2.text-right.text-xs.text-zinc-400
|
|
8
8
|
= sent_at
|
|
9
9
|
= content
|
|
@@ -10,21 +10,16 @@ module Tramway
|
|
|
10
10
|
option :sent_at
|
|
11
11
|
|
|
12
12
|
def position_classes
|
|
13
|
-
|
|
14
|
-
when :left
|
|
15
|
-
%w[items-start]
|
|
16
|
-
when :right
|
|
17
|
-
%w[items-end]
|
|
18
|
-
end.join(' ')
|
|
13
|
+
position.to_sym == :left ? 'items-start' : 'items-end'
|
|
19
14
|
end
|
|
20
15
|
|
|
21
16
|
def color_classes
|
|
22
17
|
case position.to_sym
|
|
23
18
|
when :left
|
|
24
|
-
|
|
19
|
+
'rounded-tl-md bg-zinc-900 text-zinc-50'
|
|
25
20
|
when :right
|
|
26
|
-
|
|
27
|
-
end
|
|
21
|
+
'rounded-tr-md bg-zinc-800 text-zinc-50'
|
|
22
|
+
end
|
|
28
23
|
end
|
|
29
24
|
end
|
|
30
25
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.mt-3.overflow-hidden.rounded-xl.border.border-
|
|
1
|
+
.mt-3.overflow-hidden.rounded-xl.border.border-zinc-800.bg-zinc-950.shadow-sm
|
|
2
2
|
= tramway_table do
|
|
3
3
|
- data.each_with_index do |row, index|
|
|
4
4
|
- if index.zero?
|
|
@@ -4,8 +4,9 @@ module Tramway
|
|
|
4
4
|
# Color logic implementation
|
|
5
5
|
module ColorsMethods
|
|
6
6
|
TYPE_COLOR_MAP = {
|
|
7
|
-
default: :
|
|
8
|
-
|
|
7
|
+
default: :zinc,
|
|
8
|
+
inverse: :zinc,
|
|
9
|
+
life: :zinc,
|
|
9
10
|
primary: :blue,
|
|
10
11
|
hope: :blue,
|
|
11
12
|
secondary: :zinc,
|
|
@@ -17,7 +18,6 @@ module Tramway
|
|
|
17
18
|
rage: :red,
|
|
18
19
|
love: :violet,
|
|
19
20
|
compassion: :indigo,
|
|
20
|
-
compassio: :indigo,
|
|
21
21
|
fear: :yellow,
|
|
22
22
|
submit: :green
|
|
23
23
|
}.freeze
|
|
@@ -11,8 +11,8 @@ module Tramway
|
|
|
11
11
|
options_classes = options[:class] || ''
|
|
12
12
|
|
|
13
13
|
theme_classes(
|
|
14
|
-
classic: 'container p-4 flex align-center justify-center w-full mx-auto
|
|
15
|
-
'shadow-inner rounded-xl bg-
|
|
14
|
+
classic: 'container p-4 flex align-center justify-center w-full mx-auto ' \
|
|
15
|
+
'shadow-inner rounded-xl bg-zinc-950 text-zinc-50' + options_classes
|
|
16
16
|
)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -11,22 +11,37 @@ module Tramway
|
|
|
11
11
|
include Tramway::ColorsMethods
|
|
12
12
|
|
|
13
13
|
def container_classes
|
|
14
|
-
|
|
15
|
-
classic: 'fixed top-4 right-4 z-50 space-y-2 pointer-events-none'
|
|
16
|
-
)
|
|
14
|
+
'fixed top-4 right-4 z-50 flex w-fit max-w-sm flex-col gap-2 pointer-events-none'
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
def flash_classes
|
|
20
|
-
|
|
21
|
-
classic: "flash opacity-100 px-4 py-2 rounded-xl shadow-md bg-#{resolved_color}-100 " \
|
|
22
|
-
"text-#{resolved_color}-800"
|
|
23
|
-
)
|
|
18
|
+
(base_flash_classes + semantic_flash_classes).join(' ')
|
|
24
19
|
end
|
|
25
20
|
|
|
26
21
|
def title_classes
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
'text-sm font-medium leading-6'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def base_flash_classes
|
|
28
|
+
%w[
|
|
29
|
+
flash pointer-events-auto opacity-100 rounded-md border bg-zinc-950 px-4 py-3 text-sm text-zinc-50
|
|
30
|
+
shadow-lg
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def semantic_flash_classes
|
|
35
|
+
{
|
|
36
|
+
green: %w[border-green-800 text-green-400],
|
|
37
|
+
blue: %w[border-blue-800 text-blue-400],
|
|
38
|
+
orange: %w[border-orange-800 text-orange-400],
|
|
39
|
+
red: %w[border-red-800 text-red-400],
|
|
40
|
+
violet: %w[border-violet-800 text-violet-400],
|
|
41
|
+
indigo: %w[border-indigo-800 text-indigo-400],
|
|
42
|
+
yellow: %w[border-yellow-800 text-yellow-400],
|
|
43
|
+
zinc: %w[border-zinc-800 text-zinc-50]
|
|
44
|
+
}.fetch(resolved_color.to_sym, %w[border-zinc-800 text-zinc-50])
|
|
30
45
|
end
|
|
31
46
|
end
|
|
32
47
|
end
|
|
@@ -1,7 +1,29 @@
|
|
|
1
|
-
.flex.items-center.
|
|
2
|
-
-
|
|
3
|
-
= @input.call @attribute,
|
|
1
|
+
.flex.items-center.space-x-2{ class: default_container_classes, data: { controller: 'ui--checkbox' } }
|
|
2
|
+
- checkbox_checked = checked?
|
|
3
|
+
= @input.call @attribute, **hidden_checkbox_options
|
|
4
|
+
%button{ type: 'button',
|
|
5
|
+
role: 'checkbox',
|
|
6
|
+
'aria-checked' => checkbox_checked.to_s,
|
|
7
|
+
'data-action' => 'click->ui--checkbox#toggle',
|
|
8
|
+
'data-state' => checkbox_checked ? 'checked' : 'unchecked',
|
|
9
|
+
'data-ui--checkbox-target' => 'button',
|
|
10
|
+
value: 'on',
|
|
11
|
+
class: checkbox_button_classes,
|
|
12
|
+
for: @for,
|
|
13
|
+
id: @for }
|
|
14
|
+
%span{ class: checkbox_indicator_classes, style: 'pointer-events: none', data: { 'ui--checkbox-target' => 'indicator' } }
|
|
15
|
+
%svg{ xmlns: 'http://www.w3.org/2000/svg',
|
|
16
|
+
width: '24',
|
|
17
|
+
height: '24',
|
|
18
|
+
viewBox: '0 0 24 24',
|
|
19
|
+
fill: 'none',
|
|
20
|
+
stroke: 'currentColor',
|
|
21
|
+
'stroke-width' => '2',
|
|
22
|
+
'stroke-linecap' => 'round',
|
|
23
|
+
'stroke-linejoin' => 'round',
|
|
24
|
+
class: 'h-4 w-4' }
|
|
25
|
+
%polyline{ points: '20 6 9 17 4 12' }
|
|
4
26
|
- if @label
|
|
5
27
|
%div
|
|
6
|
-
= component('tramway/form/label', for: @for, options: { class: label_classes }) do
|
|
28
|
+
= component('tramway/form/label', for: @for, options: { class: label_classes, data: { action: 'click->ui--checkbox#toggle' } }) do
|
|
7
29
|
= @label
|
|
@@ -4,8 +4,39 @@ module Tramway
|
|
|
4
4
|
module Form
|
|
5
5
|
# Tailwind-styled checkbox field
|
|
6
6
|
class CheckboxComponent < TailwindComponent
|
|
7
|
+
def checkbox_button_classes
|
|
8
|
+
'peer h-4 w-4 shrink-0 rounded-sm border border-zinc-800 bg-zinc-950 text-zinc-50 ' \
|
|
9
|
+
'ring-offset-zinc-950 ' \
|
|
10
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-300 ' \
|
|
11
|
+
'focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ' \
|
|
12
|
+
'data-[state=checked]:border-zinc-50 data-[state=checked]:bg-zinc-50 ' \
|
|
13
|
+
'data-[state=checked]:text-zinc-950'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def checkbox_indicator_classes
|
|
17
|
+
'flex items-center justify-center text-current hidden'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def checked?
|
|
21
|
+
!!ActiveModel::Type::Boolean.new.cast(options.fetch(:checked, value))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def hidden_checkbox_options
|
|
25
|
+
options.merge(
|
|
26
|
+
id: hidden_checkbox_id,
|
|
27
|
+
class: 'hidden',
|
|
28
|
+
data: options.fetch(:data, {}).merge('ui--checkbox-target' => 'input'),
|
|
29
|
+
tabindex: -1,
|
|
30
|
+
aria: { hidden: true }
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def hidden_checkbox_id
|
|
35
|
+
"#{@for}_input"
|
|
36
|
+
end
|
|
37
|
+
|
|
7
38
|
def label_classes
|
|
8
|
-
default_classes = 'cursor-pointer mb-0'
|
|
39
|
+
default_classes = 'cursor-pointer mb-0 leading-6'
|
|
9
40
|
|
|
10
41
|
case size
|
|
11
42
|
when :small
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
%label{ for: @for, class: "#{form_label_classes} #{options[:class]}" }
|
|
1
|
+
%label{ **options.except(:class), for: @for, class: "#{form_label_classes} #{options[:class]}" }
|
|
2
2
|
= content
|
|
@@ -8,9 +8,8 @@ module Tramway
|
|
|
8
8
|
option :options, optional: true, default: -> { {} }
|
|
9
9
|
|
|
10
10
|
def form_label_classes
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
11
|
+
'block text-sm font-medium leading-none mb-2 text-zinc-200 peer-disabled:cursor-not-allowed ' \
|
|
12
|
+
'peer-disabled:opacity-70'
|
|
14
13
|
end
|
|
15
14
|
end
|
|
16
15
|
end
|
|
@@ -14,11 +14,8 @@ module Tramway
|
|
|
14
14
|
}.freeze
|
|
15
15
|
|
|
16
16
|
def dropdown_classes
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
'max-h-select overflow-y-auto bg-gray-900 shadow-md ring-1 ring-gray-700 text-white ' \
|
|
20
|
-
"#{SIZE_CLASSES[size]}"
|
|
21
|
-
)
|
|
17
|
+
'absolute border border-zinc-800 w-full z-40 lef-0 rounded-md max-h-select overflow-y-auto ' \
|
|
18
|
+
"bg-zinc-950 text-zinc-50 shadow-md ring-1 ring-zinc-800 #{SIZE_CLASSES[size]}"
|
|
22
19
|
end
|
|
23
20
|
end
|
|
24
21
|
end
|
|
@@ -14,9 +14,7 @@ module Tramway
|
|
|
14
14
|
}.freeze
|
|
15
15
|
|
|
16
16
|
def item_classes
|
|
17
|
-
|
|
18
|
-
classic: "cursor-pointer hover:bg-gray-800 shadow-inner option #{SIZE_CLASSES[size]}"
|
|
19
|
-
)
|
|
17
|
+
"cursor-pointer rounded-sm text-zinc-50 hover:bg-zinc-900 option #{SIZE_CLASSES[size]}"
|
|
20
18
|
end
|
|
21
19
|
end
|
|
22
20
|
end
|
|
@@ -11,10 +11,7 @@ module Tramway
|
|
|
11
11
|
option :size_class
|
|
12
12
|
|
|
13
13
|
def base_classes
|
|
14
|
-
|
|
15
|
-
classic: 'bg-transparent appearance-none outline-none h-full w-full hidden text-gray-100 ' \
|
|
16
|
-
'placeholder-gray-500'
|
|
17
|
-
)
|
|
14
|
+
'bg-transparent appearance-none outline-none h-full w-full hidden text-zinc-50 placeholder:text-zinc-500'
|
|
18
15
|
end
|
|
19
16
|
end
|
|
20
17
|
end
|