pulse_view_components 0.3.0 → 0.4.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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -1
  3. data/README.md +26 -0
  4. data/app/assets/builds/js/pulse_view_components.js +3 -3
  5. data/app/assets/builds/js/pulse_view_components.js.map +1 -1
  6. data/app/assets/builds/pulse_view_components.css +2 -1
  7. data/app/assets/stylesheets/pulse_view_components/application.tailwind.css +44 -4
  8. data/app/assets/stylesheets/pulse_view_components/tokens.primitives.css +68 -0
  9. data/app/assets/stylesheets/pulse_view_components/tokens.system.css +95 -0
  10. data/app/components/pulse/action_list/divider.rb +13 -4
  11. data/app/components/pulse/action_list/form_wrapper.rb +2 -0
  12. data/app/components/pulse/action_list/heading.html.slim +7 -0
  13. data/app/components/pulse/action_list/heading.rb +2 -0
  14. data/app/components/pulse/action_list/item.html.slim +6 -6
  15. data/app/components/pulse/action_list/item.rb +11 -9
  16. data/app/components/pulse/action_list.css +109 -82
  17. data/app/components/pulse/action_list.html.slim +11 -0
  18. data/app/components/pulse/action_list.rb +5 -0
  19. data/app/components/pulse/badge.rb +20 -16
  20. data/app/components/pulse/base_component.rb +25 -1
  21. data/app/components/pulse/blank_slate.rb +4 -2
  22. data/app/components/pulse/border_box/header.rb +5 -3
  23. data/app/components/pulse/border_box.rb +21 -17
  24. data/app/components/pulse/box.rb +2 -0
  25. data/app/components/pulse/breadcrumb_item.rb +3 -1
  26. data/app/components/pulse/breadcrumbs.html.slim +2 -2
  27. data/app/components/pulse/breadcrumbs.rb +2 -0
  28. data/app/components/pulse/button.rb +28 -25
  29. data/app/components/pulse/component.rb +2 -1
  30. data/app/components/pulse/conditional_wrapper.rb +2 -0
  31. data/app/components/pulse/content.rb +2 -0
  32. data/app/components/pulse/counter.css +3 -3
  33. data/app/components/pulse/counter.rb +4 -0
  34. data/app/components/pulse/flash.rb +10 -6
  35. data/app/components/pulse/forms/error_explanation.html.slim +3 -3
  36. data/app/components/pulse/forms/error_explanation.rb +30 -13
  37. data/app/components/pulse/forms/error_explanation.yml +4 -0
  38. data/app/components/pulse/icon.rb +2 -0
  39. data/app/components/pulse/label.rb +5 -3
  40. data/app/components/pulse/layout.css +53 -52
  41. data/app/components/pulse/layout.rb +14 -6
  42. data/app/components/pulse/link.rb +10 -8
  43. data/app/components/pulse/modal.html.slim +20 -20
  44. data/app/components/pulse/modal.rb +10 -8
  45. data/app/components/pulse/modal_controller.js +3 -3
  46. data/app/components/pulse/nav_link.html.slim +7 -7
  47. data/app/components/pulse/nav_link.rb +4 -2
  48. data/app/components/pulse/nav_list/heading.rb +3 -1
  49. data/app/components/pulse/nav_list/item.html.slim +8 -0
  50. data/app/components/pulse/nav_list/item.rb +2 -2
  51. data/app/components/pulse/nav_list.rb +5 -0
  52. data/app/components/pulse/popover.html.slim +1 -1
  53. data/app/components/pulse/popover.rb +65 -26
  54. data/app/components/pulse/progress_bar.html.slim +2 -2
  55. data/app/components/pulse/progress_bar.rb +5 -3
  56. data/app/components/pulse/table/cell.html.slim +2 -2
  57. data/app/components/pulse/table/cell.rb +14 -10
  58. data/app/components/pulse/table/column.rb +2 -0
  59. data/app/components/pulse/table.html.slim +3 -3
  60. data/app/components/pulse/table.rb +19 -16
  61. data/app/components/pulse/text.rb +26 -24
  62. data/app/components/pulse/toast.html.slim +8 -8
  63. data/app/components/pulse/toast.rb +25 -23
  64. data/app/lib/pulse/status.rb +48 -0
  65. data/lib/pulse/view_components/version.rb +1 -1
  66. data/previews/foundations/colors_preview/palettes.html.slim +12 -0
  67. data/previews/foundations/colors_preview/semantic.html.slim +16 -0
  68. data/previews/foundations/colors_preview.rb +55 -0
  69. data/previews/pulse/action_list_preview.rb +77 -0
  70. data/previews/pulse/border_box_preview.rb +1 -1
  71. data/previews/pulse/counter_preview.rb +1 -1
  72. data/previews/pulse/flash_preview.rb +1 -1
  73. data/previews/pulse/forms/error_explanation_preview.rb +49 -0
  74. data/previews/pulse/layout_preview.rb +5 -5
  75. data/previews/pulse/nav_list_preview.rb +1 -1
  76. data/previews/pulse/popover_preview.rb +48 -22
  77. data/previews/pulse/progress_bar_preview.rb +1 -1
  78. data/previews/pulse/table_preview.rb +6 -6
  79. metadata +17 -11
