@muten/shadcn 0.2.13 → 0.2.15

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.
package/kit.css CHANGED
@@ -5519,6 +5519,15 @@ a.cx-bc-item:hover { color: var(--foreground); }
5519
5519
  /* SidebarTrigger: in the icon column (its 32 px square sits where the rows' icons sit), folded or open */
5520
5520
  .cx-sb-trigger { align-self: flex-start; flex: none; margin-left: 0; }
5521
5521
  .cx-sidebar[data-collapsed="true"] .cx-sb-trigger { align-self: flex-start; }
5522
+ .cx-sidebar .cx-sb-trigger { width: 32px; height: 32px; } /* the rows' square, so its centre is the column's */
5523
+ /* THE HEADER AND THE FOOTER USE THE ICON COLUMN TOO. Whatever leads a link or a menu button there (a logo, an avatar,
5524
+ an icon) sits centred in a 32 px box exactly over the rows' icons, open or folded, so the logo, the trigger, every icon
5525
+ and the avatar make one straight line and nothing moves sideways when the rail folds. Folded, a menu button closes
5526
+ to that box (its words fade and the rail never crops the avatar). */
5527
+ .cx-sidebar :is(.cx-sb-head, .cx-sb-foot) > a, .cx-sidebar :is(.cx-sb-head, .cx-sb-foot) .cn-sidebar-menu-button { justify-content: flex-start; padding-left: 0; }
5528
+ .cx-sidebar :is(.cx-sb-head, .cx-sb-foot) > a > :first-child, .cx-sidebar :is(.cx-sb-head, .cx-sb-foot) .cn-sidebar-menu-button > :first-child { flex: none; width: 32px; display: flex; justify-content: center; object-fit: contain; }
5529
+ .cx-sidebar :is(.cx-sb-head, .cx-sb-foot) .cn-sidebar-menu-button { transition: width .2s var(--ease-out), padding .2s var(--ease-out); }
5530
+ .cx-sidebar[data-collapsed="true"] :is(.cx-sb-head, .cx-sb-foot) .cn-sidebar-menu-button { width: 32px; padding-right: 0; }
5522
5531
 
5523
5532
  /* Sheet: its content arrives a moment after the panel, one row after another; leaving, it goes with the panel */
5524
5533
  .cx-modal[data-mode="sheet"] .cx-modal-body > * { transition: opacity var(--t-pop) var(--ease-out), translate calc(var(--t-sheet) * .8) var(--ease-out); }
@@ -5607,3 +5616,26 @@ a.cx-bc-item:hover { color: var(--foreground); }
5607
5616
  .cn-badge[data-compact="true"]:hover .cx-tone-words, .cn-badge[data-compact="true"]:focus-within .cx-tone-words { grid-template-columns: 1fr; opacity: 1; }
5608
5617
  @media (hover: none) { .cn-badge[data-compact="true"] { gap: 8px; padding-inline: 12px; } .cn-badge[data-compact="true"] .cx-tone-words { grid-template-columns: 1fr; opacity: 1; } }
5609
5618
  @media (prefers-reduced-motion: reduce) { .cx-sb-ring, .cx-tone-ring { animation-duration: 1.6s; } .cn-badge[data-compact="true"], .cn-badge[data-compact="true"] .cx-tone-words, .cx-sb-hint { transition: none; } }
5619
+
5620
+ /* ═════ SIDEBAR FOLDS · groups and levels that open and close (SidebarFoldGroup, SidebarFold, SidebarRowToggle) ═════
5621
+ What opens and closes folds to its exact height (its row grows from 0fr) while the chevron turns; closed, it is out
5622
+ of reach of the keyboard too. A row's chevron sits over the row's right end. Folded to icons, everything shows. */
5623
+ .cx-sb-fold { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .2s var(--ease-out); }
5624
+ .cx-sb-fold[data-open="false"] { grid-template-rows: 0fr; }
5625
+ .cx-sb-fold-in { min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
5626
+ .cx-sb-fold[data-open="false"] > .cx-sb-fold-in { visibility: hidden; transition: visibility 0s .2s; }
5627
+ .cx-sb-chev { width: 15px; height: 15px; flex: none; color: var(--muted-foreground); transition: transform .2s var(--ease-out); }
5628
+ [aria-expanded="false"] > .cx-sb-chev { transform: rotate(-90deg); }
5629
+ .cx-sb-gtoggle { display: flex; flex-direction: row; align-items: center; justify-content: space-between; width: 100%; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; border-radius: calc(var(--radius) * .6); }
5630
+ .cx-sb-gtoggle:hover { color: var(--foreground); }
5631
+ .cx-sb-gtoggle:focus-visible, .cx-sb-rowtoggle:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }
5632
+ .cx-sb-rowtoggle { align-self: flex-end; position: relative; z-index: 1; width: 24px; height: 24px; margin: -28px 4px 4px 0; display: grid; place-items: center; padding: 0; border: 0; border-radius: calc(var(--radius) * .6); background: none; cursor: pointer; }
5633
+ .cx-sb-menu > .cx-sb-rowtoggle { margin-top: -32px; }
5634
+ .cx-sb-rowtoggle:hover { background: var(--accent); }
5635
+ .cx-sb-rowtoggle:active { transform: scale(.94); }
5636
+ :is(.cx-sb-item, .cx-sb-subitem):has(+ .cx-sb-rowtoggle) { padding-right: 34px; }
5637
+ .cx-sb-subitem:has(+ .cx-sb-rowtoggle) { font-weight: 600; }
5638
+ .cx-sidebar[data-collapsed="true"] .cx-sb-fold { grid-template-rows: 1fr; }
5639
+ .cx-sidebar[data-collapsed="true"] .cx-sb-fold > .cx-sb-fold-in { visibility: visible; }
5640
+ .cx-sidebar[data-collapsed="true"] :is(.cx-sb-rowtoggle, .cx-sb-chev) { display: none; }
5641
+ @media (prefers-reduced-motion: reduce) { .cx-sb-fold, .cx-sb-chev { transition: none; } }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@muten/shadcn",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "shadcn-style component registry for muten - own-the-source parts you add with `muten add`.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,6 +20,14 @@
20
20
  # SidebarSubLink(label: "api", to: "/services/api", tone: "ok", busy: "{building}", hint: "Building v24")
