coveragebook_components 0.7.10 → 0.8.0.beta.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/build/coco/app.css +1065 -148
  3. data/app/assets/build/coco/app.js +255 -47
  4. data/app/assets/build/coco/book.css +26 -0
  5. data/app/assets/css/app/tippy.css +4 -0
  6. data/app/components/coco/app/blocks/header/header.css +43 -0
  7. data/app/components/coco/app/blocks/header/header.html.erb +30 -0
  8. data/app/components/coco/app/blocks/header/header.js +11 -0
  9. data/app/components/coco/app/blocks/header/header.rb +35 -0
  10. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.css +48 -3
  11. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.html.erb +14 -6
  12. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.js +18 -1
  13. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.rb +26 -1
  14. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.css +104 -0
  15. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.html.erb +42 -0
  16. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.js +28 -0
  17. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.rb +28 -0
  18. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.css +165 -0
  19. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.html.erb +43 -0
  20. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.js +41 -0
  21. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.rb +98 -0
  22. data/app/components/coco/app/elements/alert/alert.css +65 -18
  23. data/app/components/coco/app/elements/alert/alert.html.erb +4 -4
  24. data/app/components/coco/app/elements/alert/alert.js +4 -3
  25. data/app/components/coco/app/elements/alert/alert.rb +10 -0
  26. data/app/components/coco/app/elements/button/button.css +58 -0
  27. data/app/components/coco/app/elements/button/button.rb +1 -1
  28. data/app/components/coco/app/elements/button_group/button_group.rb +4 -0
  29. data/app/components/coco/app/elements/color_picker/color_picker.rb +1 -1
  30. data/app/components/coco/app/elements/menu/menu.css +1 -0
  31. data/app/components/coco/app/elements/menu/menu.html.erb +1 -1
  32. data/app/components/coco/app/elements/menu/menu.rb +2 -1
  33. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.css +22 -0
  34. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.html.erb +17 -0
  35. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.rb +20 -0
  36. data/app/components/coco/app/elements/notice/notice.css +4 -0
  37. data/app/components/coco/app/elements/snackbar/snackbar.css +8 -1
  38. data/app/components/coco/app/elements/snackbar/snackbar.rb +2 -2
  39. data/app/components/coco/app/elements/system_banner/system_banner.html.erb +2 -1
  40. data/app/components/coco/app/elements/system_banner/system_banner.js +35 -2
  41. data/app/components/coco/app/elements/system_banner/system_banner.rb +47 -3
  42. data/app/components/coco/app/layouts/application/application.css +104 -4
  43. data/app/components/coco/app/layouts/application/application.html.erb +28 -7
  44. data/app/components/coco/app/layouts/application/application.js +16 -0
  45. data/app/components/coco/app/layouts/application/application.rb +11 -3
  46. data/app/components/coco/base/avatar/avatar.css +25 -0
  47. data/app/components/coco/base/avatar/avatar.rb +20 -0
  48. data/app/components/coco/base/modal/modal.html.erb +1 -1
  49. data/app/components/coco/concerns/accepts_tag_attributes.rb +6 -2
  50. data/app/components/coco/concerns/acts_as_button_group.rb +5 -0
  51. data/app/helpers/coco/app_helper.rb +16 -0
  52. data/app/helpers/coco/base_helper.rb +4 -0
  53. data/config/tokens.cjs +4 -1
  54. data/lib/coco.rb +1 -1
  55. metadata +22 -10
  56. data/app/components/coco/app/blocks/banner/banner.css +0 -5
  57. data/app/components/coco/app/blocks/banner/banner.rb +0 -8
  58. data/app/components/coco/app/blocks/nav_bar/nav_bar.css +0 -51
  59. data/app/components/coco/app/blocks/nav_bar/nav_bar.html.erb +0 -23
  60. data/app/components/coco/app/blocks/nav_bar/nav_bar.js +0 -31
  61. data/app/components/coco/app/blocks/nav_bar/nav_bar.rb +0 -19
@@ -3,7 +3,7 @@
3
3
  @apply rounded-xl overflow-hidden border border-transparent @container;
4
4
 
5
5
  .alert-container {
6
- @apply flex items-start p-4 relative;
6
+ @apply flex items-start px-4 py-2 relative;
7
7
  }