@@ -1,95 +1,96 @@
1
1
  /* Layout */
2
2
 
3
- @define-mixin flow-as-row {
3
+ /*
4
+ Stacks the sidebar and main columns vertically. Applied below a breakpoint
5
+ by the media queries after `.Layout`. Tailwind 4 has no mixins, so this is a
6
+ custom utility pulled in with `@apply`.
7
+ */
8
+ @utility layout-flow-row {
4
9
  grid-auto-flow: row;
5
10
  grid-template-columns: 1fr !important;
6
11
 
7
12
  & .Layout-sidebar,
8
13
  & .Layout-divider,
9
14
  & .Layout-main {
10
- @apply pulse-w-full pulse-col-[1];
15
+ @apply pulse:w-full pulse:col-[1];
11
16
  }
12
17
 
13
18
  &.Layout--sidebarPosition-flowRow-start {
14
19
  & .Layout-sidebar {
15
- @apply pulse-row-[1];
20
+ @apply pulse:row-[1];
16
21
  }
17
22
 
18
23
  & .Layout-main {
19
- @apply pulse-row-[2_/_span_2];
24
+ @apply pulse:row-[2_/_span_2];
20
25
  }
21
26
  }
22
27
 
23
28
  &.Layout--sidebarPosition-flowRow-end {
24
29
  & .Layout-sidebar {
25
- @apply pulse-row-[2_/_span_2];
30
+ @apply pulse:row-[2_/_span_2];
26
31
  }
27
32
 
28
33
  & .Layout-main {
29
- @apply pulse-row-[1];
34
+ @apply pulse:row-[1];
30
35
  }
31
36
  }
32
37
 
33
38
  &.Layout--sidebarPosition-flowRow-none {
34
39
  & .Layout-sidebar {
35
- @apply pulse-hidden;
40
+ @apply pulse:hidden;
36
41
  }
37
42
  }
38
43
 
39
44
  &.Layout--divided {
40
- @mixin flow-as-row-divider;
45
+ --Layout-gutter: 0;
46
+
47
+ & .Layout-divider {
48
+ @apply pulse:h-px pulse:row-[2];
49
+
50
+ &.Layout-divider--flowRow-hidden {
51
+ @apply pulse:hidden;
52
+ }
53
+
54
+ &.Layout-divider--flowRow-shallow {
55
+ @apply pulse:h-2 pulse:border-[color:var(--borderColor-default)] pulse:[border-width:var(--borderWidth-thin)_0] pulse:mr-0 pulse:border-solid;
56
+ background: var(--bgColor-inset);
57
+ }
58
+ }
41
59
 
42
60
  & .Layout-main {
43
- @apply pulse-row-[3_/_span_1];
61
+ @apply pulse:row-[3_/_span_1];
44
62
  }
45
63
 
46
64
  &.Layout--sidebarPosition-flowRow-end {
47
65
  & .Layout-sidebar {
48
- @apply pulse-row-[3_/_span_1];
66
+ @apply pulse:row-[3_/_span_1];
49
67
  }
50
68
 
51
69
  & .Layout-main {
52
- @apply pulse-row-[1];
70
+ @apply pulse:row-[1];
53
71
  }
54
72
  }
55
73
  }
56
74
  }
57
75
 
58
- @define-mixin flow-as-row-divider {
59
- --Layout-gutter: 0;
60
-
61
- & .Layout-divider {
62
- @apply pulse-h-px pulse-row-[2];
63
-
64
- &.Layout-divider--flowRow-hidden {
65
- @apply pulse-hidden;
66
- }
67
-
68
- &.Layout-divider--flowRow-shallow {
69
- @apply pulse-h-2 pulse-border-[color:var(--borderColor-default)] pulse-border-[var(--borderWidth-thin)_0] pulse-mr-0 pulse-border-solid;
70
- background: var(--bgColor-inset);
71
- }
72
- }
73
- }
74
-
75
76
  .Layout {
76
- @apply pulse-grid pulse-grid-flow-col pulse-grid-cols-[auto_0_minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))] pulse-gap-[var(--Layout-gutter)];
77
+ @apply pulse:grid pulse:grid-flow-col pulse:grid-cols-[auto_0_minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))] pulse:gap-[var(--Layout-gutter)];
77
78
  --Layout-sidebar-width: 220px;