21
21
  # SidebarSub(label: "api") { SidebarSubLink(label: "Logs", to: "/services/api?tab=logs", active: "{tab == "logs"}") { Icon "lucide:terminal" } }
22
22
  # }
23
+ # Folding parts of the menu: SidebarFoldGroup is a SidebarGroup whose title opens and closes it; SidebarFold holds what
24
+ # opens and closes under a row (a SidebarSub), and SidebarRowToggle is that row's chevron, placed right after it. They
25
+ # fold to their height in 200 ms while the chevron turns; the page owns each `open` (persist it to keep the menu as
26
+ # it was left). Folded to icons, every group shows its icons and the chevrons go.
27
+ # SidebarFoldGroup(label: "Panel", open: panelOpen, onToggle: togglePanel) { SidebarLink(…) }
28
+ # SidebarLink(label: "Services", to: "/services") { Icon "lucide:layers" }
29
+ # SidebarRowToggle(label: "Show or hide your services", open: listOpen, onToggle: toggleList)
30
+ # SidebarFold(open: listOpen) { SidebarSub { … } }
23
31
  # The name AppSidebar avoids muten's own Sidebar primitive. shadcn-for-muten · parts · no deps · Nova (.cn-sidebar-*) + kit.css.
24
32
  part AppSidebar(collapsed: bool, label: text = "Menu") {
25
33
  Nav class("cx-sidebar") data(slot: "sidebar", collapsed: $collapsed) aria(label: $label) { Stack class("cn-sidebar-inner cx-sb-inner") data(slot: "sidebar-inner") { slot } }
@@ -64,3 +72,15 @@ part SidebarSubLink(label: text, to: text, active: text = "", count: text = "",
64
72
  when $count != "" { Span "{$count}" class("cn-sidebar-menu-badge cx-sb-count") data(slot: "sidebar-menu-badge") }
65
73
  }
66
74
  }
75
+ part SidebarFoldGroup(label: text, open: bool, onToggle: action) {
76
+ Stack class("cn-sidebar-group cx-sb-group cx-sb-foldgroup") data(slot: "sidebar-group") aria(role: "group", label: $label) {
77
+ Button -> $onToggle class("cn-sidebar-group-label cx-sb-glabel cx-sb-gtoggle") data(slot: "sidebar-group-label") aria(expanded: $open) { Span "{$label}" Icon "lucide:chevron-down" class("cx-sb-chev") }
78
+ Stack class("cx-sb-fold") data(open: $open) { Stack class("cx-sb-fold-in") { Stack class("cn-sidebar-menu cx-sb-menu") data(slot: "sidebar-menu") { slot } } }
79
+ }
80
+ }
81
+ part SidebarFold(open: bool) {
82
+ Stack class("cx-sb-fold") data(open: $open) { Stack class("cx-sb-fold-in") { slot } }
83
+ }
84
+ part SidebarRowToggle(label: text, open: bool, onToggle: action) {
85
+ Button -> $onToggle class("cx-sb-rowtoggle") aria(expanded: $open, label: $label) { Icon "lucide:chevron-down" class("cx-sb-chev") }
86
+ }
package/registry.json CHANGED
@@ -936,7 +936,7 @@
936
936
  "deps": [],
937
937
  "part": "AppSidebar",
938
938
  "file": "registry/sidebar.muten",
939
- "description": "AppSidebar - a collapsible nav panel (SidebarHeader / SidebarGroup / SidebarItem / SidebarLink), with SidebarSub / SidebarSubLink for the level below an item (active, a status dot or spinning ring, a hint on hover). Named AppSidebar so it never shadows muten's core Sidebar <aside> primitive."
939
+ "description": "AppSidebar - a collapsible nav panel (SidebarHeader / SidebarGroup / SidebarItem / SidebarLink), with SidebarSub / SidebarSubLink for the level below an item (active, a status dot or spinning ring, a hint on hover), and SidebarFoldGroup / SidebarFold / SidebarRowToggle for what opens and closes. Named AppSidebar so it never shadows muten's core Sidebar <aside> primitive."
940
940
  },
941
941
  {
942
942
  "name": "site-footer",