8
8
 
9
9
  .alert-icon {
@@ -23,7 +23,7 @@
23
23
  }
24
24
 
25
25
  .alert-title {
26
- @apply text-para-md font-bold;
26
+ @apply text-heading-6 font-bold;
27
27
  }
28
28
 
29
29
  .alert-message {
@@ -34,10 +34,6 @@
34
34
  }
35
35
  }
36
36
 
37
- &.with-title .alert-message {
38
- @apply mt-1;
39
- }
40
-
41
37
  .alert-actions {
42
38
  @apply space-x-1 flex items-center;
43
39
  }
@@ -56,7 +52,7 @@
56
52
  @apply rounded-none;
57
53
 
58
54
  .alert-container {
59
- @apply @[1000px]:justify-center;
55
+ @apply @[1000px]:justify-center px-app;
60
56
  }
61
57
 
62
58
  .alert-body {
@@ -71,14 +67,36 @@
71
67
  @apply flex-none;
72
68
 
73
69
  .coco-button .button-element {
74
- @apply text-content-dark-2 hover:text-content-dark-1;
70
+ @apply text-content-dark-2 hover:text-content-dark-1 bg-transparent hover:bg-white/10 transition;
75
71
  }
76
72
  }
77
73
  }
78
74
 
75
+ /* Condensed */
76
+
77
+ &[data-condensed="true"] {
78
+ .alert-icon {
79
+ .coco-icon {
80
+ @apply w-4 h-4;
81
+ }
82
+ }
83
+
84
+ .alert-body {
85
+ @apply pl-3;
86
+ }
87
+
88
+ .alert-title {
89
+ @apply text-para-sm;
90
+ }
91
+
92
+ .alert-message {
93
+ @apply text-para-sm;
94
+ }
95
+ }
96
+
79
97
  /* Layout */
80
98
 
81
- @apply app-alert-stacked @[500px]:app-alert-multi-line;
99
+ @apply app-alert-stacked @[576px]:app-alert-multi-line;
82
100
 
83
101
  &[data-single-line="true"]:not(.force-multi-line) {
84
102
  @apply @[1000px]:app-alert-single-line;
@@ -95,7 +113,7 @@
95
113
  }
96
114
 