78
79
  --Layout-gutter: 16px;
79
80
  }
80
81
  @media (max-width: calc(544px - 0.02px)) {
81
82
  .Layout {
82
- @mixin flow-as-row;
83
+ @apply pulse:layout-flow-row;
83
84
  }
84
85
  }
85
86
  @media (max-width: calc(768px - 0.02px)) {
86
87
  .Layout.Layout--flowRow-until-md {
87
- @mixin flow-as-row;
88
+ @apply pulse:layout-flow-row;
88
89
  }
89
90
  }
90
91
  @media (max-width: calc(1012px - 0.02px)) {
91
92
  .Layout.Layout--flowRow-until-lg {
92
- @mixin flow-as-row;
93
+ @apply pulse:layout-flow-row;
93
94
  }
94
95
  }
95
96
 
@@ -97,13 +98,13 @@
97
98
 
98
99
  /* sidebar column, separator, main column */
99
100
  .Layout .Layout-sidebar {
100
- @apply pulse-col-[1];
101
+ @apply pulse:col-[1];
101
102
  }
102
103
  .Layout .Layout-divider {
103
- @apply pulse-hidden;
104
+ @apply pulse:hidden;
104
105
  }
105
106
  .Layout .Layout-main {
106
- @apply pulse-col-[2_/_span_2];
107
+ @apply pulse:col-[2_/_span_2];
107
108
  }
108
109
 
109
110
  /* Gutter spacing */
@@ -171,43 +172,43 @@
171
172
 
172
173
  /* Sidebar position */
173
174
  .Layout.Layout--sidebarPosition-start .Layout-sidebar {
174
- @apply pulse-col-[1];
175
+ @apply pulse:col-[1];
175
176
  }
176
177
  .Layout.Layout--sidebarPosition-start .Layout-main {
177
- @apply pulse-col-[2_/_span_2];
178
+ @apply pulse:col-[2_/_span_2];
178
179
  }
179
180
  .Layout.Layout--sidebarPosition-end {
180
- @apply pulse-grid-cols-[minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))_0_auto];
181
+ @apply pulse:grid-cols-[minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))_0_auto];
181
182
  }
182
183
  .Layout.Layout--sidebarPosition-end .Layout-main {
183
- @apply pulse-col-[1];
184
+ @apply pulse:col-[1];
184
185
  }
185
186
  .Layout.Layout--sidebarPosition-end .Layout-sidebar {
186
- @apply pulse-col-[2_/_span_2];
187
+ @apply pulse:col-[2_/_span_2];
187
188
  }
188
189
 
189
190
  /* Sidebar divider */
190
191
  .Layout.Layout--divided .Layout-divider {
191
- @apply pulse-block pulse-col-[2] pulse-w-px -pulse-mr-px;
192
+ @apply pulse:block pulse:col-[2] pulse:w-px pulse:-mr-px;
192
193
  background: var(--borderColor-default);
193
194
  }
194
195
  .Layout.Layout--divided .Layout-main {
195
- @apply pulse-col-[3_/_span_1];
196
+ @apply pulse:col-[3_/_span_1];
196
197
  }
197
198
  .Layout.Layout--divided.Layout--sidebarPosition-end .Layout-sidebar {
198
- @apply pulse-col-[3_/_span_1];
199
+ @apply pulse:col-[3_/_span_1];
199
200
  }
200
201
  .Layout.Layout--divided.Layout--sidebarPosition-end .Layout-main {
201
- @apply pulse-col-[1];
202
+ @apply pulse:col-[1];
202
203
  }
203
204
  .Layout-divider {
204
- @apply pulse-hidden pulse-w-px;
205
+ @apply pulse:hidden pulse:w-px;
205
206
  }
206
207
  .Layout-sidebar {
207
- @apply pulse-w-[var(--Layout-sidebar-width)];
208
+ @apply pulse:w-[var(--Layout-sidebar-width)];
208
209
  }
209
210
  .Layout-main {
210
- @apply pulse-min-w-0;
211
+ @apply pulse:min-w-0;
211
212
  }
212
213
 
