playbook_ui 16.2.0.pre.alpha.faiconbuttonfix14520 → 16.2.0.pre.alpha.iconfixes14577

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_button/_button.scss +2 -3
  3. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +4 -1
  4. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -2
  5. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +2 -0
  6. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -2
  7. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +1 -1
  8. data/app/pb_kits/playbook/pb_icon/icon.rb +159 -19
  9. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -0
  10. data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +4 -0
  11. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +2 -0
  12. data/app/pb_kits/playbook/pb_select/_select.tsx +2 -0
  13. data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
  14. data/app/pb_kits/playbook/pb_star_rating/star_rating.html.erb +1 -1
  15. data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_interactive.tsx +1 -0
  16. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +2 -0
  17. data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +2 -2
  18. data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +4 -1
  19. data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +2 -2
  20. data/app/pb_kits/playbook/pb_textarea/textarea.test.js +1 -1
  21. data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +6 -0
  22. data/app/pb_kits/playbook/pb_time_picker/time_picker.test.jsx +2 -2
  23. data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +1 -1
  24. data/dist/chunks/{_typeahead-DXIBDeMj.js → _typeahead-COVN8XN7.js} +1 -1
  25. data/dist/chunks/vendor.js +3 -3
  26. data/dist/playbook-rails-react-bindings.js +1 -1
  27. data/dist/playbook-rails.js +1 -1
  28. data/dist/playbook.css +1 -1
  29. data/lib/playbook/forms/builder/checkbox_field.rb +1 -1
  30. data/lib/playbook/version.rb +1 -1
  31. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ab15b5936d85e9fe352d2293813967937694dc61e985fafb0ec9d21d6df752d
4
- data.tar.gz: 6bab9ca4069487ba52e762667f86f663a2a27c3c300c537a073996c9016cea49
3
+ metadata.gz: 4658800f5f85c4198d6f5396e8e51de4ac4440c905ee8b1d687dd635b9116fde
4
+ data.tar.gz: 5575760a10fb40d744d6af0979941b6b8139ddaa03b8816c7b86904a34814245
5
5
  SHA512:
6
- metadata.gz: 14144c41830ccabcc9cb3a7572e6197cd970ca4300b28aa2d4285ff06bae722b261f8613e50b38424caa67d801a9928a00abff1acb3bf2ebeef7355f9bf14f8a
7
- data.tar.gz: d6d1f2dc9c37b53d0211b5bccbd0cd2af1594c9cdf2b20eb907814ec40be28edcfc677bb0a2c27ecbb36d728c06aff220529a52d42d1b60152d60e9ab4400281
6
+ metadata.gz: d2e9025088024e65f25ac470260585c78ef7ec59651100f1360bf1f548e587cfa37dc566710c37748928919705fa4ce20a1333a4fb7ca27a09318288ea10e65e
7
+ data.tar.gz: 8f78b511d51ae7912e9e5caad1bb8d9f25158776f63f481cd05969631818306c63e6357dd950567bef10c673398b7379a411be44a06aa35375e9aa15926e4f2c
@@ -115,10 +115,9 @@ $pb_button_sizes: (
115
115
 
116
116
  // Icon-only button (icon prop set, no text) - square with equal padding
117
117
  // Rails: uses .pb_button_icon_only class
118
- // React: when pb_button_content is empty (no text). Do not match when content has
119
- // text + icon (e.g. "Exit Fullscreen" + FA icon) which can include empty spans.
118
+ // React: detects when pb_button_content has an empty text span
120
119
  &.pb_button_icon_only,
121
- &:has(.pb_button_content:empty) {
120
+ &:has(.pb_button_content > span:empty) {
122
121
  aspect-ratio: 1;
123
122
  min-width: auto;
124
123
  width: auto;
@@ -221,11 +221,14 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
221
221
  {!hideLabel && (
222
222
  <label htmlFor={pickerId}>
223
223
  {requiredIndicator ? (
224
- <Caption className="pb_date_picker_kit_label">
224
+ <Caption className="pb_date_picker_kit_label"
225
+ color="lighter"
226
+ >
225
227
  {label} <span style={{ color: `${colors.error}` }}>*</span>
226
228
  </Caption>
227
229
  ) : (
228
230
  <Caption className="pb_date_picker_kit_label"
231
+ color="lighter"
229
232
  text={label}
230
233
  />
231
234
  )}
@@ -7,11 +7,11 @@
7
7
  <% if !object.hide_label && object.label %>
8
8
  <label for="<%= object.picker_id %>">
9
9
  <% if object.required_indicator %>
10
- <%= pb_rails("caption", props: { dark: object.dark, classname: "pb_date_picker_kit_label" }) do %>
10
+ <%= pb_rails("caption", props: { dark: object.dark, classname: "pb_date_picker_kit_label", color: "lighter" }) do %>
11
11
  <%= object.label %><span style="color: #DA0014;"> *</span>
12
12
  <% end %>
13
13
  <% else %>
14
- <%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_date_picker_kit_label" }) %>
14
+ <%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_date_picker_kit_label", color: "lighter" }) %>
15
15
  <% end %>
16
16
  </label>
17
17
  <% end %>
@@ -479,6 +479,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
479
479
  {requiredIndicator ? (
480
480
  <Caption
481
481
  className="pb_dropdown_kit_label"
482
+ color="lighter"
482
483
  dark={dark}
483
484
  marginBottom="xs"
484
485
  >
@@ -487,6 +488,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
487
488
  ) : (
488
489
  <Caption
489
490
  className="pb_dropdown_kit_label"
491
+ color="lighter"
490
492
  dark={dark}
491
493
  marginBottom="xs"
492
494
  text={label}
@@ -2,11 +2,11 @@
2
2
  <% if object.label.present? %>
3
3
  <label for="<%= object.select_id %>" data-dropdown="pb-dropdown-label">
4
4
  <% if object.required_indicator %>
5
- <%= pb_rails("caption", props: { margin_bottom: "xs", classname: "pb_dropdown_kit_label", dark: object.dark }) do %>
5
+ <%= pb_rails("caption", props: { margin_bottom: "xs", classname: "pb_dropdown_kit_label", color: "lighter", dark: object.dark }) do %>
6
6
  <%= object.label %><span style="color: #DA0014;"> *</span>
7
7
  <% end %>
8
8
  <% else %>
9
- <%= pb_rails("caption", props: { text: object.label, margin_bottom: "xs", classname: "pb_dropdown_kit_label", dark: object.dark }) %>
9
+ <%= pb_rails("caption", props: { text: object.label, margin_bottom: "xs", classname: "pb_dropdown_kit_label", color: "lighter", dark: object.dark }) %>
10
10
  <% end %>
11
11
  </label>
12
12
  <% end %>
@@ -212,7 +212,7 @@ test('generated label prop', () => {
212
212
  )
213
213
 
214
214
  const kit = screen.getByTestId(testId)
215
- const label = kit.querySelector('.pb_caption_kit_md')
215
+ const label = kit.querySelector('.pb_caption_kit_md_lighter')
216
216
  expect(label).toHaveTextContent('Countries')
217
217
  })
218
218
 
@@ -2,10 +2,13 @@
2
2
 
3
3
  require "open-uri"
4
4
  require "json"
5
+ require "digest"
5
6
 
6
7
  module Playbook
7
8
  module PbIcon
8
9
  class Icon < Playbook::KitBase
10
+ ICON_PATH_DEV_CACHE_TTL_SECONDS = 2
11
+
9
12
  prop :border, type: Playbook::Props::Boolean,
10
13
  default: false
11
14
  prop :fixed_width, type: Playbook::Props::Boolean,
@@ -82,30 +85,35 @@ module Playbook
82
85
  )
83
86
  end
84
87
 
88
+ # Instance-level memoization of alias map lookup result
85
89
  def icon_alias_map
86
- return unless Rails.application.config.respond_to?(:icon_alias_path)
90
+ return @icon_alias_map if defined?(@icon_alias_map)
87
91
 
88
- base_path = Rails.application.config.icon_alias_path
89
- json = File.read(Rails.root.join(base_path))
90
- JSON.parse(json)["aliases"].freeze
92
+ @icon_alias_map = self.class.icon_alias_map
91
93
  end
92
94
 
95
+ # Instance-level memoization of resolved asset path
93
96
  def asset_path
94
- return unless Rails.application.config.respond_to?(:icon_path)
97
+ return @asset_path if defined?(@asset_path)
98
+
99
+ @asset_path =
100
+ if Rails.application.config.respond_to?(:icon_path)
101
+ resolved_icon = resolve_alias(icon)
102
+ path = self.class.icon_path_index[resolved_icon]
103
+ path if path && File.exist?(path)
104
+ end
105
+ end
106
+
107
+ def is_svg?
108
+ return @is_svg if defined?(@is_svg)
95
109
 
96
- base_path = Rails.application.config.icon_path
97
- resolved_icon = resolve_alias(icon)
98
- icon_path = Dir.glob(Rails.root.join(base_path, "**", "#{resolved_icon}.svg")).first
99
- icon_path if icon_path && File.exist?(icon_path)
110
+ @is_svg = (icon || custom_icon.to_s).include?(".svg") || asset_path.present?
100
111
  end
101
112
 
102
113
  def render_svg
103
114
  doc = Nokogiri::XML(URI.open(asset_path || icon || custom_icon)) # rubocop:disable Security/Open
104
- svg = doc.at_css "svg"
105
-
106
- unless svg
107
- return "" # Return an empty string if SVG element is not found
108
- end
115
+ svg = doc.at_css("svg")
116
+ return "" unless svg
109
117
 
110
118
  svg["class"] = %w[pb_custom_icon svg-inline--fa].concat([object.custom_icon_classname]).join(" ")
111
119
  svg["id"] = object.id
@@ -113,7 +121,9 @@ module Playbook
113
121
  svg["width"] = "auto"
114
122
  svg["tabindex"] = object.tabindex
115
123
  fill_color = object.color || "currentColor"
116
- doc.at_css("path")["fill"] = fill_color
124
+
125
+ # Safely apply fill to all paths (avoids nil errors + handles multi-path icons)
126
+ doc.css("path").each { |p| p["fill"] = fill_color }
117
127
 
118
128
  if object.data.present?
119
129
  object.data.each do |key, value|
@@ -135,14 +145,144 @@ module Playbook
135
145
  ""
136
146
  end
137
147
 
138
- def is_svg?
139
- (icon || custom_icon.to_s).include?(".svg") || asset_path.present?
148
+ # Class-level caches
149
+ class << self
150
+ @cache_mutex = Mutex.new
151
+ attr_reader :cache_mutex
152
+
153
+ # Cache aliases.json across the process, but invalidate when the file changes (dev-safe)
154
+ def icon_alias_map
155
+ return @icon_alias_map if alias_cache_fresh?
156
+
157
+ cache_mutex.synchronize do
158
+ return @icon_alias_map if alias_cache_fresh?
159
+
160
+ @icon_alias_map =
161
+ if Rails.application.config.respond_to?(:icon_alias_path)
162
+ base_path = Rails.application.config.icon_alias_path
163
+ full_path = Rails.root.join(base_path)
164
+ @icon_alias_map_mtime = safe_mtime(full_path)
165
+
166
+ json = File.read(full_path)
167
+ parsed = JSON.parse(json)
168
+ parsed.fetch("aliases", {}).freeze
169
+ end
170
+ end
171
+
172
+ @icon_alias_map
173
+ end
174
+
175
+ # Cache an index of icon_name to file path for all SVGs in the configured directory, with invalidation based on directory mtime
176
+ # Avoids recursive Dir.glob for every icon render
177
+ def icon_path_index
178
+ return @icon_path_index if index_cache_fresh?
179
+
180
+ cache_mutex.synchronize do
181
+ return @icon_path_index if index_cache_fresh?
182
+
183
+ @icon_path_index =
184
+ if Rails.application.config.respond_to?(:icon_path)
185
+ base_path = Rails.application.config.icon_path
186
+ root = Rails.root.join(base_path)
187
+
188
+ # If path doesn't exist, keep behavior aligned (no path resolution)
189
+ if Dir.exist?(root)
190
+ @icon_path_index_cache_key = icon_path_cache_key(root)
191
+
192
+ # One scan builds the map for O(1) lookups
193
+ # Key is the filename (without .svg) to match existing usage
194
+ index = {}
195
+ Dir.glob(File.join(root.to_s, "**", "*.svg")).sort.each do |p|
196
+ name = File.basename(p, ".svg")
197
+ index[name] ||= p
198
+ end
199
+ index.freeze
200
+ else
201
+ @icon_path_index_cache_key = nil
202
+ {}
203
+ end
204
+ else
205
+ {}
206
+ end
207
+
208
+ @icon_path_index_checked_at = monotonic_now if Rails.env.development?
209
+ end
210
+
211
+ @icon_path_index
212
+ end
213
+
214
+ private
215
+
216
+ def alias_cache_fresh?
217
+ return false unless defined?(@icon_alias_map)
218
+
219
+ return true unless Rails.application.config.respond_to?(:icon_alias_path)
220
+
221
+ full_path = Rails.root.join(Rails.application.config.icon_alias_path)
222
+ safe_mtime(full_path) == @icon_alias_map_mtime
223
+ rescue
224
+ false
225
+ end
226
+
227
+ def index_cache_fresh?
228
+ return false unless defined?(@icon_path_index)
229
+
230
+ return true unless Rails.application.config.respond_to?(:icon_path)
231
+
232
+ # In development, skip expensive tree digest checks for a short window
233
+ # This keeps hot-reload behavior while avoiding per-render full scans
234
+ return true if Rails.env.development? && within_dev_icon_index_ttl?
235
+
236
+ root = Rails.root.join(Rails.application.config.icon_path)
237
+ fresh = icon_path_cache_key(root) == @icon_path_index_cache_key
238
+ @icon_path_index_checked_at = monotonic_now
239
+ fresh
240
+ rescue
241
+ false
242
+ end
243
+
244
+ def within_dev_icon_index_ttl?
245
+ return false unless defined?(@icon_path_index_checked_at)
246
+
247
+ (monotonic_now - @icon_path_index_checked_at) < ICON_PATH_DEV_CACHE_TTL_SECONDS
248
+ rescue
249
+ false
250
+ end
251
+
252
+ def monotonic_now
253
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
254
+ end
255
+
256
+ def icon_path_cache_key(root)
257
+ return safe_mtime(root) unless Rails.env.development?
258
+
259
+ digest = Digest::SHA1.new
260
+ root_prefix = "#{root}/"
261
+
262
+ Dir.glob(File.join(root.to_s, "**", "*.svg")).sort.each do |path|
263
+ stat = File.stat(path)
264
+ digest << path.delete_prefix(root_prefix)
265
+ digest << stat.mtime.to_f.to_s
266
+ digest << stat.size.to_s
267
+ end
268
+
269
+ digest.hexdigest
270
+ rescue
271
+ nil
272
+ end
273
+
274
+ def safe_mtime(path)
275
+ File.exist?(path) ? File.mtime(path) : nil
276
+ rescue
277
+ nil
278
+ end
140
279
  end
141
280
 
142
281
  private
143
282
 
144
283
  def resolve_alias(icon)
145
284
  return icon unless icon_alias_map
285
+ return icon if icon.nil?
146
286
 
147
287
  aliases = icon_alias_map[icon]
148
288
  return icon unless aliases
@@ -155,8 +295,8 @@ module Playbook
155
295
  end
156
296
 
157
297
  def file_exists?(alias_name)
158
- base_path = Rails.application.config.icon_path
159
- File.exist?(Dir.glob(Rails.root.join(base_path, "**", "#{alias_name}.svg")).first)
298
+ # Use the cached index (no recursive glob)
299
+ self.class.icon_path_index.key?(alias_name)
160
300
  end
161
301
 
162
302
  def svg_size
@@ -532,6 +532,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>(
532
532
  {requiredIndicator ? (
533
533
  <Caption
534
534
  className="pb_multi_level_select_kit_label"
535
+ color="lighter"
535
536
  marginBottom="xs"
536
537
  >
537
538
  {label} <span className="required_indicator">*</span>
@@ -539,6 +540,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>(
539
540
  ) : (
540
541
  <Caption
541
542
  className="pb_multi_level_select_kit_label"
543
+ color="lighter"
542
544
  marginBottom="xs"
543
545
  text={label}
544
546
  />
@@ -119,12 +119,14 @@ const Passphrase = (props: PassphraseProps): React.ReactElement => {
119
119
  {hasLabel && (requiredIndicator ? (
120
120
  <Caption
121
121
  className="passphrase-label"
122
+ color="lighter"
122
123
  >
123
124
  {label} <span className="required_indicator">*</span>
124
125
  </Caption>
125
126
  ) : (
126
127
  <Caption
127
128
  className="passphrase-label"
129
+ color="lighter"
128
130
  text={label}
129
131
  />
130
132
  ))}
@@ -142,12 +144,14 @@ const Passphrase = (props: PassphraseProps): React.ReactElement => {
142
144
  orientation="column"
143
145
  >
144
146
  <Caption
147
+ color="lighter"
145
148
  marginBottom="xs"
146
149
  text="Tips for a good passphrase"
147
150
  />
148
151
  <div>
149
152
  {tips.map((tip, i) => (
150
153
  <Caption
154
+ color="lighter"
151
155
  key={i}
152
156
  marginBottom="xs"
153
157
  size="xs"
@@ -262,6 +262,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
262
262
  {
263
263
  requiredIndicator ? (
264
264
  <Caption className="pb_text_input_kit_label"
265
+ color="lighter"
265
266
  marginBottom="xs"
266
267
  >
267
268
  {label} <span style={{ color: `${colors.error}` }}>*</span>
@@ -269,6 +270,7 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
269
270
  ) : (
270
271
  <Caption
271
272
  className="pb_text_input_kit_label"
273
+ color="lighter"
272
274
  marginBottom="xs"
273
275
  text={label}
274
276
  />
@@ -134,12 +134,14 @@ const Select = ({
134
134
  >
135
135
  {requiredIndicator ? (
136
136
  <Caption
137
+ color="lighter"
137
138
  dark={props.dark}>
138
139
  {label}
139
140
  <span style={{ color: "#DA0014" }}> *</span>
140
141
  </Caption>
141
142
  ) : (
142
143
  <Caption
144
+ color="lighter"
143
145
  dark={props.dark}
144
146
  text={label}
145
147
  />
@@ -4,11 +4,11 @@
4
4
  <% if object.label %>
5
5
  <label class="pb_select_kit_label" for="<%= object.input_options[:id] || object.name %>">
6
6
  <% if object.required_indicator %>
7
- <%= pb_rails("caption", props: { dark: object.dark }) do %>
7
+ <%= pb_rails("caption", props: { color: "lighter", dark: object.dark }) do %>
8
8
  <%= object.label %><span style="color: #DA0014;"> *</span>
9
9
  <% end %>
10
10
  <% else %>
11
- <%= pb_rails("caption", props: { text: object.label, dark: object.dark }) %>
11
+ <%= pb_rails("caption", props: { color: "lighter", text: object.label, dark: object.dark }) %>
12
12
  <% end %>
13
13
  </label>
14
14
  <% end %>
@@ -37,7 +37,7 @@
37
37
  <% else %>
38
38
  <%= pb_rails("flex", props: { data: {"pb-star-rating-wrapper": "true" }, orientation: "column" }) do %>
39
39
  <% if object.label.present? %>
40
- <%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
40
+ <%= pb_rails("caption", props: { color: "lighter", text: object.label, margin_bottom:"xs"}) %>
41
41
  <% end %>
42
42
 
43
43
  <%= hidden_input_tag %>
@@ -54,6 +54,7 @@ const StarRatingInteractive = (props: StarRatingInteractiveProps) => {
54
54
  {label &&
55
55
  <Caption
56
56
  className="pb_star_rating_kit_label"
57
+ color="lighter"
57
58
  marginBottom="xs"
58
59
  text={label}
59
60
  />
@@ -253,6 +253,7 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
253
253
  requiredIndicator ? (
254
254
  <Caption
255
255
  className="pb_text_input_kit_label"
256
+ color="lighter"
256
257
  dark={dark}
257
258
  >
258
259
  {label} <span style={{ color: dark ? colors.text_error_dark : colors.text_error }}>*</span>
@@ -260,6 +261,7 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
260
261
  ) : (
261
262
  <Caption
262
263
  className="pb_text_input_kit_label"
264
+ color="lighter"
263
265
  dark={dark}
264
266
  text={label}
265
267
  />
@@ -2,11 +2,11 @@
2
2
  <% if object.label.present? %>
3
3
  <label for="<%= object.input_options[:id] || object.id %>">
4
4
  <% if object.required_indicator %>
5
- <%= pb_rails("caption", props: { dark: object.dark, classname: "pb_text_input_kit_label" }) do %>
5
+ <%= pb_rails("caption", props: { dark: object.dark, classname: "pb_text_input_kit_label", color: "lighter" }) do %>
6
6
  <%= object.label %><span style="color: #DA0014;"> *</span>
7
7
  <% end %>
8
8
  <% else %>
9
- <%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label" }) %>
9
+ <%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label", color: "lighter" }) %>
10
10
  <% end %>
11
11
  </label>
12
12
  <% end %>
@@ -133,11 +133,14 @@ const Textarea = ({
133
133
  <label htmlFor={id}>
134
134
  {
135
135
  requiredIndicator ? (
136
- <Caption className="pb_text_input_kit_label">
136
+ <Caption className="pb_text_input_kit_label"
137
+ color="lighter"
138
+ >
137
139
  {label} <span style={{ color: `${colors.text_error}` }}>*</span>
138
140
  </Caption>
139
141
  ) : (
140
142
  <Caption className="pb_text_input_kit_label"
143
+ color="lighter"
141
144
  text={label}
142
145
  />
143
146
  )
@@ -2,11 +2,11 @@
2
2
  <% if object.label.present? %>
3
3
  <label for="<%= object.input_options[:id] || object.id %>" >
4
4
  <% if object.required_indicator %>
5
- <%= pb_rails("caption", props: { text: object.label, dark: object.dark }) do %>
5
+ <%= pb_rails("caption", props: { color: "lighter", text: object.label, dark: object.dark }) do %>
6
6
  <%= object.label %><span style="color: #DA0014;"> *</span>
7
7
  <% end %>
8
8
  <% else %>
9
- <%= pb_rails("caption", props: {text: object.label, dark: object.dark}) %>
9
+ <%= pb_rails("caption", props: { color: "lighter", text: object.label, dark: object.dark }) %>
10
10
  <% end %>
11
11
  </label>
12
12
  <% end %>
@@ -149,7 +149,7 @@ describe("TextArea Kit Props", () => {
149
149
  )
150
150
 
151
151
  const kit = screen.getByTestId(testId)
152
- const error = kit.querySelector(".pb_caption_kit_md")
152
+ const error = kit.querySelector(".pb_caption_kit_md_lighter")
153
153
 
154
154
  expect(error.innerHTML).toBe("Test Label")
155
155
  })
@@ -707,6 +707,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
707
707
  {requiredIndicator ? (
708
708
  <Caption
709
709
  className="pb_time_picker_kit_label"
710
+ color="lighter"
710
711
  dark={dark}
711
712
  marginBottom="xs"
712
713
  size="md"
@@ -716,6 +717,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
716
717
  ) : (
717
718
  <Caption
718
719
  className="pb_time_picker_kit_label"
720
+ color="lighter"
719
721
  dark={dark}
720
722
  marginBottom="xs"
721
723
  size="md"
@@ -766,6 +768,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
766
768
  <label htmlFor={`${uniqueId}-hour`}>
767
769
  <Caption
768
770
  className="time_input_label"
771
+ color="lighter"
769
772
  dark={dark}
770
773
  size="sm"
771
774
  text="Hour"
@@ -813,6 +816,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
813
816
  <label htmlFor={`${uniqueId}-minute`}>
814
817
  <Caption
815
818
  className="time_input_label"
819
+ color="lighter"
816
820
  dark={dark}
817
821
  size="sm"
818
822
  text="Minute"
@@ -859,6 +863,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
859
863
  <div className="meridiem">
860
864
  <Caption
861
865
  className="time_input_label"
866
+ color="lighter"
862
867
  dark={dark}
863
868
  size="sm"
864
869
  text="Period"
@@ -905,6 +910,7 @@ const TimePicker = (props: TimePickerProps): JSX.Element => {
905
910
  )}
906
911
  {showTimezone && (
907
912
  <Caption
913
+ color="lighter"
908
914
  dark={dark}
909
915
  lineHeight="tight"
910
916
  marginTop="sm"
@@ -71,14 +71,14 @@ describe('TimePicker', () => {
71
71
  render(<TimePicker data={{ testid: 'clickable-picker' }} />)
72
72
  const input = screen.getByPlaceholderText('Select Time')
73
73
  fireEvent.click(input)
74
- expect(screen.getByText('Hour', { selector: '.pb_caption_kit_sm' })).toBeInTheDocument()
74
+ expect(screen.getByText('Hour', { selector: '.pb_caption_kit_sm_lighter' })).toBeInTheDocument()
75
75
  })
76
76
 
77
77
  test('does not open dropdown on input click when disabled', () => {
78
78
  render(<TimePicker disabled />)
79
79
  const input = screen.getByPlaceholderText('Select Time')
80
80
  fireEvent.click(input)
81
- expect(screen.queryByText('Hour', { selector: '.pb_caption_kit_sm' })).not.toBeInTheDocument()
81
+ expect(screen.queryByText('Hour', { selector: '.pb_caption_kit_sm_lighter' })).not.toBeInTheDocument()
82
82
  })
83
83
 
84
84
  test('renders with required attribute', () => {
@@ -20,7 +20,7 @@ test('typeahead classname + label renders as expected', () => {
20
20
  )
21
21
 
22
22
  const kit = screen.getByTestId('typeahead-test')
23
- const label = kit.querySelector(".pb_caption_kit_md.pb_text_input_kit_label")
23
+ const label = kit.querySelector(".pb_caption_kit_md_lighter.pb_text_input_kit_label")
24
24
  expect(kit).toHaveClass("pb_typeahead_kit")
25
25
  expect(label).toHaveTextContent("Colors")
26
26
  })