97
115
  &[data-theme*="vivid"] {
98
- @apply border-none;
116
+ @apply border-none antialiased;
99
117
 
100
118
  .alert-content {
101
119
  @apply text-content-light-1;
@@ -186,13 +204,16 @@
186
204
 
187
205
  @layer utilities {
188
206
  .app-alert-stacked {
189
- .alert-title {
190
- matgin-top: -1px;
191
- margin-bottom: 2px;
207
+ .alert-container {
208
+ @apply py-4;
192
209
  }
193
210
 
194
211
  .alert-actions {
195
- @apply mt-2;
212
+ @apply mt-3;
213
+ }
214
+
215
+ &.with-title .alert-message {
216
+ @apply mt-1;
196
217
  }
197
218
 
198
219
  &[data-dismissable="true"] {
@@ -208,7 +229,7 @@
208
229
 
209
230
  .app-alert-multi-line {
210
231
  .alert-container {
211
- @apply items-center;
232
+ @apply items-center py-2.5;
212
233
  }
213
234
 
214
235
  .alert-icon {
@@ -227,22 +248,34 @@
227
248
  margin-bottom: 0;
228
249
  }
229
250
 
251
+ &.with-title .alert-message {
252
+ @apply mt-1;
253
+ }
254
+
255
+ &[data-condensed="true"].with-title .alert-message {
256
+ @apply mt-0.5;
257
+ }
258
+
230
259
  .alert-actions {
231
260
  @apply mt-0 ml-auto;
232
261
  }
233
262
 
234
263
  &[data-dismissable="true"] {
235
- .alert-container {
236
- @apply pr-3;
264
+ .alert-body {
265
+ @apply pr-10;
237
266
  }
238
267
 
239
268
  .alert-dismiss {
240
- @apply relative top-auto right-auto flex flex-col;
269
+ @apply absolute right-3 top-1/2 -translate-y-1/2;
241
270
  }
242
271
  }
243
272
  }
244
273
 
245
274
  .app-alert-single-line {
275
+ .alert-container {
276
+ @apply py-3;
277
+ }
278
+
246
279
  .alert-content {
247
280
  @apply flex items-center w-full space-x-2;
248
281
  }
@@ -251,8 +284,22 @@
251
284
  @apply whitespace-nowrap;
252
285
  }
253
286
 
287
+ &.with-title .alert-message {
288
+ @apply mt-0;
289
+ }
290
+
254
291
  .alert-link {
255
292
  @apply hidden;
256
293
  }
294
+
295
+ &[data-dismissable="true"] {
296
+ .alert-container {
297
+ @apply px-12;
298
+ }
299
+
300
+ .alert-dismiss {
301
+ @apply absolute right-[21px] top-1/2 -translate-y-1/2;
302
+ }
303
+ }
257
304
  }
258
305
  }
@@ -1,8 +1,8 @@
1
1
  <%= render component_tag(x: {
2
2
  data: "appAlert",
3
- show: "!dismissed",
4
3
  bind: "root",
5
- cloak: true
4
+ show: "!dismissed",
5
+ cloak: (true if cloak?)
6
6
  }, class: {
7
7
  "with-title": title?,
8
8
  "vivid": vivid?
@@ -44,7 +44,7 @@
44
44
  <%= coco_button(
45
45
  *@action_data[:args],
46
46
  **@action_data[:kwargs],
47
- size: :sm,
47
+ size: button_size,
48
48
  &@action_data[:block]
49
49
  ) %>
50
50
  </div>
@@ -58,7 +58,7 @@
58
58
  <%= coco_button(
59
59
  *@secondary_action_data[:args],
60
60
  **@secondary_action_data[:kwargs],
61
- size: :sm,
61
+ size: button_size,
62
62
  &@secondary_action_data[:block]
63
63
  ) %>
64
64
  </div>
@@ -21,18 +21,19 @@ export default CocoComponent("appAlert", () => {
21
21
  },
22
22
 
23
23
  remove() {
24
+ this.$nextTick(() => this.$dispatch("alert:removed", { alert: this }));
24
25
  this.$root.remove();
25
26
  },
26
27
 
27
28
  checkSingleLineWrap({ height }) {
28
- if (!this.forceMultiLine) {
29
+ this.forceMultiLine = false;
30
+ this.$nextTick(() => {
29
31
  this.forceMultiLine = height > 24 && this.$options.singleLine;
30
- }
32
+ });
31
33
  },
32
34
 
33
35
  root: {
34
36
  "x-options": '["dismissable", "singleLine"]',
35
- "x-show": "!dismissed",
36
37
  ":class": "{'force-multi-line': forceMultiLine}",
37
38
  },
38
39
  };
@@ -22,6 +22,8 @@ module Coco
22
22
  accepts_option :banner, from: [true, false], default: false
23
23
  accepts_option :theme, from: THEMES, default: "info"
24
24
  accepts_option :single_line, from: [true, false]
25
+ accepts_option :cloak, from: [true, false], default: true, private: true
26
+ accepts_option :condensed, from: [true, false], default: false
25
27
 
26
28
  renders_one :title
27
29
 
@@ -58,6 +60,10 @@ module Coco
58
60
  get_option_value(:single_line)
59
61
  end
60
62
 
63
+ def cloak?
64
+ get_option_value(:cloak)
65
+ end
66
+
61
67
  def vivid?
62
68
  theme = get_option_value(:theme)
63
69
  theme.to_s.match?(/vivid$/)
@@ -66,6 +72,10 @@ module Coco
66
72
  def unvividify(theme)
67
73
  theme.to_s.match?(/vivid$/) ? theme.to_s.underscore.gsub("_vivid", "").to_sym : theme
68
74
  end
75
+
76
+ def button_size
77
+ get_option_value(:condensed) ? :xs : :sm
78
+ end
69
79
  end
70
80
  end
71
81
  end
@@ -286,6 +286,10 @@
286
286
 
287
287
  /* Responsive resizing */
288
288
 
289
+ &[data-size="xs"] {
290
+ @apply app-button-xs;
291
+ }
292
+
289
293
  &[data-size="sm"] {
290
294
  @apply app-button-sm;
291
295
  }
@@ -299,6 +303,10 @@
299
303
  }
300
304
 
301
305
  @media screen(md) {
306
+ &[data-size-md="xs"] {
307
+ @apply app-button-xs;
308
+ }
309
+
302
310
  &[data-size-md="sm"] {
303
311
  @apply app-button-sm;
304
312
  }
@@ -313,6 +321,10 @@
313
321
  }
314
322
 
315
323
  @media screen(lg) {
324
+ &[data-size-lg="xs"] {
325
+ @apply app-button-xs;
326
+ }
327
+
316
328
  &[data-size-lg="sm"] {
317
329
  @apply app-button-sm;
318
330
  }
@@ -327,6 +339,10 @@
327
339
  }
328
340
 
329
341
  @media screen(xl) {
342
+ &[data-size-xl="xs"] {
343
+ @apply app-button-xs;
344
+ }
345
+
330
346
  &[data-size-xl="sm"] {
331
347
  @apply app-button-sm;
332
348
  }
@@ -341,6 +357,11 @@
341
357
  }
342
358
 
343
359
  @media screen(2xl) {
360
+ &[data-size-xxl="xs"],
361
+ &[data-size-2xl="xs"] {
362
+ @apply app-button-xs;
363
+ }
364
+
344
365
  &[data-size-xxl="sm"],
345
366
  &[data-size-2xl="sm"] {
346
367
  @apply app-button-sm;
@@ -358,6 +379,10 @@
358
379
  }
359
380
 
360
381
  @media screen(max) {
382
+ &[data-size-max="xs"] {
383
+ @apply app-button-xs;
384
+ }
385
+
361
386
  &[data-size-max="sm"] {
362
387
  @apply app-button-sm;
363
388
  }
@@ -374,6 +399,39 @@
374
399
  }
375
400
 
376
401
  @layer utilities {
402
+ .app-button-xs {
403
+ .button-content {
404
+ @apply text-label-xs;
405
+ }
406
+
407
+ .button-icon [data-component="icon"],
408
+ .button-toggle {
409
+ @apply w-3.5 h-3.5;
410
+ }
411
+
412
+ &[data-theme] {
413
+ .button-element {
414
+ @apply py-2 px-3;
415
+ }
416
+
417
+ &.icon-only > .button-element .button-icon,
418
+ &[data-collapsed="true"] > .button-element .button-icon {
419
+ @apply -ml-1.5 -mr-1.5;
420
+ }
421
+ }
422
+
423
+ &[data-theme|="text"] {
424
+ .button-element {
425
+ @apply px-1;
426
+ }
427
+
428
+ &.icon-only > .button-element .button-icon,
429
+ &[data-collapsed="true"] > .button-element .button-icon {
430
+ @apply px-2;
431
+ }
432
+ }
433
+ }
434
+
377
435
  .app-button-sm {
378
436
  .button-content {
379
437
  @apply text-label-sm;
@@ -2,7 +2,7 @@ module Coco
2
2
  module App
3
3
  module Elements
4
4
  class Button < Coco::Button
5
- SIZES = [:sm, :md, :lg, nil]
5
+ SIZES = [:xs, :sm, :md, :lg, nil]
6
6
 
7
7
  SIZE_ALIASES = {
8
8
  default: [:sm, {xl: :md}]
@@ -26,6 +26,10 @@ module Coco
26
26
  **kwargs
27
27
  }
28
28
 
29
+ if component_args.key?(:resize)
30
+ args[:resize] = component_args[:resize]
31
+ end
32
+
29
33
  if get_option_value(:collapsible) == false
30
34
  args[:collapsible] = false
31
35
  end
@@ -20,7 +20,7 @@ module Coco
20
20
  {color: "#3A2D86"}
21
21
  ]
22
22
 
23
- accepts_option :size, from: [:sm, :md, nil], default: :sm
23
+ accepts_option :size, from: [:xs, :sm, :md, nil], default: :sm
24
24
 
25
25
  before_render do
26
26
  content unless content_evaluated?
@@ -1,6 +1,7 @@
1
1
  @layer components {
2
2
  [data-coco][data-component="app-menu"] {
3
3
  width: fit-content;
4
+ max-width: 240px;
4
5
 
5
6
  .menu-item {
6
7
  > * {
@@ -1,6 +1,6 @@
1
1
  <%= render component_tag do %>
2
2
  <ol class="menu-items">
3
- <% items.each do |item| %>
3
+ <% items.compact.each do |item| %>
4
4
  <li class="menu-item">
5
5
  <%= item %>
6
6
  </li>
@@ -5,9 +5,10 @@ module Coco
5
5
  include Concerns::ActsAsButtonGroup
6
6
  include Concerns::AcceptsOptions
7
7
 
8
- accepts_option :size, from: [:sm, :md, nil], default: :sm
8
+ accepts_option :size, from: [:xs, :sm, :md, nil], default: :sm
9
9
 
10
10
  renders_many :htmls, ->(*args, **kwargs, &block) do
11
+ init_button_group
11
12
  items << block.call
12
13
  end
13
14
 
@@ -0,0 +1,22 @@
1
+ @layer components {
2
+ [data-coco][data-component="app-user-profile"] {
3
+ @apply px-4 py-1.5 grid grid-rows-1 gap-3;
4
+ grid-template-columns: min-content 1fr;
5
+
6
+ .user-profile-avatar {
7
+ @apply flex items-center;
8
+ }
9
+
10
+ .user-profile-details {
11
+ @apply space-y-1;
12
+ }
13
+
14
+ .user-profile-name {
15
+ @apply font-semibold truncate;
16
+ }
17
+
18
+ .user-profile-email {
19
+ @apply text-gray-500 text-label-sm italic truncate;
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,17 @@
1
+ <%= render component_tag do %>
2
+ <div class="user-profile-avatar">
3
+ <%= avatar %>
4
+ </div>
5
+ <div class="user-profile-details">
6
+ <% if name.present? %>
7
+ <h5 class="user-profile-name">
8
+ <%= name %>
9
+ </h5>
10
+ <% end %>
11
+ <% if email.present? %>
12
+ <div class="user-profile-email">
13
+ <%= email %>
14
+ </div>
15
+ <% end %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,20 @@
1
+ module Coco
2
+ module App
3
+ module Elements
4
+ module MenuItems
5
+ class UserProfile < Coco::Component
6
+ renders_one :avatar, ->(**kwargs) do
7
+ Coco::Avatar.new(name: name, **kwargs, size: :lg)
8
+ end
9
+
10
+ attr_reader :name, :email
11
+
12
+ def initialize(name:, email:, **)
13
+ @name = name
14
+ @email = email
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,9 @@
1
1
  @layer components {
2
2
  [data-coco][data-component="app-notice"] {
3
3
  @apply rounded-xl overflow-hidden;
4
+
5
+ div[class="alert-container"] {
6
+ @apply py-4;
7
+ }
4
8
  }
5
9
  }
@@ -1,3 +1,9 @@
1
+ @layer base {
2
+ :root {
3
+ --snackbar-bottom-offset: theme(spacing.8);
4
+ }
5
+ }
6
+
1
7
  @layer components {
2
8
  [data-coco][data-component="app-snackbar"] {
3
9
  @apply bg-background-dark-2 rounded-xl overflow-hidden shadow-xl w-full;
@@ -46,7 +52,8 @@
46
52
  }
47
53
 
48
54
  &[data-position="fixed"] {
49
- @apply fixed bottom-8 left-1/2 -translate-x-1/2;
55
+ @apply fixed left-1/2 -translate-x-1/2;
56
+ bottom: var(--snackbar-bottom-offset);
50
57
  z-index: 10001;
51
58
  }
52
59
 
@@ -14,8 +14,8 @@ module Coco
14
14
 
15
15
  accepts_option :theme, from: [:positive, :warning, :negative, :pending]
16
16
 
17
- renders_one :action, ->(**kwargs, &block) do
18
- Coco::App::Elements::Button.new(**kwargs, theme: :blank, size: :sm, icon: nil)
17
+ renders_one :action, ->(*args, **kwargs, &block) do
18
+ coco_button(*args, **kwargs, theme: :blank, size: :sm, icon: nil, &block)
19
19
  end
20
20
 
21
21
  before_render do
@@ -1,4 +1,5 @@
1
- <%= render component_tag(x: { data: "appSystemBanner" }) do %>
1
+ <%= render component_tag(
2
+ x: { data: x_data("appSystemBanner", alpine_data), bind: "root"}) do %>
2
3
  <%= render alert do %>
3
4
  <%= content %>
4
5
  <% end %>
@@ -1,5 +1,38 @@
1
1
  import { CocoComponent } from "@js/coco";
2
+ import Cookies from "js-cookie";
2
3
 
3
- export default CocoComponent("appSystemBanner", () => {
4
- return {};
4
+ export default CocoComponent("appSystemBanner", (opts = {}) => {
5
+ return {
6
+ cookieName: null,
7
+ cookieValue: null,
8
+ cookieExpiry: null,
9
+
10
+ init() {
11
+ this.cookieName = opts.cookieName;
12
+ this.cookieValue = opts.cookieValue;
13
+ this.cookieExpiry = opts.cookieExpiry;
14
+ },
15
+
16
+ onDismiss() {
17
+ this.$dispatch("banner:dismiss", { banner: this });
18
+ if (this.shouldSetCookie) {
19
+ Cookies.set(this.cookieName, this.cookieValue, {
20
+ expires: this.cookieExpiry,
21
+ });
22
+ }
23
+ },
24
+
25
+ remove() {
26
+ this.$root.remove();
27
+ },
28
+
29
+ get shouldSetCookie() {
30
+ return Number.isInteger(this.cookieExpiry);
31
+ },
32
+
33
+ root: {
34
+ "@alert:dismiss": "onDismiss",
35
+ "@alert:removed": "remove",
36
+ },
37
+ };
5
38
  });
@@ -5,17 +5,61 @@ module Coco
5
5
  include Concerns::AcceptsOptions
6
6
  include Concerns::WrapsComponent
7
7
 
8
+ accepts_option :dismissable, from: [true, false], default: false
9
+
8
10
  wraps_component :alert do |args|
9
11
  theme = vivid_theme_name(args.fetch(:theme, nil)) || :info_vivid
10
- Coco::App::Elements::Alert.new(**args, theme: theme, banner: true, single_line: true)
12
+ Coco::App::Elements::Alert.new(
13
+ **args,
14
+ theme: theme,
15
+ banner: true,
16
+ cloak: false,
17
+ single_line: true,
18
+ dismissable: dismissable?,
19
+ condensed: true
20
+ )
11
21
  end
12
22
 
13
23
  %i[title action secondary_action link].each do |slot_name|
14
- renders_one slot_name, ->(**kwargs, &block) do
15
- alert.send("with_#{slot_name}".to_sym, **kwargs, &block)
24
+ renders_one slot_name, ->(*args, **kwargs, &block) do
25
+ alert.send("with_#{slot_name}".to_sym, *args, **kwargs, &block)
26
+ end
27
+ end
28
+
29
+ before_render do
30
+ if dismissable? && id.blank?
31
+ raise ArgumentError, "Dismissable banners must be given an ID"
16
32
  end
17
33
  end
18
34
 
35
+ attr_reader :dismiss_for, :id
36
+
37
+ def initialize(id: nil, dismiss_for: nil, **)
38
+ @id = id
39
+ @dismiss_for = dismiss_for
40
+ set_tag_attr(:id, id)
41
+ end
42
+
43
+ def dismissable?
44
+ get_option_value(:dismissable) == true
45
+ end
46
+
47
+ def render?
48
+ helpers.cookies[dismiss_cookie_name] != "true"
49
+ end
50
+
51
+ def dismiss_cookie_name
52
+ "cb_system_banner_#{tag_attr(:id)&.underscore}_dismissed".to_sym
53
+ end
54
+
55
+ def alpine_data
56
+ dismissable? ? {
57
+ cookie_name: dismiss_cookie_name,
58
+ cookie_expiry: dismiss_for&.in_days&.to_i,
59
+ cookie_value: "true"
60
+ } : {}
61
+ end
62
+
19
63
  private
20
64
 
21
65
  def vivid_theme_name(theme)