213
214
  /* Centered main column
@@ -215,7 +216,7 @@
215
216
  .Layout-main .Layout-main-centered-md,
216
217
  .Layout-main .Layout-main-centered-lg,
217
218
  .Layout-main .Layout-main-centered-xl {
218
- @apply pulse-mx-auto;
219
+ @apply pulse:mx-auto;
219
220
  }
220
221
  .Layout-main .Layout-main-centered-md > .container-md,
221
222
  .Layout-main .Layout-main-centered-md > .container-lg,
@@ -226,14 +227,14 @@
226
227
  .Layout-main .Layout-main-centered-xl > .container-md,
227
228
  .Layout-main .Layout-main-centered-xl > .container-lg,
228
229
  .Layout-main .Layout-main-centered-xl > .container-xl {
229
- @apply pulse-ml-0;
230
+ @apply pulse:ml-0;
230
231
  }
231
232
  .Layout-main .Layout-main-centered-md {
232
- @apply pulse-max-w-[calc(var(--breakpoint-medium)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
233
+ @apply pulse:max-w-[calc(var(--breakpoint-medium)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
233
234
  }
234
235
  .Layout-main .Layout-main-centered-lg {
235
- @apply pulse-max-w-[calc(var(--breakpoint-large)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
236
+ @apply pulse:max-w-[calc(var(--breakpoint-large)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
236
237
  }
237
238
  .Layout-main .Layout-main-centered-xl {
238
- @apply pulse-max-w-[calc(var(--breakpoint-xlarge)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
239
+ @apply pulse:max-w-[calc(var(--breakpoint-xlarge)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
239
240
  }
@@ -3,6 +3,10 @@
3
3
  module Pulse
4
4
  # Renders a two-column page layout
5
5
  class Layout < Pulse::Component
6
+ # Main and sidebar placement work. Main `width:` options other than `:full`
7
+ # emit Primer classes that no CSS defines, so the content is not centred.
8
+ status :beta
9
+
6
10
  FIRST_IN_SOURCE_DEFAULT = :sidebar
7
11
  FIRST_IN_SOURCE_OPTIONS = [FIRST_IN_SOURCE_DEFAULT, :main].freeze
8
12
 
@@ -61,10 +65,10 @@ module Pulse
61
65
  @system_arguments = system_arguments
62
66
  @system_arguments[:tag] = :div
63
67
  @system_arguments[:classes] = merge_classes(
64
- 'pulse-grid pulse-grid-flow-col',
65
- 'pulse-grid-cols-[auto_0_minmax(0,calc(100%_-_var(--pulse-layout' \
68
+ 'pulse:grid pulse:grid-flow-col',
69
+ 'pulse:grid-cols-[auto_0_minmax(0,calc(100%_-_var(--pulse-layout' \
66
70
  '-sidebar-width)_-_var(--pulse-layout-gutter)))]',
67
- 'pulse-gap-[var(--pulse-layout-gutter)]',
71
+ 'pulse:gap-(--pulse-layout-gutter)',
68
72
  GUTTER_MAPPINGS[fetch_or_fallback(GUTTER_OPTIONS, gutter,
69
73
  GUTTER_DEFAULT)],
70
74
  system_arguments[:classes]
@@ -77,6 +81,8 @@ module Pulse
77
81
 
78
82
  # The layout's main content.
79
83
  class Main < Pulse::Component
84
+ status :stable
85
+
80
86
  WIDTH_DEFAULT = :full
81
87
  WIDTH_OPTIONS = [WIDTH_DEFAULT, :md, :lg, :xl].freeze
82
88
 
@@ -92,7 +98,7 @@ module Pulse
92
98
  @system_arguments[:tag] =
93
99
  fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
94
100
  @system_arguments[:classes] = merge_classes(
95
- 'pulse-col-[2_/_span_2]',
101
+ 'pulse:col-[2/span_2]',
96
102
  system_arguments[:classes]
97
103
  )
98
104
  end
@@ -105,7 +111,7 @@ module Pulse
105
111
  render(
106
112
  Pulse::BaseComponent.new(
107
113
  tag: :div,
108
- classes: "pulse-mx-auto Layout-main-centered-#{@width}"
114
+ classes: "pulse:mx-auto Layout-main-centered-#{@width}"
109
115
  )
110
116
  ) do
111
117
  render(Pulse::BaseComponent.new(tag: :div, container: @width)) do
@@ -119,6 +125,8 @@ module Pulse
119
125
 
120
126
  # The layout's sidebar content.
121
127
  class Sidebar < Pulse::Component
128
+ status :stable
129
+
122
130
  TAG_DEFAULT = :div
123
131
  TAG_OPTIONS = [TAG_DEFAULT, :aside, :nav, :section].freeze
124
132
 
@@ -128,7 +136,7 @@ module Pulse
128
136
  @system_arguments[:tag] =
129
137
  fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
130
138
  @system_arguments[:classes] = merge_classes(
131
- 'pulse-col-[1]',
139
+ 'pulse:col-1',
132
140
  @system_arguments[:classes]
133
141
  )
134
142
  end
@@ -5,13 +5,15 @@ module Pulse
5
5
  # `Link` styles anchor tags with default styling and hover
6
6
  # text-decoration.
7
7
  class Link < Pulse::Component
8
+ status :stable
9
+
8
10
  DEFAULT_SCHEME = :tertiary
9
11
  SCHEME_MAPPINGS = {
10
- primary: 'pulse-text-primary hover:pulse-text-primary',
11
- secondary: 'pulse-text-secondary hover:pulse-text-secondary',
12
- tertiary: 'pulse-text-tertiary hover:pulse-text-tertiary',
13
- reversed: 'pulse-text-gray-300 hover:pulse-text-gray-300 ' \
14
- 'focus:pulse-text-gray-300'
12
+ primary: 'pulse:text-primary pulse:hover:text-primary',
13
+ secondary: 'pulse:text-secondary pulse:hover:text-secondary',
14
+ tertiary: 'pulse:text-tertiary pulse:hover:text-tertiary',
15
+ reversed: 'pulse:text-neutral-300 pulse:hover:text-neutral-300 ' \
16
+ 'pulse:focus:text-neutral-300'
15
17
  }.freeze
16
18
  SCHEME_OPTIONS = SCHEME_MAPPINGS.keys.freeze
17
19
 
@@ -31,8 +33,8 @@ module Pulse
31
33
  SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_MAPPINGS.keys, scheme,
32
34
  DEFAULT_SCHEME)],
33
35
  @options[:classes],
34
- 'pulse-font-bold': bold,
35
- 'pulse-underline hover:pulse-no-underline': condition && underline
36
+ 'pulse:font-bold': bold,
37
+ 'pulse:underline pulse:hover:no-underline': condition && underline
36
38
  )
37
39
  end
38
40
 
@@ -45,7 +47,7 @@ module Pulse
45
47
 
46
48
  @options[:classes] = class_names(
47
49
  @options[:classes],
48
- 'pulse-flex pulse-items-center pulse-gap-1.5'
50
+ 'pulse:flex pulse:items-center pulse:gap-1.5'
49
51
  )
50
52
  end
51
53
  end
@@ -1,40 +1,40 @@
1
1
  = turbo_frame_tag 'pulse_modal' do
2
2
  = render Pulse::BaseComponent.new(**@system_arguments) do
3
3
  - unless auto_close
4
- div class="pulse-flex pulse-items-center pulse-justify-center pulse-min-h-screen pulse-p-6 pulse-box-border"
4
+ div class="pulse:flex pulse:items-center pulse:justify-center pulse:min-h-screen pulse:p-6 pulse:box-border"
5
5
  /! bg overlay
6
6
  div{
7
7
  data-pulse--modal-target="wrapper" data-action="#{close_on_overlay_click ? 'click->pulse--modal#close' : ''}" aria-hidden="true"
8
- data-transition-enter="pulse-ease-out pulse-duration-300"
9
- data-transition-enter-start="pulse-opacity-0"
10
- data-transition-enter-end="pulse-opacity-100"
11
- data-transition-leave="pulse-ease-in pulse-duration-200"
12
- data-transition-leave-start="pulse-opacity-100"
13
- data-transition-leave-end="pulse-opacity-0"
14
- class="pulse-fixed pulse-inset-0 pulse-bg-neutral-700/75 pulse-transition-opacity" }
8
+ data-transition-enter="pulse:ease-out pulse:duration-300"
9
+ data-transition-enter-start="pulse:opacity-0"
10
+ data-transition-enter-end="pulse:opacity-100"
11
+ data-transition-leave="pulse:ease-in pulse:duration-200"
12
+ data-transition-leave-start="pulse:opacity-100"
13
+ data-transition-leave-end="pulse:opacity-0"
14
+ class="pulse:fixed pulse:inset-0 pulse:bg-neutral-700/75 pulse:transition-opacity" }
15
15
 
16
16
  /! modal
17
17
  div{
18
18
  data-pulse--modal-target="body"
19
- data-transition-enter="pulse-ease-out pulse-duration-300"
20
- data-transition-enter-start="pulse-opacity-0 pulse-translate-y-4 sm:pulse-translate-y-0 sm:pulse-scale-95"
21
- data-transition-enter-end="pulse-opacity-100 pulse-translate-y-0 sm:pulse-scale-100"
22
- data-transition-leave="pulse-ease-in pulse-duration-200"
23
- data-transition-leave-start="pulse-opacity-100 pulse-translate-y-0 sm:pulse-scale-100"
24
- data-transition-leave-end="pulse-opacity-0 pulse-translate-y-4 sm:pulse-translate-y-0 sm:pulse-scale-95"
25
- class="pulse-relative pulse-z-50 pulse-bg-white pulse-shadow-xl pulse-rounded-lg pulse-transition-all #{modal_classes}"
19
+ data-transition-enter="pulse:ease-out pulse:duration-300"
20
+ data-transition-enter-start="pulse:opacity-0 pulse:translate-y-4 pulse:sm:translate-y-0 pulse:sm:scale-95"
21
+ data-transition-enter-end="pulse:opacity-100 pulse:translate-y-0 pulse:sm:scale-100"
22
+ data-transition-leave="pulse:ease-in pulse:duration-200"
23
+ data-transition-leave-start="pulse:opacity-100 pulse:translate-y-0 pulse:sm:scale-100"
24
+ data-transition-leave-end="pulse:opacity-0 pulse:translate-y-4 pulse:sm:translate-y-0 pulse:sm:scale-95"
25
+ class="pulse:relative pulse:z-50 pulse:bg-white pulse:shadow-xl pulse:rounded-lg pulse:transition-all #{modal_classes}"
26
26
  role="dialog"
27
27
  aria-modal="true"}
28
28
 
29
29
  /! header
30
- div class="pulse-flex pulse-items-center pulse-justify-between pulse-gap-4 pulse-p-4 md:pulse-p-5 pulse-border-b"
30
+ div class="pulse:flex pulse:items-center pulse:justify-between pulse:gap-4 pulse:p-4 pulse:md:p-5 pulse:border-b"
31
31
  - if title?
32
- = render Pulse::Text.new(type: :h4, el_tag: :h2, classes: 'pulse-tracking-tight pulse-text-gray pulse-truncate')
32
+ = render Pulse::Text.new(type: :h4, el_tag: :h2, classes: 'pulse:tracking-tight pulse:text-neutral-700 pulse:truncate')
33
33
  = title
34
34
 
35
35
  - if close_button
36
36
  button{
37
- class="pulse-ms-auto pulse-inline-flex pulse-items-center pulse-justify-center pulse-w-10 pulse-h-7 pulse-bg-transparent pulse-border-none pulse-text-gray"
37
+ class="pulse:ms-auto pulse:inline-flex pulse:items-center pulse:justify-center pulse:w-10 pulse:h-7 pulse:bg-transparent pulse:border-none pulse:text-neutral-700"
38
38
  data-action="pulse--modal#close"
39
39
  aria-label="Close Modal"}
40
40
 
@@ -42,10 +42,10 @@
42
42
 
43
43
 
44
44
  /! body
45
- div class="pulse-p-4 md:pulse-p-5 #{'pulse-mb-4' unless footer}"
45
+ div class="pulse:p-4 pulse:md:p-5 #{'pulse:mb-4' unless footer}"
46
46
  = content
47
47
 
48
48
  /! footer
49
49
  - if footer
50
- div class="pulse-flex pulse-items-center pulse-p-4 md:pulse-p-5 pulse-border-t pulse-border-gray-300"
50
+ div class="pulse:flex pulse:items-center pulse:p-4 pulse:md:p-5 pulse:border-t pulse:border-neutral-300"
51
51
  = footer
@@ -3,6 +3,8 @@
3
3
  module Pulse
4
4
  # Renders a modal component targetable by turbo frame
5
5
  class Modal < Pulse::Component
6
+ status :stable
7
+
6
8
  include Turbo::FramesHelper
7
9
 
8
10
  renders_one :title
@@ -10,11 +12,11 @@ module Pulse
10
12
 
11
13
  DEFAULT_SIZE = :md
12
14
  SIZE_MAPPINGS = {
13
- sm: 'pulse-max-w-md',
14
- md: 'pulse-max-w-2xl',
15
- lg: 'pulse-max-w-4xl',
16
- xl: 'pulse-max-w-5xl',
17
- xxl: 'pulse-max-w-6xl'
15
+ sm: 'pulse:max-w-md',
16
+ md: 'pulse:max-w-2xl',
17
+ lg: 'pulse:max-w-4xl',
18
+ xl: 'pulse:max-w-5xl',
19
+ xxl: 'pulse:max-w-6xl'
18
20
  }.freeze
19
21
  SIZE_OPTIONS = SIZE_MAPPINGS.keys.freeze
20
22
 
@@ -24,7 +26,7 @@ module Pulse
24
26
  @size = fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)
25
27
  @system_arguments = system_arguments
26
28
  @modal_classes = merge_classes(
27
- 'pulse-w-full',
29
+ 'pulse:w-full',
28
30
  SIZE_MAPPINGS[@size],
29
31
  @system_arguments.delete(:classes)
30
32
  )
@@ -36,8 +38,8 @@ module Pulse
36
38
 
37
39
  @system_arguments[:'aria-labelledby'] = 'modal-title'
38
40
  @system_arguments[:'aria-modal'] = true
39
- @system_arguments[:classes] = 'pulse-fixed pulse-z-9999 pulse-inset-0 ' \
40
- 'pulse-overflow-y-auto'
41
+ @system_arguments[:classes] = 'pulse:fixed pulse:z-9999 pulse:inset-0 ' \
42
+ 'pulse:overflow-y-auto'
41
43
  @system_arguments[:data] = data_attributes
42
44
  @system_arguments[:role] = 'dialog'
43
45
  @system_arguments[:tabindex] = 0
@@ -43,7 +43,7 @@ export default class extends Controller {
43
43
  this.lastFocusedElement = document.activeElement
44
44
  enter(this.wrapperTarget)
45
45
  enter(this.bodyTarget)
46
- document.body.classList.add("pulse-overflow-hidden")
46
+ document.body.classList.add("pulse:overflow-hidden")
47
47
  }
48
48
 
49
49
  close(e) {
@@ -54,7 +54,7 @@ export default class extends Controller {
54
54
  this.element.remove()
55
55
  })
56
56
 
57
- document.body.classList.remove("pulse-overflow-hidden")
57
+ document.body.classList.remove("pulse:overflow-hidden")
58
58
 
59
59
  // Return focus to the last focused element
60
60
  if (this.lastFocusedElement) this.lastFocusedElement.focus()
@@ -66,7 +66,7 @@ export default class extends Controller {
66
66
 
67
67
  autoClose(e) {
68
68
  this.element.remove()
69
- document.body.classList.remove("pulse-overflow-hidden")
69
+ document.body.classList.remove("pulse:overflow-hidden")
70
70
  }
71
71
 
72
72
  handleSubmit = e => {
@@ -2,15 +2,15 @@
2
2
  = render Pulse::BaseComponent.new(**@system_arguments) do
3
3
  - if @variant == :desktop
4
4
  = active_link_to @path, active: @active_mode,
5
- class_active: 'pulse-text-white hover:pulse-text-white hover:pulse-no-underline pulse-px-3 pulse-py-2 pulse-font-medium pulse-relative pulse-group pulse-is-active',
6
- class_inactive: 'pulse-text-white hover:pulse-text-white hover:pulse-no-underline pulse-px-3 pulse-py-2 pulse-font-medium pulse-relative pulse-group' do
5
+ class_active: 'pulse:text-white pulse:hover:text-white pulse:hover:no-underline pulse:px-3 pulse:py-2 pulse:font-medium pulse:relative pulse:group pulse-is-active',
6
+ class_inactive: 'pulse:text-white pulse:hover:text-white pulse:hover:no-underline pulse:px-3 pulse:py-2 pulse:font-medium pulse:relative pulse:group' do
7
7
  = @label
8
- span class="pulse-absolute -pulse-bottom-0.5 pulse-left-1/2 pulse-w-0 pulse-h-0.5 pulse-bg-gray-300 group-hover:pulse-w-1/2 group-hover:pulse-transition-all pulse-duration-200"
9
- span class="pulse-absolute -pulse-bottom-0.5 pulse-right-1/2 pulse-w-0 pulse-h-0.5 pulse-bg-gray-300 group-hover:pulse-w-1/2 group-hover:pulse-transition-all pulse-duration-200"
10
- span class="pulse-absolute -pulse-bottom-0.5 pulse-start-0 pulse-w-full pulse-h-0.5 pulse-bg-primary pulse-hidden group-[.pulse-is-active]:pulse-block"
8
+ span class="pulse:absolute pulse:-bottom-0.5 pulse:left-1/2 pulse:w-0 pulse:h-0.5 pulse:bg-neutral-300 pulse:group-hover:w-1/2 pulse:group-hover:transition-all pulse:duration-200"
9
+ span class="pulse:absolute pulse:-bottom-0.5 pulse:right-1/2 pulse:w-0 pulse:h-0.5 pulse:bg-neutral-300 pulse:group-hover:w-1/2 pulse:group-hover:transition-all pulse:duration-200"
10
+ span class="pulse:absolute pulse:-bottom-0.5 pulse:inset-s-0 pulse:w-full pulse:h-0.5 pulse:bg-primary pulse:hidden pulse:group-[.pulse-is-active]:block"
11
11
  - else
12
12
  = active_link_to @path, active: @active_mode,
13
- class_active: 'pulse-text-primary-800 hover:pulse-no-underline pulse-block pulse-px-3 pulse-py-2',
14
- class_inactive: 'pulse-text-gray hover:pulse-no-underline pulse-block pulse-px-3 pulse-py-2',
13
+ class_active: 'pulse:text-primary-800 pulse:hover:no-underline pulse:block pulse:px-3 pulse:py-2',
14
+ class_inactive: 'pulse:text-neutral-700 pulse:hover:no-underline pulse:block pulse:px-3 pulse:py-2',
15
15
  data: { action: 'dropdown#toggle' } do
16
16
  = @label
@@ -3,10 +3,12 @@
3
3
  module Pulse
4
4
  # Links in navbars
5
5
  class NavLink < Pulse::Component
6
+ status :stable
7
+
6
8
  DEFAULT_VARIANT = :desktop
7
9
  VARIANT_MAPPINGS = {
8
- desktop: 'pulse-px-3 pulse-py-2',
9
- mobile: 'pulse-px-3 pulse-py-2'
10
+ desktop: 'pulse:px-3 pulse:py-2',
11
+ mobile: 'pulse:px-3 pulse:py-2'
10
12
  }.freeze
11
13
  VARIANT_OPTIONS = VARIANT_MAPPINGS.keys.freeze
12
14
 
@@ -6,6 +6,8 @@ module Pulse
6
6
  #
7
7
  # See <%= link_to_component(NavList) %> for usage examples.
8
8
  class Heading < Pulse::Component
9
+ status :alpha
10
+
9
11
  attr_reader :title, :id, :heading_level, :system_arguments
10
12
 
11
13
  # @param title [String] The text content of the heading.
@@ -26,7 +28,7 @@ module Pulse
26
28
  type: :body4,
27
29
  tag: :"h#{heading_level}",
28
30
  id:,
29
- classes: 'pulse-ml-2 pulse-mb-4',
31
+ classes: 'pulse:ml-2 pulse:mb-4',
30
32
  **system_arguments
31
33
  ).with_content(title)
32
34
  )
@@ -0,0 +1,8 @@
1
+ /! components/pulse/nav_list/item
2
+ - with_private_content do
3
+ - if items.present?
4
+ = render(Pulse::BaseComponent.new(tag: :ul, **@sub_list_arguments)) do
5
+ - items.each do |item|
6
+ = item
7
+
8
+ = render_parent
@@ -81,7 +81,7 @@ module Pulse
81
81
  else
82
82
  @system_arguments[:classes] = merge_classes(
83
83
  @system_arguments[:classes],
84
- 'pulse-outline-none pulse-bg-gray-50' => active?
84
+ 'pulse:outline-hidden pulse:bg-neutral-50' => active?
85
85
  )
86
86
  end
87
87
 
@@ -118,7 +118,7 @@ module Pulse
118
118
  "
119
119
 
120
120
  with_private_trailing_action_icon(
121
- :'chevron-down',
121
+ icon: :'chevron-down',
122
122
  classes: 'ActionListItem-collapseIcon'
123
123
  )
124
124
 
@@ -14,6 +14,11 @@ module Pulse
14
14
  # or more ID values that determine which item will appear selected. Use the
15
15
  # `selected_item_id` argument to select the appropriate item.
16
16
  class NavList < Pulse::Component
17
+ # Incomplete: built on `ActionList`. Avatar items raise, sub-items render
18
+ # expanded and cannot be toggled, and the show-more item has no JavaScript.
19
+ # Top-level items, headings, groups and selection work.
20
+ status :alpha
21
+
17
22
  # @private
18
23
  def self.custom_element_name
19
24
  'nav-list'
@@ -1,5 +1,5 @@
1
1
  /! components/pulse/popover
2
- = render Pulse::BaseComponent.new(**@system_arguments) do
2
+ = render Pulse::BaseComponent.new(**wrapper_arguments) do
3
3
  = render(body_component) do
4
4
  = heading
5
5
  = body