coveragebook_components 0.7.9 → 0.8.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/build/coco/app.css +1134 -165
  3. data/app/assets/build/coco/app.js +307 -49
  4. data/app/assets/build/coco/book.css +55 -9
  5. data/app/assets/build/coco/book.js +24 -2
  6. data/app/assets/css/app/tippy.css +4 -0
  7. data/app/assets/css/base/base.css +12 -0
  8. data/app/assets/css/base/components/coco.css +0 -3
  9. data/app/assets/js/app/setup.js +22 -0
  10. data/app/assets/js/app.js +2 -0
  11. data/app/assets/js/helpers/location.js +9 -0
  12. data/app/assets/js/libs/tippy/index.js +7 -2
  13. data/app/components/coco/app/blocks/header/header.css +43 -0
  14. data/app/components/coco/app/blocks/header/header.html.erb +30 -0
  15. data/app/components/coco/app/blocks/header/header.js +11 -0
  16. data/app/components/coco/app/blocks/header/header.rb +35 -0
  17. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.css +48 -3
  18. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.html.erb +14 -6
  19. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.js +18 -1
  20. data/app/components/coco/app/blocks/nav_drawer/nav_drawer.rb +26 -1
  21. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.css +104 -0
  22. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.html.erb +42 -0
  23. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.js +28 -0
  24. data/app/components/coco/app/blocks/sidebar_nav/sidebar_nav.rb +28 -0
  25. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.css +165 -0
  26. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.html.erb +43 -0
  27. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.js +41 -0
  28. data/app/components/coco/app/blocks/sidebar_nav_item/sidebar_nav_item.rb +98 -0
  29. data/app/components/coco/app/elements/alert/alert.css +65 -18
  30. data/app/components/coco/app/elements/alert/alert.html.erb +20 -5
  31. data/app/components/coco/app/elements/alert/alert.js +4 -3
  32. data/app/components/coco/app/elements/alert/alert.rb +16 -6
  33. data/app/components/coco/app/elements/button/button.css +87 -5
  34. data/app/components/coco/app/elements/button/button.rb +3 -1
  35. data/app/components/coco/app/elements/button_group/button_group.rb +4 -0
  36. data/app/components/coco/app/elements/button_to/button_to.css +5 -1
  37. data/app/components/coco/app/elements/button_to/button_to.rb +8 -1
  38. data/app/components/coco/app/elements/color_picker/color_picker.rb +1 -1
  39. data/app/components/coco/app/elements/menu/menu.css +5 -0
  40. data/app/components/coco/app/elements/menu/menu.html.erb +1 -1
  41. data/app/components/coco/app/elements/menu/menu.rb +2 -1
  42. data/app/components/coco/app/elements/menu_button/menu_button.html.erb +6 -0
  43. data/app/components/coco/app/elements/menu_button/menu_button.rb +8 -9
  44. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.css +22 -0
  45. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.html.erb +17 -0
  46. data/app/components/coco/app/elements/menu_items/user_profile/user_profile.rb +20 -0
  47. data/app/components/coco/app/elements/notice/notice.css +4 -0
  48. data/app/components/coco/app/elements/notice/notice.rb +2 -2
  49. data/app/components/coco/app/elements/snackbar/snackbar.css +8 -1
  50. data/app/components/coco/app/elements/snackbar/snackbar.rb +2 -2
  51. data/app/components/coco/app/elements/system_banner/system_banner.html.erb +2 -1
  52. data/app/components/coco/app/elements/system_banner/system_banner.js +35 -2
  53. data/app/components/coco/app/elements/system_banner/system_banner.rb +47 -3
  54. data/app/components/coco/app/layouts/application/application.css +104 -4
  55. data/app/components/coco/app/layouts/application/application.html.erb +28 -7
  56. data/app/components/coco/app/layouts/application/application.js +16 -0
  57. data/app/components/coco/app/layouts/application/application.rb +11 -3
  58. data/app/components/coco/base/avatar/avatar.css +25 -0
  59. data/app/components/coco/base/avatar/avatar.rb +20 -0
  60. data/app/components/coco/base/icon/icon.css +6 -2
  61. data/app/components/coco/base/icon/icon.rb +1 -1
  62. data/app/components/coco/base/modal/modal.css +2 -1
  63. data/app/components/coco/base/modal/modal.html.erb +1 -1
  64. data/app/components/coco/base/modal/modal.js +2 -0
  65. data/app/components/coco/base/modal_lightbox/modal_lightbox.js +2 -2
  66. data/app/components/coco/base/placeholder/placeholder.css +15 -1
  67. data/app/components/coco/base/placeholder/placeholder.rb +2 -0
  68. data/app/components/coco/concerns/accepts_tag_attributes.rb +6 -2
  69. data/app/components/coco/concerns/acts_as_button_group.rb +30 -12
  70. data/app/helpers/coco/app_helper.rb +26 -2
  71. data/app/helpers/coco/base_helper.rb +6 -0
  72. data/app/helpers/coco/url_helper.rb +5 -1
  73. data/config/tailwind.base.config.cjs +3 -0
  74. data/config/tokens.cjs +6 -0
  75. data/lib/coco.rb +1 -1
  76. metadata +24 -10
  77. data/app/components/coco/app/blocks/banner/banner.css +0 -5
  78. data/app/components/coco/app/blocks/banner/banner.rb +0 -8
  79. data/app/components/coco/app/blocks/nav_bar/nav_bar.css +0 -51
  80. data/app/components/coco/app/blocks/nav_bar/nav_bar.html.erb +0 -23
  81. data/app/components/coco/app/blocks/nav_bar/nav_bar.js +0 -31
  82. data/app/components/coco/app/blocks/nav_bar/nav_bar.rb +0 -19
@@ -12,4 +12,8 @@
12
12
  .tippy-box[data-theme~="coco-app-menu"] {
13
13
  @apply tippy-dropdown-box;
14
14
  }
15
+
16
+ .tippy-box[data-theme~="coco-naked-dropdown"] {
17
+ width: min-content;
18
+ }
15
19
  }
@@ -10,10 +10,22 @@
10
10
  @import "./components/coco";
11
11
 
12
12
  @layer base {
13
+ :root {
14
+ --app-height: 100%;
15
+ }
16
+
13
17
  html {
14
18
  @apply font-body scroll-smooth motion-safe:scroll-auto text-content-dark-1;
15
19
  }
16
20
 
21
+ html.app-layout,
22
+ html.app-layout body {
23
+ width: 100vw;
24
+ height: 100vh;
25
+ height: var(—-app-height);
26
+ overflow: hidden;
27
+ }
28
+
17
29
  a {
18
30
  @apply text-current underline underline-offset-2;
19
31
  }
@@ -2,9 +2,6 @@
2
2
  [data-coco] {
3
3
  @apply text-content-dark-1 font-body;
4
4
 
5
- -webkit-font-smoothing: antialiased;
6
- -moz-osx-font-smoothing: grayscale;
7
-
8
5
  h1,
9
6
  h2,
10
7
  h3,
@@ -0,0 +1,22 @@
1
+ import { navigateTo } from "@helpers/location";
2
+
3
+ // Global JS navigation handler.
4
+ // Optionally uses Turbo for the page navigation.
5
+ window.addEventListener("navigate", (event) => {
6
+ const { url, turbo, action } = event.detail;
7
+ if (url) {
8
+ navigateTo(url, { turbo, action });
9
+ }
10
+ });
11
+
12
+ // Uodate the value of the `--app-height` css variable
13
+ // when the viewport size changes. To help work around the
14
+ // issues when using 100vh on mobile safari (https://medium.com/quick-code/100vh-problem-with-ios-safari-92ab23c852a8)
15
+ function setAppHeightProperty() {
16
+ document.documentElement.style.setProperty(
17
+ "--app-height",
18
+ `${window.innerHeight}px`
19
+ );
20
+ }
21
+ window.addEventListener("resize", setAppHeightProperty);
22
+ setAppHeightProperty();
data/app/assets/js/app.js CHANGED
@@ -5,6 +5,8 @@ console.info("Initializing Coco JS", packageJSON.version);
5
5
  import "container-query-polyfill";
6
6
  import Alpine from "@libs/alpine";
7
7
 
8
+ import "./app/setup";
9
+
8
10
  import "./base/components";
9
11
  import "./book/components";
10
12
  import "./app/components";
@@ -0,0 +1,9 @@
1
+ function navigateTo(url, options = {}) {
2
+ if (window.Turbo && options.turbo === true) {
3
+ window.Turbo.visit(url, { action: options.action || "advance" });
4
+ } else {
5
+ location.assign(url);
6
+ }
7
+ }
8
+
9
+ export { navigateTo };
@@ -1,4 +1,9 @@
1
- import tippy, { createSingleton, followCursor, roundArrow } from "tippy.js";
1
+ import tippy, {
2
+ createSingleton,
3
+ followCursor,
4
+ roundArrow,
5
+ hideAll,
6
+ } from "tippy.js";
2
7
  import hideOnEsc from "./plugins/hide_on_esc";
3
8
 
4
9
  tippy.setDefaultProps({
@@ -9,4 +14,4 @@ tippy.setDefaultProps({
9
14
  });
10
15
 
11
16
  export default tippy;
12
- export { tippy, createSingleton, hideOnEsc, followCursor };
17
+ export { tippy, createSingleton, hideOnEsc, followCursor, hideAll };
@@ -0,0 +1,43 @@
1
+ @layer components {
2
+ [data-coco][data-component="app-header"] {
3
+ @apply @container;
4
+
5
+ .header-content {
6
+ @apply h-14 flex items-center bg-background-header px-app;
7
+ }
8
+
9
+ .header-logo {
10
+ @apply flex-none mr-6;
11
+ }
12
+
13
+ .header-logo-no-wordmark {
14
+ @apply h-7 xs:hidden translate-x-1;
15
+ }
16
+
17
+ .header-logo-full {
18
+ @apply hidden xs:block h-7;
19
+ }
20
+
21
+ .header-links {
22
+ @apply flex items-center w-full;
23
+ }
24
+
25
+ .header-link-group {
26
+ @apply items-center gap-x-6;
27
+ }
28
+
29
+ .header-secondary {
30
+ @apply ml-auto translate-x-2 sm:translate-x-[17px];
31
+ }
32
+
33
+ .header-mobile-controls {
34
+ @apply flex @4xl:hidden items-center ml-auto translate-x-2 sm:translate-x-4 md:translate-x-6;
35
+ }
36
+
37
+ &.with-nav-drawer {
38
+ .header-link-group {
39
+ @apply hidden @4xl:flex;
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,30 @@
1
+ <%= render component_tag(
2
+ x: {data: "appHeader", "bind:class": "{'drawer-open': drawerOpen}"},
3
+ class: {"with-nav-drawer": mobile_nav?}
4
+ ) do %>
5
+ <div class="header-content">
6
+ <%= tag.send(home_path ? :a : :div, class: "header-logo", href: home_path) do %>
7
+ <%= image_tag asset_url("coco/img/coveragebook-logomark-white.svg"),
8
+ alt: "CoverageBook logomark",
9
+ class: "header-logo-no-wordmark" %>
10
+ <%= image_tag asset_url("coco/img/coveragebook-landscape-white.svg"),
11
+ alt: "CoverageBook full logo",
12
+ class: "header-logo-full" %>
13
+ <% end %>
14
+ <nav class="header-links" x-ref="links">
15
+ <div class="header-link-group header-primary" x-ref="primaryLinks">
16
+ <%= primary_nav %>
17
+ </div>
18
+ <div class="header-link-group header-secondary" x-ref="secondaryLinks">
19
+ <%= secondary_nav %>
20
+ </div>
21
+ <% if mobile_nav? %>
22
+ <div class="header-mobile-controls">
23
+ <%= coco_button(icon: :menu, theme: :text_neutral_light, size: :md, click: "toggleDrawer", x: {show: "!drawerOpen"}) %>
24
+ <%= coco_button(icon: :x, theme: :text_neutral_light, size: :md, click: "toggleDrawer", x: {show: "drawerOpen", cloak: true}) %>
25
+ </div>
26
+ <% end %>
27
+ </nav>
28
+ </div>
29
+ <%= mobile_nav %>
30
+ <% end %>
@@ -0,0 +1,11 @@
1
+ import { CocoComponent } from "@js/coco";
2
+
3
+ export default CocoComponent("appHeader", () => {
4
+ return {
5
+ drawerOpen: false,
6
+
7
+ toggleDrawer() {
8
+ this.drawerOpen = !this.drawerOpen;
9
+ },
10
+ };
11
+ });
@@ -0,0 +1,35 @@
1
+ module Coco
2
+ module App
3
+ module Blocks
4
+ class Header < Coco::Component
5
+ renders_one :primary_nav, ->(**kwargs) do
6
+ Coco::App::Elements::ButtonGroup.new(
7
+ theme: :text_neutral_light,
8
+ collapsible: false,
9
+ size: :sm,
10
+ **kwargs
11
+ )
12
+ end
13
+
14
+ renders_one :secondary_nav, ->(**kwargs) do
15
+ Coco::App::Elements::ButtonGroup.new(
16
+ theme: :text_neutral_light,
17
+ collapsible: false,
18
+ size: :sm,
19
+ **kwargs
20
+ )
21
+ end
22
+
23
+ renders_one :mobile_nav, ->(**kwargs) do
24
+ Coco::App::Blocks::NavDrawer.new(**kwargs)
25
+ end
26
+
27
+ attr_reader :home_path
28
+
29
+ def initialize(home_path: nil, **)
30
+ @home_path = home_path
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,9 +1,54 @@
1
1
  @layer components {
2
2
  [data-coco][data-component="app-nav-drawer"] {
3
- @apply fixed top-0 left-0 bottom-0 h-screen w-[340px] bg-white shadow-2xl overflow-hidden;
3
+ @apply pointer-events-none fixed top-14 left-0 bottom-0 w-screen overflow-hidden;
4
+ height: var(--app-height);
4
5
 
5
- .nav-inner {
6
- @apply p-4;
6
+ .nav-drawer-overlay {
7
+ @apply pointer-events-none absolute inset-0 bg-black opacity-0 transition-opacity;
8
+ }
9
+
10
+ .nav-drawer-content {
11
+ @apply absolute top-0 right-0 bottom-0 bg-white overflow-auto translate-x-full transition-transform py-4;
12
+ max-width: 340px;
13
+ min-width: 280px;
14
+ width: fit-content;
15
+ }
16
+
17
+ .nav-drawer-item:last-child {
18
+ @apply mb-10;
19
+ }
20
+
21
+ .nav-drawer-button {
22
+ @apply w-full text-content-dark-2 hover:text-content-dark-1 hover:bg-background-light-3;
23
+
24
+ .button-inner {
25
+ @apply mx-0 px-4 py-3;
26
+ }
27
+ }
28
+
29
+ .nav-drawer-heading {
30
+ @apply mt-4 mb-2 mx-4 border-b text-content-dark-1/50 border-gray-300 pb-3;
31
+ }
32
+
33
+ .nav-drawer-divider {
34
+ @apply h-0 border-t border-gray-300 my-3;
35
+ }
36
+
37
+ [data-component="app-notice"] {
38
+ @apply mb-4;
39
+ }
40
+
41
+ .drawer-open & {
42
+ @apply pointer-events-auto;
43
+
44
+ .nav-drawer-overlay {
45
+ @apply pointer-events-auto opacity-60;
46
+ backdrop-filter: blur(2px);
47
+ }
48
+
49
+ .nav-drawer-content {
50
+ @apply pointer-events-auto translate-x-0 shadow-2xl;
51
+ }
7
52
  }
8
53
  }
9
54
  }
@@ -1,8 +1,16 @@
1
- <%= render component_tag(x: { data: "appNavDrawer" }) do %>
2
- <div class="nav-inner">
3
- <div class="nav-header">
4
- <%= coco_button(icon: :x, theme: nil) %>
5
- </div>
6
- <%= content %>
1
+ <%= render component_tag(
2
+ x: {
3
+ data: "appNavDrawer",
4
+ "@keydown.escape.document": "close",
5
+ "@resize.window": "close"
6
+ }
7
+ ) do %>
8
+ <div class="nav-drawer-overlay" @click="close"></div>
9
+ <div class="nav-drawer-content" x-ref="content" x-trap.noscroll.inert.noreturn="active">
10
+ <% items.each do |item| %>
11
+ <div class="nav-drawer-item">
12
+ <%= item %>
13
+ </div>
14
+ <% end %>
7
15
  </div>
8
16
  <% end %>
@@ -2,6 +2,23 @@ import { CocoComponent } from "@js/coco";
2
2
 
3
3
  export default CocoComponent("appNavDrawer", () => {
4
4
  return {
5
- open: false,
5
+ active: false,
6
+
7
+ init() {
8
+ this.$watch("drawerOpen", (open) => {
9
+ if (open) {
10
+ this.$refs.content.scrollTop = 0;
11
+ setTimeout(() => {
12
+ this.active = true;
13
+ }, 200);
14
+ } else {
15
+ this.active = false;
16
+ }
17
+ });
18
+ },
19
+
20
+ close() {
21
+ this.drawerOpen = false;
22
+ },
6
23
  };
7
24
  });
@@ -2,7 +2,32 @@ module Coco
2
2
  module App
3
3
  module Blocks
4
4
  class NavDrawer < Coco::Component
5
- include Coco::AppHelper
5
+ renders_many :items, types: {
6
+ html: ->(&block) { block.call },
7
+ divider: ->(&block) { tag.div class: "nav-drawer-divider" },
8
+ heading: ->(text, **kwargs, &block) do
9
+ tag.h4(text, class: "nav-drawer-heading")
10
+ end,
11
+ button: ->(*args, **kwargs, &block) do
12
+ coco_button(*args, **kwargs, theme: nil, size: :md, fit: :full, class: "nav-drawer-button", &block)
13
+ end
14
+ }
15
+
16
+ def with_divider(...)
17
+ with_item_divider(...)
18
+ end
19
+
20
+ def with_html(...)
21
+ with_item_html(...)
22
+ end
23
+
24
+ def with_button(...)
25
+ with_item_button(...)
26
+ end
27
+
28
+ def with_heading(...)
29
+ with_item_heading(...)
30
+ end
6
31
  end
7
32
  end
8
33
  end
@@ -0,0 +1,104 @@
1
+ @layer components {
2
+ [data-coco][data-component="app-sidebar-nav"] {
3
+ @apply bg-background-dark-2 antialiased;
4
+ @apply w-full h-14 grid grid-rows-1;
5
+ grid-template-columns: repeat(3, minmax(0, 1fr)) minmax(0, 1fr);
6
+
7
+ .nav-action {
8
+ .nav-item-label {
9
+ @apply hidden !text-content-primary-inverse-vivid;
10
+ }
11
+ }
12
+
13
+ .nav-actions-button {
14
+ @apply bg-content-primary-inverse-vivid transition-all text-content-light-1;
15
+ @apply h-10 w-10 flex items-center justify-center mx-auto rounded-full cursor-pointer;
16
+
17
+ &:hover {
18
+ transform: scale(1.05);
19
+ }
20
+
21
+ .coco-icon {
22
+ @apply h-6 w-6;
23
+ }
24
+ }
25
+
26
+ .nav-item {
27
+ @apply hidden sm:contents h-full justify-center w-full;
28
+ }
29
+
30
+ .mobile-nav-item {
31
+ @apply flex sm:contents;
32
+ }
33
+
34
+ @media screen(sm) {
35
+ @apply sidebar-nav-vertical-condensed;
36
+ }
37
+
38
+ @media screen(md) {
39
+ @apply sidebar-nav-vertical;
40
+ }
41
+
42
+ @media screen(letterbox) {
43
+ @apply sidebar-nav-vertical-condensed;
44
+ }
45
+ }
46
+
47
+ .sidebar-nav-action {
48
+ @apply flex items-start p-1;
49
+
50
+ .sidebar-nav-action-icon {
51
+ @apply flex-none mr-3 text-content-light-1;
52
+ }
53
+
54
+ .sidebar-nav-action-detail {
55
+ @apply w-full text-left;
56
+ }
57
+
58
+ .sidebar-nav-action-label {
59
+ @apply mb-0.5 font-semibold text-content-light-1;
60
+ }
61
+
62
+ .sidebar-nav-action-description {
63
+ @apply text-para-xs;
64
+ }
65
+ }
66
+
67
+ .sidebar-nav-menu a.sidebar-nav-actions-item {
68
+ width: 320px;
69
+ }
70
+ }
71
+
72
+ @layer utilities {
73
+ .sidebar-nav-vertical-condensed {
74
+ @apply block w-18 h-full;
75
+
76
+ .nav-action .nav-item-label {
77
+ @apply block;
78
+ }
79
+
80
+ .nav-actions-button {
81
+ @apply h-14 w-14 mb-2;
82
+
83
+ .coco-icon {
84
+ @apply w-8 h-8;
85
+ }
86
+ }
87
+ }
88
+
89
+ .sidebar-nav-vertical {
90
+ @apply block w-24 h-full;
91
+
92
+ .nav-action .nav-item-label {
93
+ @apply block;
94
+ }
95
+
96
+ .nav-actions-button {
97
+ @apply h-[72px] w-[72px];
98
+
99
+ .coco-icon {
100
+ @apply h-10 w-10;
101
+ }
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,42 @@
1
+ <%= render component_tag(:nav, x: {data: "appSidebarNav"}) do %>
2
+ <% if actions? %>
3
+ <div class="nav-item mobile-nav-item nav-action">
4
+ <%= render Coco::App::Blocks::SidebarNavItem.new(label: "Add", emphasise: true) do |item| %>
5
+ <% item.with_icon do %>
6
+ <span class="nav-actions-button">
7
+ <%= coco_icon :plus, size: :xl %>
8
+ </span>
9
+ <% end %>
10
+
11
+ <% item.with_menu do %>
12
+ <% actions_data.each do |action| %>
13
+ <%= coco_link(action[:href],
14
+ **action.except(:label, :description, :href, :icon),
15
+ theme: nil,
16
+ class: "sidebar-nav-menu-item sidebar-nav-actions-item") do %>
17
+ <div class="sidebar-nav-action">
18
+ <div class="sidebar-nav-action-icon">
19
+ <%= coco_icon(action[:icon], size: :md) %>
20
+ </div>
21
+ <div class="sidebar-nav-action-detail">
22
+ <h4 class="sidebar-nav-action-label">
23
+ <%= action[:label] %>
24
+ </h4>
25
+ <% if action.key?(:description) %>
26
+ <div class="sidebar-nav-action-description">
27
+ <%= raw action[:description] %>
28
+ </div>
29
+ <% end %>
30
+ </div>
31
+ </div>
32
+ <% end %>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
36
+ </div>
37
+ <% end %>
38
+
39
+ <% items.each do |item| %>
40
+ <%= item %>
41
+ <% end %>
42
+ <% end %>
@@ -0,0 +1,28 @@
1
+ import tokens from "@config/tokens.cjs";
2
+ import { CocoComponent } from "@js/coco";
3
+
4
+ const mobileMaxWidth = parseInt(tokens.app.screens.sm, 10);
5
+
6
+ export default CocoComponent("appSidebarNav", () => {
7
+ return {
8
+ sizeObserver: null,
9
+ mobileLayout: true,
10
+
11
+ init() {
12
+ this.sizeObserver = new ResizeObserver(
13
+ Alpine.throttle((entries) => {
14
+ this.$nextTick(() => {
15
+ const bodyWidth = entries[0].contentRect.width;
16
+ this.mobileLayout = bodyWidth < mobileMaxWidth;
17
+ });
18
+ }, 20)
19
+ );
20
+
21
+ this.sizeObserver.observe(document.documentElement);
22
+ },
23
+
24
+ destroy() {
25
+ this.sizeObserver && this.sizeObserver.disconnect();
26
+ },
27
+ };
28
+ });
@@ -0,0 +1,28 @@
1
+ module Coco
2
+ module App
3
+ module Blocks
4
+ class SidebarNav < Coco::Component
5
+ renders_many :actions, ->(label, href, icon:, **kwargs) do
6
+ @actions_data << {label: label, href: href, icon: icon, **kwargs}
7
+ end
8
+
9
+ renders_many :items, ->(label, href, show_on_mobile: true, **kwargs, &block) do
10
+ tag.div class: ["nav-item", ("mobile-nav-item" if show_on_mobile)] do
11
+ render Coco::App::Blocks::SidebarNavItem.new(
12
+ label: label,
13
+ href: href,
14
+ active: helpers.current_page?(href),
15
+ **kwargs
16
+ ), &block
17
+ end
18
+ end
19
+
20
+ attr_reader :actions_data
21
+
22
+ def initialize(**)
23
+ @actions_data = []
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end