@mhmo91/schmancy 0.9.16 → 0.9.18

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 (101) hide show
  1. package/custom-elements.json +111 -51
  2. package/dist/agent/schmancy.agent.js +288 -38
  3. package/dist/agent/schmancy.agent.js.map +1 -1
  4. package/dist/agent/schmancy.manifest.json +332 -25
  5. package/dist/breadcrumb.cjs.map +1 -1
  6. package/dist/breadcrumb.js.map +1 -1
  7. package/dist/card-BslSqOsf.cjs.map +1 -1
  8. package/dist/card-CEdgK9nb.js.map +1 -1
  9. package/dist/details-B8p62xmR.cjs.map +1 -1
  10. package/dist/details-CCW52lzz.js.map +1 -1
  11. package/dist/dialog.cjs.map +1 -1
  12. package/dist/dialog.js.map +1 -1
  13. package/dist/divider-CbEWg3G_.js.map +1 -1
  14. package/dist/divider-JyyFw_3J.cjs.map +1 -1
  15. package/dist/dropdown.cjs.map +1 -1
  16. package/dist/dropdown.js.map +1 -1
  17. package/dist/expand-BmwIPNjq.cjs.map +1 -1
  18. package/dist/expand-bFa_qVDT.js.map +1 -1
  19. package/dist/handover/agent-runtime-followups.md +1 -1
  20. package/dist/handover/agent-runtime-v1.md +3 -3
  21. package/dist/list-BpjKUOzM.js.map +1 -1
  22. package/dist/list-CMWHu6cV.cjs.map +1 -1
  23. package/dist/menu-BIBUgS1T.js.map +1 -1
  24. package/dist/menu-DS8Iz4fJ.cjs.map +1 -1
  25. package/dist/navigation-rail.cjs.map +1 -1
  26. package/dist/navigation-rail.js.map +1 -1
  27. package/dist/page.cjs.map +1 -1
  28. package/dist/page.js.map +1 -1
  29. package/dist/scroll-CdmXRXh2.js.map +1 -1
  30. package/dist/scroll-V1rAZ9fK.cjs.map +1 -1
  31. package/dist/sheet-DdlZhnDG.cjs.map +1 -1
  32. package/dist/sheet-LFVo5iN4.js.map +1 -1
  33. package/dist/src-C7niWYur.js.map +1 -1
  34. package/dist/src-I4M33WK2.cjs.map +1 -1
  35. package/dist/surface-0XM4DBaT.js.map +1 -1
  36. package/dist/surface-B6DA01kL.cjs.map +1 -1
  37. package/dist/theme-Cq_c9IO3.js.map +1 -1
  38. package/dist/theme-DU5yXaV-.cjs.map +1 -1
  39. package/dist/tree.cjs.map +1 -1
  40. package/dist/tree.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/breadcrumb/breadcrumb.ts +14 -4
  43. package/src/card/actions.ts +9 -0
  44. package/src/card/card.ts +18 -0
  45. package/src/card/content.ts +9 -0
  46. package/src/card/media.ts +6 -0
  47. package/src/details/details.ts +12 -0
  48. package/src/dialog/dialog.component.ts +9 -9
  49. package/src/divider/divider.ts +11 -0
  50. package/src/dropdown/dropdown-component.ts +13 -1
  51. package/src/dropdown/dropdown-content.ts +11 -3
  52. package/src/expand/expand-root.component.ts +12 -0
  53. package/src/expand/expand.component.ts +14 -0
  54. package/src/layout/scroll/scroll.ts +5 -1
  55. package/src/list/list-item.ts +10 -0
  56. package/src/list/list.ts +7 -8
  57. package/src/menu/menu-item.ts +13 -0
  58. package/src/menu/menu.ts +10 -22
  59. package/src/nav-drawer/appbar.ts +11 -0
  60. package/src/nav-drawer/content.ts +11 -0
  61. package/src/nav-drawer/drawer.ts +15 -0
  62. package/src/nav-drawer/navbar.ts +14 -0
  63. package/src/navigation-bar/navigation-bar-item.ts +3 -4
  64. package/src/navigation-bar/navigation-bar.ts +3 -9
  65. package/src/navigation-rail/navigation-rail-item.ts +3 -7
  66. package/src/navigation-rail/navigation-rail.ts +12 -8
  67. package/src/page/page.ts +8 -11
  68. package/src/sheet/sheet.ts +17 -0
  69. package/src/surface/surface.ts +4 -10
  70. package/src/theme/theme.component.ts +10 -15
  71. package/src/tree/tree.ts +12 -0
  72. package/types/src/breadcrumb/breadcrumb.d.ts +14 -4
  73. package/types/src/card/actions.d.ts +9 -0
  74. package/types/src/card/card.d.ts +18 -0
  75. package/types/src/card/content.d.ts +9 -0
  76. package/types/src/card/media.d.ts +6 -0
  77. package/types/src/details/details.d.ts +12 -0
  78. package/types/src/dialog/dialog.component.d.ts +9 -9
  79. package/types/src/divider/divider.d.ts +11 -0
  80. package/types/src/dropdown/dropdown-component.d.ts +13 -1
  81. package/types/src/dropdown/dropdown-content.d.ts +11 -3
  82. package/types/src/expand/expand-root.component.d.ts +12 -0
  83. package/types/src/expand/expand.component.d.ts +14 -0
  84. package/types/src/layout/scroll/scroll.d.ts +5 -1
  85. package/types/src/list/list-item.d.ts +10 -0
  86. package/types/src/list/list.d.ts +7 -8
  87. package/types/src/menu/menu-item.d.ts +13 -0
  88. package/types/src/menu/menu.d.ts +10 -22
  89. package/types/src/nav-drawer/appbar.d.ts +11 -0
  90. package/types/src/nav-drawer/content.d.ts +11 -0
  91. package/types/src/nav-drawer/drawer.d.ts +15 -0
  92. package/types/src/nav-drawer/navbar.d.ts +14 -0
  93. package/types/src/navigation-bar/navigation-bar-item.d.ts +3 -4
  94. package/types/src/navigation-bar/navigation-bar.d.ts +3 -9
  95. package/types/src/navigation-rail/navigation-rail-item.d.ts +3 -7
  96. package/types/src/navigation-rail/navigation-rail.d.ts +12 -8
  97. package/types/src/page/page.d.ts +8 -11
  98. package/types/src/sheet/sheet.d.ts +17 -0
  99. package/types/src/surface/surface.d.ts +4 -10
  100. package/types/src/theme/theme.component.d.ts +10 -15
  101. package/types/src/tree/tree.d.ts +12 -0
package/dist/tree.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tree.cjs","names":[],"sources":["../src/tree/tree.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { fromEvent, merge, switchMap, takeUntil, tap, zip } from 'rxjs'\n\n/**\n * @element schmancy-tree\n * @slot root - The root element of the tree\n * @slot - The children of the tree\n */\n@customElement('schmancy-tree')\nexport class SchmancyTree extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t\tbackground-color: initial;\n\t}\n\t::slotted([slot='root']) {\n\t\twidth: 100%;\n\t\ttext-align: left;\n\t}\n\t::slotted([slot='root'] + *) {\n\t\tmargin-top: 0.5rem;\n\t}\n`) {\n\t/**\n\t * Whether the tree’s children are visible\n\t */\n\t@property({ type: Boolean }) open = false\n\n\t@query('#toggler') toggler!: HTMLSlotElement\n\t@query('slot:not([name=\"root\"])') defaultSlot!: HTMLSlotElement\n\n\t// Since it's actually a <schmancy-button>, use HTMLElement or a custom type\n\t@query('#chevron') chevron!: HTMLElement\n\n\tprivate readonly _a11yId = `schmancy-tree-${Math.random().toString(36).slice(2, 10)}`\n\tprivate get _contentId() { return `${this._a11yId}-content` }\n\n\t/** ElementInternals — broadcasts `:state(open)` for consumer CSS. */\n\tprivate readonly _internals: ElementInternals | undefined = (() => {\n\t\ttry { return this.attachInternals() } catch { return undefined }\n\t})()\n\n\tupdated(changed: Map<string, unknown>) {\n\t\tsuper.updated?.(changed)\n\t\tif (changed.has('open')) {\n\t\t\tif (this.open) this._internals?.states.add('open')\n\t\t\telse this._internals?.states.delete('open')\n\t\t}\n\t}\n\n\tfirstUpdated() {\n\t\t// Hide or show the slot initially based on `open`\n\t\tif (!this.open) {\n\t\t\tthis.defaultSlot.hidden = true\n\t\t}\n\n\t\t// Root toggler\n\t\tconst toggleClick$ = fromEvent<MouseEvent>(this.toggler, 'click').pipe(\n\t\t\ttakeUntil(this.disconnecting),\n\t\t\ttap(e => {\n\t\t\t\te.preventDefault()\n\t\t\t\te.stopPropagation()\n\t\t\t\tthis.dispatchEvent(new CustomEvent('toggle', { bubbles: false, composed: true }))\n\t\t\t}),\n\t\t)\n\n\t\t// Chevron (the schmancy-button) click\n\t\tconst chevronClick$ = fromEvent<MouseEvent>(this.chevron, 'click')\n\n\t\tmerge(toggleClick$, chevronClick$)\n\t\t\t.pipe(\n\t\t\t\tswitchMap(() => {\n\t\t\t\t\t// 1. Animate the chevron rotation\n\t\t\t\t\t// If `open` is true, rotate from 180 -> 0; if false, from 0 -> 180\n\t\t\t\t\tconst fromDeg = this.open ? 180 : 0\n\t\t\t\t\tconst toDeg = this.open ? 0 : 180\n\t\t\t\t\tconst chevronAnimation = this.chevron.animate(\n\t\t\t\t\t\t[{ transform: `rotate(${fromDeg}deg)` }, { transform: `rotate(${toDeg}deg)` }],\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\t\teasing: 'ease-in',\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\n\t\t\t\t\t// 2. Animate the slot’s height + opacity\n\t\t\t\t\tif (!this.open) {\n\t\t\t\t\t\t// We are about to open, so remove `hidden` to measure scrollHeight\n\t\t\t\t\t\tthis.defaultSlot.hidden = false\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromOpacity = this.open ? 1 : 0\n\t\t\t\t\tconst toOpacity = this.open ? 0 : 1\n\n\t\t\t\t\tconst slotAnimation = this.defaultSlot.animate([{ opacity: fromOpacity }, { opacity: toOpacity }], {\n\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\teasing: 'ease-out',\n\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Hide the slot if we just closed it\n\t\t\t\t\tslotAnimation.onfinish = () => {\n\t\t\t\t\t\tif (this.open) {\n\t\t\t\t\t\t\tthis.defaultSlot.hidden = true\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.defaultSlot.style.height = 'auto'\n\t\t\t\t\t\t\tthis.defaultSlot.style.opacity = '1'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return an Observable that completes when both animations finish\n\t\t\t\t\treturn zip(fromEvent(chevronAnimation, 'finish'), fromEvent(slotAnimation, 'finish')).pipe(\n\t\t\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t\ttap(() => {\n\t\t\t\t\t// Flip the open state\n\t\t\t\t\tthis.open = !this.open\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<div class=\"flex content-center items-center justify-between\">\n\t\t\t\t<!-- Root toggler content -->\n\t\t\t\t<slot id=\"toggler\" name=\"root\"></slot>\n\n\t\t\t\t<!-- The chevron or arrow symbol -->\n\t\t\t\t<!-- Stop propagation on the schmancy-button itself just to avoid double triggers -->\n\t\t\t\t<schmancy-button\n\t\t\t\t\tslot=\"trailing\"\n\t\t\t\t\tid=\"chevron\"\n\t\t\t\t\taria-expanded=${this.open ? 'true' : 'false'}\n\t\t\t\t\taria-controls=${this._contentId}\n\t\t\t\t\taria-label=${this.open ? 'Collapse' : 'Expand'}\n\t\t\t\t\t@click=${(e: Event) => e.stopPropagation()}\n\t\t\t\t>\n\t\t\t\t\t⌅\n\t\t\t\t</schmancy-button>\n\t\t\t</div>\n\n\t\t\t<!-- The default slot: tree children -->\n\t\t\t<slot id=${this._contentId}></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-tree': SchmancyTree\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree.cjs","names":[],"sources":["../src/tree/tree.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { fromEvent, merge, switchMap, takeUntil, tap, zip } from 'rxjs'\n\n/**\n * Expandable tree node — a recursive disclosure widget. One root slot, one default slot for child nodes. Each node can itself contain schmancy-tree children.\n *\n * @element schmancy-tree\n * @summary Use for hierarchical navigation / file-explorer layouts. Each level is a schmancy-tree with a `root` slot (the parent label) and default slot (the children, which may be more schmancy-trees).\n * @example\n * <schmancy-tree>\n * <schmancy-list-item slot=\"root\">src/</schmancy-list-item>\n * <schmancy-tree>\n * <schmancy-list-item slot=\"root\">components/</schmancy-list-item>\n * <schmancy-list-item>button.ts</schmancy-list-item>\n * </schmancy-tree>\n * </schmancy-tree>\n * @platform details toggle - Recursive `<details>`-like disclosure. Degrades to a plain nested list if the tag never registers — loses expand/collapse but stays navigable.\n * @slot root - The root element of the tree\n * @slot - The children of the tree\n */\n@customElement('schmancy-tree')\nexport class SchmancyTree extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t\tbackground-color: initial;\n\t}\n\t::slotted([slot='root']) {\n\t\twidth: 100%;\n\t\ttext-align: left;\n\t}\n\t::slotted([slot='root'] + *) {\n\t\tmargin-top: 0.5rem;\n\t}\n`) {\n\t/**\n\t * Whether the tree’s children are visible\n\t */\n\t@property({ type: Boolean }) open = false\n\n\t@query('#toggler') toggler!: HTMLSlotElement\n\t@query('slot:not([name=\"root\"])') defaultSlot!: HTMLSlotElement\n\n\t// Since it's actually a <schmancy-button>, use HTMLElement or a custom type\n\t@query('#chevron') chevron!: HTMLElement\n\n\tprivate readonly _a11yId = `schmancy-tree-${Math.random().toString(36).slice(2, 10)}`\n\tprivate get _contentId() { return `${this._a11yId}-content` }\n\n\t/** ElementInternals — broadcasts `:state(open)` for consumer CSS. */\n\tprivate readonly _internals: ElementInternals | undefined = (() => {\n\t\ttry { return this.attachInternals() } catch { return undefined }\n\t})()\n\n\tupdated(changed: Map<string, unknown>) {\n\t\tsuper.updated?.(changed)\n\t\tif (changed.has('open')) {\n\t\t\tif (this.open) this._internals?.states.add('open')\n\t\t\telse this._internals?.states.delete('open')\n\t\t}\n\t}\n\n\tfirstUpdated() {\n\t\t// Hide or show the slot initially based on `open`\n\t\tif (!this.open) {\n\t\t\tthis.defaultSlot.hidden = true\n\t\t}\n\n\t\t// Root toggler\n\t\tconst toggleClick$ = fromEvent<MouseEvent>(this.toggler, 'click').pipe(\n\t\t\ttakeUntil(this.disconnecting),\n\t\t\ttap(e => {\n\t\t\t\te.preventDefault()\n\t\t\t\te.stopPropagation()\n\t\t\t\tthis.dispatchEvent(new CustomEvent('toggle', { bubbles: false, composed: true }))\n\t\t\t}),\n\t\t)\n\n\t\t// Chevron (the schmancy-button) click\n\t\tconst chevronClick$ = fromEvent<MouseEvent>(this.chevron, 'click')\n\n\t\tmerge(toggleClick$, chevronClick$)\n\t\t\t.pipe(\n\t\t\t\tswitchMap(() => {\n\t\t\t\t\t// 1. Animate the chevron rotation\n\t\t\t\t\t// If `open` is true, rotate from 180 -> 0; if false, from 0 -> 180\n\t\t\t\t\tconst fromDeg = this.open ? 180 : 0\n\t\t\t\t\tconst toDeg = this.open ? 0 : 180\n\t\t\t\t\tconst chevronAnimation = this.chevron.animate(\n\t\t\t\t\t\t[{ transform: `rotate(${fromDeg}deg)` }, { transform: `rotate(${toDeg}deg)` }],\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\t\teasing: 'ease-in',\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\n\t\t\t\t\t// 2. Animate the slot’s height + opacity\n\t\t\t\t\tif (!this.open) {\n\t\t\t\t\t\t// We are about to open, so remove `hidden` to measure scrollHeight\n\t\t\t\t\t\tthis.defaultSlot.hidden = false\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromOpacity = this.open ? 1 : 0\n\t\t\t\t\tconst toOpacity = this.open ? 0 : 1\n\n\t\t\t\t\tconst slotAnimation = this.defaultSlot.animate([{ opacity: fromOpacity }, { opacity: toOpacity }], {\n\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\teasing: 'ease-out',\n\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Hide the slot if we just closed it\n\t\t\t\t\tslotAnimation.onfinish = () => {\n\t\t\t\t\t\tif (this.open) {\n\t\t\t\t\t\t\tthis.defaultSlot.hidden = true\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.defaultSlot.style.height = 'auto'\n\t\t\t\t\t\t\tthis.defaultSlot.style.opacity = '1'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return an Observable that completes when both animations finish\n\t\t\t\t\treturn zip(fromEvent(chevronAnimation, 'finish'), fromEvent(slotAnimation, 'finish')).pipe(\n\t\t\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t\ttap(() => {\n\t\t\t\t\t// Flip the open state\n\t\t\t\t\tthis.open = !this.open\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<div class=\"flex content-center items-center justify-between\">\n\t\t\t\t<!-- Root toggler content -->\n\t\t\t\t<slot id=\"toggler\" name=\"root\"></slot>\n\n\t\t\t\t<!-- The chevron or arrow symbol -->\n\t\t\t\t<!-- Stop propagation on the schmancy-button itself just to avoid double triggers -->\n\t\t\t\t<schmancy-button\n\t\t\t\t\tslot=\"trailing\"\n\t\t\t\t\tid=\"chevron\"\n\t\t\t\t\taria-expanded=${this.open ? 'true' : 'false'}\n\t\t\t\t\taria-controls=${this._contentId}\n\t\t\t\t\taria-label=${this.open ? 'Collapse' : 'Expand'}\n\t\t\t\t\t@click=${(e: Event) => e.stopPropagation()}\n\t\t\t\t>\n\t\t\t\t\t⌅\n\t\t\t\t</schmancy-button>\n\t\t\t</div>\n\n\t\t\t<!-- The default slot: tree children -->\n\t\t\t<slot id=${this._contentId}></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-tree': SchmancyTree\n\t}\n}\n"],"mappings":"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"}
package/dist/tree.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tree.js","names":[],"sources":["../src/tree/tree.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { fromEvent, merge, switchMap, takeUntil, tap, zip } from 'rxjs'\n\n/**\n * @element schmancy-tree\n * @slot root - The root element of the tree\n * @slot - The children of the tree\n */\n@customElement('schmancy-tree')\nexport class SchmancyTree extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t\tbackground-color: initial;\n\t}\n\t::slotted([slot='root']) {\n\t\twidth: 100%;\n\t\ttext-align: left;\n\t}\n\t::slotted([slot='root'] + *) {\n\t\tmargin-top: 0.5rem;\n\t}\n`) {\n\t/**\n\t * Whether the tree’s children are visible\n\t */\n\t@property({ type: Boolean }) open = false\n\n\t@query('#toggler') toggler!: HTMLSlotElement\n\t@query('slot:not([name=\"root\"])') defaultSlot!: HTMLSlotElement\n\n\t// Since it's actually a <schmancy-button>, use HTMLElement or a custom type\n\t@query('#chevron') chevron!: HTMLElement\n\n\tprivate readonly _a11yId = `schmancy-tree-${Math.random().toString(36).slice(2, 10)}`\n\tprivate get _contentId() { return `${this._a11yId}-content` }\n\n\t/** ElementInternals — broadcasts `:state(open)` for consumer CSS. */\n\tprivate readonly _internals: ElementInternals | undefined = (() => {\n\t\ttry { return this.attachInternals() } catch { return undefined }\n\t})()\n\n\tupdated(changed: Map<string, unknown>) {\n\t\tsuper.updated?.(changed)\n\t\tif (changed.has('open')) {\n\t\t\tif (this.open) this._internals?.states.add('open')\n\t\t\telse this._internals?.states.delete('open')\n\t\t}\n\t}\n\n\tfirstUpdated() {\n\t\t// Hide or show the slot initially based on `open`\n\t\tif (!this.open) {\n\t\t\tthis.defaultSlot.hidden = true\n\t\t}\n\n\t\t// Root toggler\n\t\tconst toggleClick$ = fromEvent<MouseEvent>(this.toggler, 'click').pipe(\n\t\t\ttakeUntil(this.disconnecting),\n\t\t\ttap(e => {\n\t\t\t\te.preventDefault()\n\t\t\t\te.stopPropagation()\n\t\t\t\tthis.dispatchEvent(new CustomEvent('toggle', { bubbles: false, composed: true }))\n\t\t\t}),\n\t\t)\n\n\t\t// Chevron (the schmancy-button) click\n\t\tconst chevronClick$ = fromEvent<MouseEvent>(this.chevron, 'click')\n\n\t\tmerge(toggleClick$, chevronClick$)\n\t\t\t.pipe(\n\t\t\t\tswitchMap(() => {\n\t\t\t\t\t// 1. Animate the chevron rotation\n\t\t\t\t\t// If `open` is true, rotate from 180 -> 0; if false, from 0 -> 180\n\t\t\t\t\tconst fromDeg = this.open ? 180 : 0\n\t\t\t\t\tconst toDeg = this.open ? 0 : 180\n\t\t\t\t\tconst chevronAnimation = this.chevron.animate(\n\t\t\t\t\t\t[{ transform: `rotate(${fromDeg}deg)` }, { transform: `rotate(${toDeg}deg)` }],\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\t\teasing: 'ease-in',\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\n\t\t\t\t\t// 2. Animate the slot’s height + opacity\n\t\t\t\t\tif (!this.open) {\n\t\t\t\t\t\t// We are about to open, so remove `hidden` to measure scrollHeight\n\t\t\t\t\t\tthis.defaultSlot.hidden = false\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromOpacity = this.open ? 1 : 0\n\t\t\t\t\tconst toOpacity = this.open ? 0 : 1\n\n\t\t\t\t\tconst slotAnimation = this.defaultSlot.animate([{ opacity: fromOpacity }, { opacity: toOpacity }], {\n\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\teasing: 'ease-out',\n\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Hide the slot if we just closed it\n\t\t\t\t\tslotAnimation.onfinish = () => {\n\t\t\t\t\t\tif (this.open) {\n\t\t\t\t\t\t\tthis.defaultSlot.hidden = true\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.defaultSlot.style.height = 'auto'\n\t\t\t\t\t\t\tthis.defaultSlot.style.opacity = '1'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return an Observable that completes when both animations finish\n\t\t\t\t\treturn zip(fromEvent(chevronAnimation, 'finish'), fromEvent(slotAnimation, 'finish')).pipe(\n\t\t\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t\ttap(() => {\n\t\t\t\t\t// Flip the open state\n\t\t\t\t\tthis.open = !this.open\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<div class=\"flex content-center items-center justify-between\">\n\t\t\t\t<!-- Root toggler content -->\n\t\t\t\t<slot id=\"toggler\" name=\"root\"></slot>\n\n\t\t\t\t<!-- The chevron or arrow symbol -->\n\t\t\t\t<!-- Stop propagation on the schmancy-button itself just to avoid double triggers -->\n\t\t\t\t<schmancy-button\n\t\t\t\t\tslot=\"trailing\"\n\t\t\t\t\tid=\"chevron\"\n\t\t\t\t\taria-expanded=${this.open ? 'true' : 'false'}\n\t\t\t\t\taria-controls=${this._contentId}\n\t\t\t\t\taria-label=${this.open ? 'Collapse' : 'Expand'}\n\t\t\t\t\t@click=${(e: Event) => e.stopPropagation()}\n\t\t\t\t>\n\t\t\t\t\t⌅\n\t\t\t\t</schmancy-button>\n\t\t\t</div>\n\n\t\t\t<!-- The default slot: tree children -->\n\t\t\t<slot id=${this._contentId}></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-tree': SchmancyTree\n\t}\n}\n"],"mappings":";;;;;;AAWO,IAAA,IAAA,cAA2B,EAAgB,CAAG;;;;;;;;;;;;;;;4BAiBhB,GAAA,KAAA,UAQT,iBAAiB,KAAK,QAAA,CAAS,SAAS,GAAA,CAAI,MAAM,GAAG,GAAA,IAAA,KAAA,oBAAA;AAK/E,OAAA;AAAM,WAAO,KAAK,iBAAA;WAAA;AAA4B;;MAAA;;CAJ/C,IAAA,aAAY;AAAe,SAAO,GAAG,KAAK,QAAA;;CAO1C,QAAQ,GAAA;AACP,QAAM,UAAU,EAAA,EACZ,EAAQ,IAAI,OAAA,KACX,KAAK,OAAM,KAAK,YAAY,OAAO,IAAI,OAAA,GACtC,KAAK,YAAY,OAAO,OAAO,OAAA;;CAItC,eAAA;AAEM,OAAK,SACT,KAAK,YAAY,SAAA,CAAS,IAgB3B,EAZqB,EAAsB,KAAK,SAAS,QAAA,CAAS,KACjE,EAAU,KAAK,cAAA,EACf,GAAI,MAAA;AACH,KAAE,gBAAA,EACF,EAAE,iBAAA,EACF,KAAK,cAAc,IAAI,YAAY,UAAU;IAAE,SAAA,CAAS;IAAO,UAAA,CAAU;IAAA,CAAA,CAAA;IAAA,CAAA,EAKrD,EAAsB,KAAK,SAAS,QAAA,CAAA,CAGxD,KACA,QAAA;GAGC,IAAM,IAAU,KAAK,OAAO,MAAM,GAC5B,IAAQ,KAAK,OAAO,IAAI,KACxB,IAAmB,KAAK,QAAQ,QACrC,CAAC,EAAE,WAAW,UAAU,EAAA,OAAA,EAAiB,EAAE,WAAW,UAAU,EAAA,OAAA,CAAA,EAChE;IACC,UAAU;IACV,QAAQ;IACR,MAAM;IAAA,CAAA;AAKH,QAAK,SAET,KAAK,YAAY,SAAA,CAAS;GAG3B,IAAM,IAAc,QAAK,MACnB,IAAY,OAAK,MAEjB,IAAgB,KAAK,YAAY,QAAQ,CAAC,EAAE,SAAS,GAAA,EAAe,EAAE,SAAS,GAAA,CAAA,EAAc;IAClG,UAAU;IACV,QAAQ;IACR,MAAM;IAAA,CAAA;AAcP,UAVA,EAAc,iBAAA;AACT,SAAK,OACR,KAAK,YAAY,SAAA,CAAS,KAE1B,KAAK,YAAY,MAAM,SAAS,QAChC,KAAK,YAAY,MAAM,UAAU;MAK5B,EAAI,EAAU,GAAkB,SAAA,EAAW,EAAU,GAAe,SAAA,CAAA,CAAW,KACrF,EAAU,KAAK,cAAA,CAAA;IAAA,EAGjB,QAAA;AAEC,QAAK,OAAA,CAAQ,KAAK;IAAA,EAEnB,EAAU,KAAK,cAAA,CAAA,CAEf,WAAA;;CAGH,SAAA;AACC,SAAO,CAAI;;;;;;;;;;qBAUQ,KAAK,OAAO,SAAS,QAAA;qBACrB,KAAK,WAAA;kBACR,KAAK,OAAO,aAAa,SAAA;eAC5B,MAAa,EAAE,iBAAA,CAAA;;;;;;;cAOhB,KAAK,WAAA;;;;GAvHjB,EAAS,EAAE,MAAM,SAAA,CAAA,CAAA,EAAU,EAAA,WAAA,QAAA,KAAA,EAAA,EAAA,EAAA,CAE3B,EAAM,WAAA,CAAA,EAAW,EAAA,WAAA,WAAA,KAAA,EAAA,EAAA,EAAA,CACjB,EAAM,4BAAA,CAAA,EAA0B,EAAA,WAAA,eAAA,KAAA,EAAA,EAAA,EAAA,CAGhC,EAAM,WAAA,CAAA,EAAW,EAAA,WAAA,WAAA,KAAA,EAAA,EAAA,IAAA,EAAA,CAxBlB,EAAc,gBAAA,CAAA,EAAgB,EAAA;AAAA,SAAA,KAAA"}
1
+ {"version":3,"file":"tree.js","names":[],"sources":["../src/tree/tree.ts"],"sourcesContent":["import { TailwindElement } from '@mixins/index'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { fromEvent, merge, switchMap, takeUntil, tap, zip } from 'rxjs'\n\n/**\n * Expandable tree node — a recursive disclosure widget. One root slot, one default slot for child nodes. Each node can itself contain schmancy-tree children.\n *\n * @element schmancy-tree\n * @summary Use for hierarchical navigation / file-explorer layouts. Each level is a schmancy-tree with a `root` slot (the parent label) and default slot (the children, which may be more schmancy-trees).\n * @example\n * <schmancy-tree>\n * <schmancy-list-item slot=\"root\">src/</schmancy-list-item>\n * <schmancy-tree>\n * <schmancy-list-item slot=\"root\">components/</schmancy-list-item>\n * <schmancy-list-item>button.ts</schmancy-list-item>\n * </schmancy-tree>\n * </schmancy-tree>\n * @platform details toggle - Recursive `<details>`-like disclosure. Degrades to a plain nested list if the tag never registers — loses expand/collapse but stays navigable.\n * @slot root - The root element of the tree\n * @slot - The children of the tree\n */\n@customElement('schmancy-tree')\nexport class SchmancyTree extends TailwindElement(css`\n\t:host {\n\t\tdisplay: block;\n\t\tposition: relative;\n\t\tbackground-color: initial;\n\t}\n\t::slotted([slot='root']) {\n\t\twidth: 100%;\n\t\ttext-align: left;\n\t}\n\t::slotted([slot='root'] + *) {\n\t\tmargin-top: 0.5rem;\n\t}\n`) {\n\t/**\n\t * Whether the tree’s children are visible\n\t */\n\t@property({ type: Boolean }) open = false\n\n\t@query('#toggler') toggler!: HTMLSlotElement\n\t@query('slot:not([name=\"root\"])') defaultSlot!: HTMLSlotElement\n\n\t// Since it's actually a <schmancy-button>, use HTMLElement or a custom type\n\t@query('#chevron') chevron!: HTMLElement\n\n\tprivate readonly _a11yId = `schmancy-tree-${Math.random().toString(36).slice(2, 10)}`\n\tprivate get _contentId() { return `${this._a11yId}-content` }\n\n\t/** ElementInternals — broadcasts `:state(open)` for consumer CSS. */\n\tprivate readonly _internals: ElementInternals | undefined = (() => {\n\t\ttry { return this.attachInternals() } catch { return undefined }\n\t})()\n\n\tupdated(changed: Map<string, unknown>) {\n\t\tsuper.updated?.(changed)\n\t\tif (changed.has('open')) {\n\t\t\tif (this.open) this._internals?.states.add('open')\n\t\t\telse this._internals?.states.delete('open')\n\t\t}\n\t}\n\n\tfirstUpdated() {\n\t\t// Hide or show the slot initially based on `open`\n\t\tif (!this.open) {\n\t\t\tthis.defaultSlot.hidden = true\n\t\t}\n\n\t\t// Root toggler\n\t\tconst toggleClick$ = fromEvent<MouseEvent>(this.toggler, 'click').pipe(\n\t\t\ttakeUntil(this.disconnecting),\n\t\t\ttap(e => {\n\t\t\t\te.preventDefault()\n\t\t\t\te.stopPropagation()\n\t\t\t\tthis.dispatchEvent(new CustomEvent('toggle', { bubbles: false, composed: true }))\n\t\t\t}),\n\t\t)\n\n\t\t// Chevron (the schmancy-button) click\n\t\tconst chevronClick$ = fromEvent<MouseEvent>(this.chevron, 'click')\n\n\t\tmerge(toggleClick$, chevronClick$)\n\t\t\t.pipe(\n\t\t\t\tswitchMap(() => {\n\t\t\t\t\t// 1. Animate the chevron rotation\n\t\t\t\t\t// If `open` is true, rotate from 180 -> 0; if false, from 0 -> 180\n\t\t\t\t\tconst fromDeg = this.open ? 180 : 0\n\t\t\t\t\tconst toDeg = this.open ? 0 : 180\n\t\t\t\t\tconst chevronAnimation = this.chevron.animate(\n\t\t\t\t\t\t[{ transform: `rotate(${fromDeg}deg)` }, { transform: `rotate(${toDeg}deg)` }],\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\t\teasing: 'ease-in',\n\t\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\n\t\t\t\t\t// 2. Animate the slot’s height + opacity\n\t\t\t\t\tif (!this.open) {\n\t\t\t\t\t\t// We are about to open, so remove `hidden` to measure scrollHeight\n\t\t\t\t\t\tthis.defaultSlot.hidden = false\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fromOpacity = this.open ? 1 : 0\n\t\t\t\t\tconst toOpacity = this.open ? 0 : 1\n\n\t\t\t\t\tconst slotAnimation = this.defaultSlot.animate([{ opacity: fromOpacity }, { opacity: toOpacity }], {\n\t\t\t\t\t\tduration: 150,\n\t\t\t\t\t\teasing: 'ease-out',\n\t\t\t\t\t\tfill: 'forwards',\n\t\t\t\t\t})\n\n\t\t\t\t\t// Hide the slot if we just closed it\n\t\t\t\t\tslotAnimation.onfinish = () => {\n\t\t\t\t\t\tif (this.open) {\n\t\t\t\t\t\t\tthis.defaultSlot.hidden = true\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.defaultSlot.style.height = 'auto'\n\t\t\t\t\t\t\tthis.defaultSlot.style.opacity = '1'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return an Observable that completes when both animations finish\n\t\t\t\t\treturn zip(fromEvent(chevronAnimation, 'finish'), fromEvent(slotAnimation, 'finish')).pipe(\n\t\t\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t\ttap(() => {\n\t\t\t\t\t// Flip the open state\n\t\t\t\t\tthis.open = !this.open\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\t<div class=\"flex content-center items-center justify-between\">\n\t\t\t\t<!-- Root toggler content -->\n\t\t\t\t<slot id=\"toggler\" name=\"root\"></slot>\n\n\t\t\t\t<!-- The chevron or arrow symbol -->\n\t\t\t\t<!-- Stop propagation on the schmancy-button itself just to avoid double triggers -->\n\t\t\t\t<schmancy-button\n\t\t\t\t\tslot=\"trailing\"\n\t\t\t\t\tid=\"chevron\"\n\t\t\t\t\taria-expanded=${this.open ? 'true' : 'false'}\n\t\t\t\t\taria-controls=${this._contentId}\n\t\t\t\t\taria-label=${this.open ? 'Collapse' : 'Expand'}\n\t\t\t\t\t@click=${(e: Event) => e.stopPropagation()}\n\t\t\t\t>\n\t\t\t\t\t⌅\n\t\t\t\t</schmancy-button>\n\t\t\t</div>\n\n\t\t\t<!-- The default slot: tree children -->\n\t\t\t<slot id=${this._contentId}></slot>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-tree': SchmancyTree\n\t}\n}\n"],"mappings":";;;;;;AAuBO,IAAA,IAAA,cAA2B,EAAgB,CAAG;;;;;;;;;;;;;;;4BAiBhB,GAAA,KAAA,UAQT,iBAAiB,KAAK,QAAA,CAAS,SAAS,GAAA,CAAI,MAAM,GAAG,GAAA,IAAA,KAAA,oBAAA;AAK/E,OAAA;AAAM,WAAO,KAAK,iBAAA;WAAA;AAA4B;;MAAA;;CAJ/C,IAAA,aAAY;AAAe,SAAO,GAAG,KAAK,QAAA;;CAO1C,QAAQ,GAAA;AACP,QAAM,UAAU,EAAA,EACZ,EAAQ,IAAI,OAAA,KACX,KAAK,OAAM,KAAK,YAAY,OAAO,IAAI,OAAA,GACtC,KAAK,YAAY,OAAO,OAAO,OAAA;;CAItC,eAAA;AAEM,OAAK,SACT,KAAK,YAAY,SAAA,CAAS,IAgB3B,EAZqB,EAAsB,KAAK,SAAS,QAAA,CAAS,KACjE,EAAU,KAAK,cAAA,EACf,GAAI,MAAA;AACH,KAAE,gBAAA,EACF,EAAE,iBAAA,EACF,KAAK,cAAc,IAAI,YAAY,UAAU;IAAE,SAAA,CAAS;IAAO,UAAA,CAAU;IAAA,CAAA,CAAA;IAAA,CAAA,EAKrD,EAAsB,KAAK,SAAS,QAAA,CAAA,CAGxD,KACA,QAAA;GAGC,IAAM,IAAU,KAAK,OAAO,MAAM,GAC5B,IAAQ,KAAK,OAAO,IAAI,KACxB,IAAmB,KAAK,QAAQ,QACrC,CAAC,EAAE,WAAW,UAAU,EAAA,OAAA,EAAiB,EAAE,WAAW,UAAU,EAAA,OAAA,CAAA,EAChE;IACC,UAAU;IACV,QAAQ;IACR,MAAM;IAAA,CAAA;AAKH,QAAK,SAET,KAAK,YAAY,SAAA,CAAS;GAG3B,IAAM,IAAc,QAAK,MACnB,IAAY,OAAK,MAEjB,IAAgB,KAAK,YAAY,QAAQ,CAAC,EAAE,SAAS,GAAA,EAAe,EAAE,SAAS,GAAA,CAAA,EAAc;IAClG,UAAU;IACV,QAAQ;IACR,MAAM;IAAA,CAAA;AAcP,UAVA,EAAc,iBAAA;AACT,SAAK,OACR,KAAK,YAAY,SAAA,CAAS,KAE1B,KAAK,YAAY,MAAM,SAAS,QAChC,KAAK,YAAY,MAAM,UAAU;MAK5B,EAAI,EAAU,GAAkB,SAAA,EAAW,EAAU,GAAe,SAAA,CAAA,CAAW,KACrF,EAAU,KAAK,cAAA,CAAA;IAAA,EAGjB,QAAA;AAEC,QAAK,OAAA,CAAQ,KAAK;IAAA,EAEnB,EAAU,KAAK,cAAA,CAAA,CAEf,WAAA;;CAGH,SAAA;AACC,SAAO,CAAI;;;;;;;;;;qBAUQ,KAAK,OAAO,SAAS,QAAA;qBACrB,KAAK,WAAA;kBACR,KAAK,OAAO,aAAa,SAAA;eAC5B,MAAa,EAAE,iBAAA,CAAA;;;;;;;cAOhB,KAAK,WAAA;;;;GAvHjB,EAAS,EAAE,MAAM,SAAA,CAAA,CAAA,EAAU,EAAA,WAAA,QAAA,KAAA,EAAA,EAAA,EAAA,CAE3B,EAAM,WAAA,CAAA,EAAW,EAAA,WAAA,WAAA,KAAA,EAAA,EAAA,EAAA,CACjB,EAAM,4BAAA,CAAA,EAA0B,EAAA,WAAA,eAAA,KAAA,EAAA,EAAA,EAAA,CAGhC,EAAM,WAAA,CAAA,EAAW,EAAA,WAAA,WAAA,KAAA,EAAA,EAAA,IAAA,EAAA,CAxBlB,EAAc,gBAAA,CAAA,EAAgB,EAAA;AAAA,SAAA,KAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhmo91/schmancy",
3
- "version": "0.9.16",
3
+ "version": "0.9.18",
4
4
  "description": "UI library build with web components",
5
5
  "main": "./dist/index.js",
6
6
  "customElements": "custom-elements.json",
@@ -3,10 +3,17 @@ import { css, html } from 'lit'
3
3
  import { customElement, property } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
- * Breadcrumb navigation container. Wraps a list of `schmancy-breadcrumb-item`
7
- * elements with the correct ARIA landmark and semantics.
6
+ * Breadcrumb trail — navigation history from root to current page. Renders schmancy-breadcrumb-item children with separators between.
8
7
  *
9
8
  * @element schmancy-breadcrumb
9
+ * @summary Use for deep hierarchical navigation (file explorer paths, e-commerce category chains, admin settings trees). Last item is styled as the current page automatically.
10
+ * @example
11
+ * <schmancy-breadcrumb separator="›">
12
+ * <schmancy-breadcrumb-item href="/">Home</schmancy-breadcrumb-item>
13
+ * <schmancy-breadcrumb-item href="/docs">Docs</schmancy-breadcrumb-item>
14
+ * <schmancy-breadcrumb-item>Getting started</schmancy-breadcrumb-item>
15
+ * </schmancy-breadcrumb>
16
+ * @platform nav - Styled `<nav aria-label="Breadcrumb">`. Degrades to a plain nav if the tag never registers.
10
17
  * @slot - Default slot for `<schmancy-breadcrumb-item>` children.
11
18
  * @attr separator - Character or string rendered between items. Default `/`.
12
19
  * @csspart separator - The separator element.
@@ -69,10 +76,13 @@ export class SchmancyBreadcrumb extends TailwindElement(css`
69
76
  }
70
77
 
71
78
  /**
72
- * Individual breadcrumb item. Renders as a link when `href` is provided,
73
- * otherwise as a plain span (represents the current page).
79
+ * Single segment in a schmancy-breadcrumb trail a link when `href` is set, or a plain span (the current page) when omitted.
74
80
  *
75
81
  * @element schmancy-breadcrumb-item
82
+ * @summary Always nested inside schmancy-breadcrumb. Omit `href` on the current page — it gets aria-current="page" automatically.
83
+ * @example
84
+ * <schmancy-breadcrumb-item href="/products">Products</schmancy-breadcrumb-item>
85
+ * @platform a - Renders an `<a>` or `<span>` depending on href. Degrades to a plain anchor/span if the tag never registers.
76
86
  * @slot - Label content.
77
87
  * @attr href - If set, renders as an anchor.
78
88
  * @attr current - Marks as `aria-current="page"`.
@@ -3,7 +3,16 @@ import { css, html } from 'lit'
3
3
  import { customElement } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
+ * Action row of a schmancy-card — holds the card's buttons / links (typically aligned bottom-right).
7
+ *
6
8
  * @element schmancy-card-action
9
+ * @summary Always nested inside schmancy-card. Holds the primary + secondary CTAs for the card.
10
+ * @example
11
+ * <schmancy-card-action>
12
+ * <schmancy-button variant="text">Cancel</schmancy-button>
13
+ * <schmancy-button variant="filled">Save</schmancy-button>
14
+ * </schmancy-card-action>
15
+ * @platform div - Styled flex container. Degrades to a plain div if the tag never registers.
7
16
  * @slot - The content of the action
8
17
  */
9
18
  @customElement('schmancy-card-action')
package/src/card/card.ts CHANGED
@@ -4,6 +4,24 @@ import { customElement, property, state } from 'lit/decorators.js'
4
4
  import { cursorGlow } from '../directives/cursor-glow'
5
5
  import { ifDefined } from 'lit/directives/if-defined.js'
6
6
 
7
+ /**
8
+ * Material Design card — a surface-level container for grouping related content with media / content / actions slots.
9
+ *
10
+ * @element schmancy-card
11
+ * @summary Use for discrete pieces of content that appear in a list (a product, a note, a message). Combine with schmancy-card-media / schmancy-card-content / schmancy-card-action children.
12
+ * @example
13
+ * <schmancy-card type="elevated" href="/items/42">
14
+ * <schmancy-card-media src="/thumb.jpg" alt="Thumbnail"></schmancy-card-media>
15
+ * <schmancy-card-content>
16
+ * <h3>Title</h3>
17
+ * <p>One-line description of the card's content.</p>
18
+ * </schmancy-card-content>
19
+ * <schmancy-card-action>
20
+ * <schmancy-button variant="text">Open</schmancy-button>
21
+ * </schmancy-card-action>
22
+ * </schmancy-card>
23
+ * @platform div - Styled `<div>`; becomes an `<a>` when `href` is set so the whole card is a single interactive surface. Degrades to a plain div/a if the tag never registers.
24
+ */
7
25
  @customElement('schmancy-card')
8
26
  export default class SchmancyCard extends TailwindElement(css`
9
27
  :host {
@@ -3,7 +3,16 @@ import { css, html } from 'lit'
3
3
  import { customElement } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
+ * Content region of a schmancy-card — holds the card's headline, supporting text, and inline controls.
7
+ *
6
8
  * @element schmancy-card-content
9
+ * @summary Always nested inside schmancy-card. The padded content block between the media and action rows.
10
+ * @example
11
+ * <schmancy-card-content>
12
+ * <h3>Card title</h3>
13
+ * <p>Supporting text that describes the card's subject.</p>
14
+ * </schmancy-card-content>
15
+ * @platform div - Styled `<div>` with padding. Degrades to a plain div if the tag never registers.
7
16
  */
8
17
  @customElement('schmancy-card-content')
9
18
  export default class SchmancyCardContent extends TailwindElement(css`
package/src/card/media.ts CHANGED
@@ -3,7 +3,13 @@ import { css, html } from 'lit'
3
3
  import { customElement, property } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
+ * Media region of a schmancy-card — the image / thumbnail at the top of the card.
7
+ *
6
8
  * @element schmancy-card-media
9
+ * @summary Always nested inside schmancy-card. Pass `src` + `alt` props or slot an `<img>` / `<video>` for custom media.
10
+ * @example
11
+ * <schmancy-card-media src="/thumb.jpg" alt="Product photo"></schmancy-card-media>
12
+ * @platform img - Renders an `<img>` (or wraps a slotted media element). Degrades to a styled `<img>` if the tag never registers.
7
13
  */
8
14
  @customElement('schmancy-card-media')
9
15
  export default class SchmancyCardMedia extends TailwindElement(css`
@@ -9,6 +9,18 @@ import { distinctUntilChanged, filter, take, takeUntil, tap } from 'rxjs/operato
9
9
  import { SPRING_SNAPPY } from '../utils/animation.js'
10
10
  import { reducedMotion$ } from '../directives/reduced-motion'
11
11
 
12
+ /**
13
+ * Expandable disclosure panel — a styled `<details>` / `<summary>` pair with animated expand + overlay options.
14
+ *
15
+ * @element schmancy-details
16
+ * @summary Use for progressive-disclosure content: FAQs, collapsible settings sections, accordion-style lists. Prefer schmancy-expand for full-page accordions where only one section can be open at a time.
17
+ * @example
18
+ * <schmancy-details summary="Shipping details">
19
+ * <p>Order ships in 2 business days.</p>
20
+ * </schmancy-details>
21
+ * @platform details toggle - Wraps native `<details>`/`<summary>`. Degrades to the native element if the tag never registers — same keyboard accessibility, just no animation.
22
+ * @fires toggle - When the open state changes (bubbles from the native `<details>`).
23
+ */
12
24
  @customElement('schmancy-details')
13
25
  export default class SchmancyDetails extends SurfaceMixin(
14
26
  TailwindElement(css`
@@ -10,28 +10,28 @@ import { DialogBase } from './dialog-base.mixin'
10
10
  import { DialogHereMorty, DialogWhereAreYouRicky, DialogWhereAreYouRickyEvent } from './dialog-events'
11
11
 
12
12
  /**
13
- * Unified dialog component that handles both content-only and confirm modes.
13
+ * Modal dialog content-only (just a styled panel) or confirm mode (title + message + confirm/cancel buttons). Prefer the imperative `$dialog` service for most use cases; use the element directly only when you want a declaratively-positioned dialog.
14
14
  *
15
15
  * @element schmancy-dialog
16
+ * @summary Blocks interaction with the rest of the page until dismissed. For quick confirmations, prefer `$dialog.confirm({ ... })` over this element. For arbitrary dialog content driven imperatively, prefer `$dialog.component(MyComponent)`.
17
+ * @platform dialog close - Positioned overlay in light DOM. Degrades to a styled `<dialog>` if the tag never registers — loses custom animations but keeps focus trap + ESC close.
16
18
  * @slot default - Content slot for dialog body (used in content mode)
17
19
  * @slot content - Named slot for custom content in confirm mode
20
+ * @fires confirm - In confirm mode, when the confirm button is clicked.
21
+ * @fires cancel - In confirm mode, when the cancel button or ESC is activated.
18
22
  *
19
23
  * @example Content mode (no buttons):
20
- * ```html
21
24
  * <schmancy-dialog>
22
25
  * <my-custom-content></my-custom-content>
23
26
  * </schmancy-dialog>
24
- * ```
25
27
  *
26
28
  * @example Confirm mode (with buttons):
27
- * ```html
28
29
  * <schmancy-dialog
29
- * title="Confirm Action"
30
- * message="Are you sure?"
31
- * confirm-text="Yes"
32
- * cancel-text="No"
30
+ * title="Delete item?"
31
+ * message="This action cannot be undone."
32
+ * confirm-text="Delete"
33
+ * cancel-text="Keep"
33
34
  * ></schmancy-dialog>
34
- * ```
35
35
  */
36
36
  @customElement('schmancy-dialog')
37
37
  export class SchmancyDialog extends DialogBase(
@@ -3,6 +3,17 @@ import { $LitElement } from '@mixins/index'
3
3
  import { css, html } from 'lit'
4
4
  import { customElement, property } from 'lit/decorators.js'
5
5
 
6
+ /**
7
+ * Thin horizontal (or vertical) separator rule between sections of content.
8
+ *
9
+ * @element schmancy-divider
10
+ * @summary Semantic separator between groups — list items, menu sections, content blocks. Uses outline theme token.
11
+ * @example
12
+ * <schmancy-list-item>First</schmancy-list-item>
13
+ * <schmancy-divider></schmancy-divider>
14
+ * <schmancy-list-item>Second</schmancy-list-item>
15
+ * @platform hr - Styled horizontal rule. Degrades to a native `<hr>` if the tag never registers.
16
+ */
6
17
  @customElement('schmancy-divider')
7
18
  export default class SchmancyDivider extends $LitElement(css`
8
19
  :host {
@@ -5,9 +5,21 @@ import { customElement, property, query, queryAssignedElements, state } from 'li
5
5
  import { filter, fromEvent, takeUntil, Subscription } from 'rxjs'
6
6
 
7
7
  /**
8
- * A dropdown component that displays content when triggered.
8
+ * Anchored floating dropdown a generic "show this content relative to that trigger" primitive. Unlike schmancy-menu (which uses the dialog service and is list-shaped), dropdown is a low-level popover anchored with Floating UI. Use when you want a custom-shaped overlay tied to a specific trigger element without the menu semantics.
9
9
  *
10
10
  * @element schmancy-dropdown
11
+ * @summary Prefer schmancy-menu for action lists, schmancy-autocomplete for type-ahead, schmancy-tooltip for hover hints. Reach for schmancy-dropdown when none of those fit — custom filters, color pickers, inline forms anchored to a trigger.
12
+ * @example
13
+ * <schmancy-dropdown>
14
+ * <schmancy-button slot="trigger">Filters</schmancy-button>
15
+ * <schmancy-dropdown-content>
16
+ * <schmancy-form>…</schmancy-form>
17
+ * </schmancy-dropdown-content>
18
+ * </schmancy-dropdown>
19
+ * @platform div - Anchored via Floating UI (autoUpdate, flip, shift). Degrades to inline content if the tag never registers — loses positioning but content stays accessible.
20
+ * @attr open - Boolean; whether the dropdown is visible.
21
+ * @fires open - When the dropdown opens.
22
+ * @fires close - When the dropdown closes.
11
23
  * @slot trigger - The element that triggers the dropdown
12
24
  * @slot - Default slot for the dropdown content
13
25
  */
@@ -3,12 +3,20 @@ import { css, html } from 'lit'
3
3
  import { customElement, property } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
- * Content container for the schmancy-dropdown component.
6
+ * Content panel for a schmancy-dropdown — a styled positioned surface. Always nested inside schmancy-dropdown and placed alongside the trigger slot.
7
7
  *
8
8
  * @element schmancy-dropdown-content
9
+ * @summary Nest this inside schmancy-dropdown (not in the trigger slot). Use the `content` CSS part to customize backgrounds / shadows / padding without shadow-root piercing.
10
+ * @example
11
+ * <schmancy-dropdown>
12
+ * <schmancy-button slot="trigger">Open</schmancy-button>
13
+ * <schmancy-dropdown-content>
14
+ * Panel contents…
15
+ * </schmancy-dropdown-content>
16
+ * </schmancy-dropdown>
17
+ * @platform div - Positioned panel with theme-aware styling. Degrades to an inline div if the tag never registers.
9
18
  * @slot - Default slot for dropdown content.
10
- * @csspart content - The inner wrapper element; style to override panel
11
- * backgrounds, shadows, padding, or borders without shadow-root piercing.
19
+ * @csspart content - The inner wrapper element; style to override panel backgrounds, shadows, padding, or borders without shadow-root piercing.
12
20
  */
13
21
  @customElement('schmancy-dropdown-content')
14
22
  export class SchmancyDropdownContent extends TailwindElement(css`
@@ -7,6 +7,18 @@ import { SPRING_SMOOTH } from '../utils/animation.js'
7
7
  import { reducedMotion$ } from '../directives/reduced-motion'
8
8
  import '../surface/surface.js'
9
9
 
10
+ /**
11
+ * Container for schmancy-expand children — coordinates mutual-exclusion so only one child is open at a time. Also renders the portal panel that the active child expands into.
12
+ *
13
+ * @element schmancy-expand-root
14
+ * @summary Always wrap a group of schmancy-expand children. Without a root, each schmancy-expand behaves independently (which is usually not what you want — prefer schmancy-details for that).
15
+ * @example
16
+ * <schmancy-expand-root>
17
+ * <schmancy-expand summary="Step 1">…</schmancy-expand>
18
+ * <schmancy-expand summary="Step 2">…</schmancy-expand>
19
+ * </schmancy-expand-root>
20
+ * @platform div - Coordinating wrapper. Degrades to a plain div if the tag never registers — children fall back to independent `<details>` behavior.
21
+ */
10
22
  @customElement('schmancy-expand-root')
11
23
  export class SchmancyExpandRoot extends SurfaceMixin(TailwindElement(css`
12
24
  :host {
@@ -12,6 +12,20 @@ import { SchmancyExpandRoot } from './expand-root.component.js'
12
12
  /** Dispatch this event on window to close whichever schmancy-expand is currently open */
13
13
  export const SCHMANCY_EXPAND_REQUEST_CLOSE = 'schmancy-expand-request-close'
14
14
 
15
+ /**
16
+ * Accordion-style section — expands on click, coordinates with siblings via schmancy-expand-root to close any sibling when a new one opens. Only one schmancy-expand can be open at a time within the same root.
17
+ *
18
+ * @element schmancy-expand
19
+ * @summary Use for grouped progressive-disclosure where only one section should be open at a time. Prefer schmancy-details when sections should be independent.
20
+ * @example
21
+ * <schmancy-expand-root>
22
+ * <schmancy-expand summary="Billing">Billing form…</schmancy-expand>
23
+ * <schmancy-expand summary="Shipping">Shipping form…</schmancy-expand>
24
+ * <schmancy-expand summary="Review">Order review…</schmancy-expand>
25
+ * </schmancy-expand-root>
26
+ * @platform details toggle - Schmancy-skinned accordion section. Degrades to `<details>` if the tag never registers — loses mutual-exclusion behavior but stays functional.
27
+ * @fires toggle - When the open state changes.
28
+ */
15
29
  @customElement('schmancy-expand')
16
30
  export default class SchmancyExpand extends TailwindElement(css`
17
31
  :host {
@@ -49,7 +49,11 @@ declare global {
49
49
  }
50
50
 
51
51
  /**
52
- * A custom scrollable container with enhanced features.
52
+ * Scrollable container with debounced scroll events, horizontal/vertical direction, optional hidden scrollbar, and programmatic scrollTo via command events or refs.
53
+ *
54
+ * @element schmancy-scroll
55
+ * @summary Use anywhere you'd reach for `overflow: auto` but also need debounced scroll events (for sticky headers, scroll spies, virtualization triggers) or the ability to drive scroll from elsewhere in the app by dispatching a schmancy-scroll-command event.
56
+ * @platform div - Styled scrollable `<div>`. Degrades to a plain scrollable div if the tag never registers — loses the debounced scroll event and the command-bus integration.
53
57
  *
54
58
  * @fires {SchmancyScrollEvent} scroll - Fired when scrolling occurs (with a configurable debounce)
55
59
  * @slot - Default slot for content to be scrolled
@@ -6,7 +6,17 @@ import { css, html } from 'lit'
6
6
  import { customElement, property, queryAssignedElements } from 'lit/decorators.js'
7
7
 
8
8
  /**
9
+ * Single row in a schmancy-list — supports leading icon/avatar, main content, trailing actions. Clickable via click event, or used as a schmancy-menu-item's visual base.
10
+ *
9
11
  * @element schmancy-list-item
12
+ * @summary Prefer nesting inside schmancy-list for consistent spacing/surface. Use `href` to make the row a navigation target (renders as `<a>`), or a click handler for in-app actions.
13
+ * @example
14
+ * <schmancy-list-item href="/profile">
15
+ * <schmancy-icon slot="leading">person</schmancy-icon>
16
+ * Profile
17
+ * <schmancy-icon slot="trailing">chevron_right</schmancy-icon>
18
+ * </schmancy-list-item>
19
+ * @platform li click - Styled `<li>` or `<a>` depending on `href`. Degrades to a plain list item if the tag never registers.
10
20
  * @slot leading - leading content
11
21
  * @slot trailing - trailing content
12
22
  * @slot - default content
package/src/list/list.ts CHANGED
@@ -7,19 +7,18 @@ import { customElement, property } from 'lit/decorators.js'
7
7
  import { SchmancyListTypeContext } from './context'
8
8
 
9
9
  /**
10
- * `<schmancy-list>` component.
11
- *
12
- * A list component that wraps its content within a customizable surface.
13
- * It allows you to set the surface type and fill style, and can optionally
14
- * enable scrolling behavior by delegating the scroller attribute to the surface.
10
+ * Wrapped list container — holds schmancy-list-item children on a themed surface. Optionally scrollable.
15
11
  *
16
12
  * @element schmancy-list
17
- * @slot - The default slot for list items.
18
- *
13
+ * @summary Use for vertical lists of similarly-shaped items: settings entries, menu items, contact lists, notification lists. Pair with schmancy-list-item children.
19
14
  * @example
20
15
  * <schmancy-list surface="container" scroller>
21
- * <schmancy-list-item>List Item 1</schmancy-list-item>
16
+ * <schmancy-list-item>First</schmancy-list-item>
17
+ * <schmancy-list-item>Second</schmancy-list-item>
18
+ * <schmancy-list-item>Third</schmancy-list-item>
22
19
  * </schmancy-list>
20
+ * @platform ul - Styled list container. Degrades to a plain ul/div if the tag never registers.
21
+ * @slot - The default slot for list items.
23
22
  */
24
23
  @customElement('schmancy-list')
25
24
  export class List extends TailwindElement(css`
@@ -3,6 +3,19 @@ import { css, html } from 'lit'
3
3
  import { customElement } from 'lit/decorators.js'
4
4
  import { $dialog } from '../dialog/dialog-service'
5
5
 
6
+ /**
7
+ * Single item inside a schmancy-menu. Auto-dismisses the menu dialog on click — attach your action handler to `@click` and it just works.
8
+ *
9
+ * @element schmancy-menu-item
10
+ * @summary Always nested inside schmancy-menu. The click handler runs before the dialog closes, so `@click=${() => doThing()}` is the full pattern.
11
+ * @example
12
+ * <schmancy-menu-item @click=${() => archive()}>
13
+ * <schmancy-icon slot="leading">archive</schmancy-icon>
14
+ * Archive
15
+ * </schmancy-menu-item>
16
+ * @platform menuitem click - Wraps schmancy-list-item with auto-dismiss. Degrades to a styled `<button role="menuitem">` if the tag never registers.
17
+ * @slot - The item label and optional icons.
18
+ */
6
19
  @customElement('schmancy-menu-item')
7
20
  export default class SchmancyMenuItem extends $LitElement(css`
8
21
  :host {
package/src/menu/menu.ts CHANGED
@@ -4,31 +4,19 @@ import { customElement, query } from 'lit/decorators.js'
4
4
  import { $dialog } from '../dialog/dialog-service'
5
5
 
6
6
  /**
7
- * Menu Component
7
+ * Floating menu — a trigger button + a list of schmancy-menu-item children that open as a positioned dialog on click.
8
8
  *
9
- * CRITICAL: The dialog ONLY renders the raw menu items passed via the default slot.
10
- * NO <ul> wrapper, NO classes, NO additional markup in the dialog call.
11
- * The dialog service handles positioning and display - we just pass the pure content.
12
- *
13
- * @example Basic menu with auto-dismiss
14
- * ```typescript
9
+ * @element schmancy-menu
10
+ * @summary Use for dropdown menus attached to a button or icon — "More actions", "Account", row overflow menus in tables. Clicking a schmancy-menu-item inside auto-dismisses; custom components slotted inside must call `$dialog.dismiss()` themselves.
11
+ * @example
15
12
  * <schmancy-menu>
16
- * <schmancy-button slot="trigger">Actions</schmancy-button>
17
- * <schmancy-menu-item @click=${() => editItem()}>Edit</schmancy-menu-item>
18
- * <schmancy-menu-item @click=${() => deleteItem()}>Delete</schmancy-menu-item>
13
+ * <schmancy-icon-button slot="trigger" aria-label="Actions">
14
+ * <schmancy-icon>more_vert</schmancy-icon>
15
+ * </schmancy-icon-button>
16
+ * <schmancy-menu-item @click=${() => edit()}>Edit</schmancy-menu-item>
17
+ * <schmancy-menu-item @click=${() => remove()}>Delete</schmancy-menu-item>
19
18
  * </schmancy-menu>
20
- * ```
21
- * Note: Dialog auto-dismisses when schmancy-menu-item is clicked
22
- *
23
- * @example Custom component (manual dismiss)
24
- * ```typescript
25
- * <schmancy-menu>
26
- * <schmancy-icon-button slot="trigger">settings</schmancy-icon-button>
27
- * <my-settings-form @submit=${() => $dialog.dismiss()}></my-settings-form>
28
- * </schmancy-menu>
29
- * ```
30
- * Note: Custom components must call $dialog.dismiss() manually
31
- *
19
+ * @platform menu close - Trigger + floating listbox dialog. Degrades to a native `<select>` or inline list if the tag never registers.
32
20
  * @slot trigger - Button to open menu (new naming)
33
21
  * @slot button - Button to open menu (backward compatible)
34
22
  * @slot default - Menu items or any custom component to display in dialog
@@ -3,7 +3,18 @@ import { css, html } from 'lit'
3
3
  import { customElement } from 'lit/decorators.js'
4
4
 
5
5
  /**
6
+ * Top app bar region inside schmancy-nav-drawer — the horizontal strip above the content area that typically holds the page title, hamburger trigger, and contextual actions.
7
+ *
6
8
  * @element schmancy-nav-drawer-appbar
9
+ * @summary Always nested inside schmancy-nav-drawer. Holds the page-level title + top-right actions. On mobile, the drawer's hamburger button renders inside this region.
10
+ * @example
11
+ * <schmancy-nav-drawer-appbar>
12
+ * <schmancy-typography type="title" token="lg">Dashboard</schmancy-typography>
13
+ * <schmancy-icon-button slot="trailing" aria-label="Notifications">
14
+ * <schmancy-icon>notifications</schmancy-icon>
15
+ * </schmancy-icon-button>
16
+ * </schmancy-nav-drawer-appbar>
17
+ * @platform header - Styled horizontal bar. Degrades to a plain header element if the tag never registers.
7
18
  * @slot - The default slot
8
19
  */
9
20
  @customElement('schmancy-nav-drawer-appbar')
@@ -3,6 +3,17 @@ import { css, html } from 'lit'
3
3
  import { customElement } from 'lit/decorators.js'
4
4
  import { fromEvent, takeUntil } from 'rxjs'
5
5
 
6
+ /**
7
+ * Main content region inside schmancy-nav-drawer — typically hosts the router outlet or the page's body content.
8
+ *
9
+ * @element schmancy-nav-drawer-content
10
+ * @summary Always nested inside schmancy-nav-drawer. Scrollable by default; propagates scroll events up so the drawer can collapse app-bar on scroll.
11
+ * @example
12
+ * <schmancy-nav-drawer-content>
13
+ * <schmancy-area name="main"></schmancy-area>
14
+ * </schmancy-nav-drawer-content>
15
+ * @platform main scroll - Scrollable `<main>`. Degrades to a plain scrollable div if the tag never registers.
16
+ */
6
17
  @customElement('schmancy-nav-drawer-content')
7
18
  export class SchmancyNavigationDrawerContent extends $LitElement(css`
8
19
  :host {
@@ -12,8 +12,23 @@ import {
12
12
  } from './context'
13
13
 
14
14
  /**
15
+ * Responsive navigation drawer — a left sidebar that becomes a hamburger-triggered modal overlay on narrow viewports. Composes schmancy-nav-drawer-navbar (the nav rail), schmancy-nav-drawer-appbar (the top bar), and schmancy-nav-drawer-content (the main region).
16
+ *
15
17
  * @element schmancy-nav-drawer
18
+ * @summary The app-shell layout primitive. Wrap your whole app in this when you want "persistent sidebar on desktop, drawer on mobile" behavior. Mode auto-switches at the breakpoint.
19
+ * @example
20
+ * <schmancy-nav-drawer>
21
+ * <schmancy-nav-drawer-navbar>
22
+ * <!-- nav items, typically schmancy-list-item links -->
23
+ * </schmancy-nav-drawer-navbar>
24
+ * <schmancy-nav-drawer-appbar>App title</schmancy-nav-drawer-appbar>
25
+ * <schmancy-nav-drawer-content>
26
+ * <!-- router outlet / page content -->
27
+ * </schmancy-nav-drawer-content>
28
+ * </schmancy-nav-drawer>
29
+ * @platform div - Flex layout with viewport-width mode switching. Degrades to a stack of plain divs if the tag never registers.
16
30
  * @slot - The content slot
31
+ * @fires schmancy-drawer-state - When the drawer open/close state changes on mobile.
17
32
  */
18
33
  @customElement('schmancy-nav-drawer')
19
34
  export class SchmancyNavigationDrawer extends $LitElement(css`
@@ -16,6 +16,20 @@ const OVERLAY_ANIM_DURATION_OPEN = 200
16
16
  const OVERLAY_ANIM_DURATION_CLOSE = 150
17
17
  const NAV_ANIM_DURATION = 200
18
18
 
19
+ /**
20
+ * Sidebar region inside schmancy-nav-drawer — the persistent-on-desktop / modal-on-mobile nav rail.
21
+ *
22
+ * @element schmancy-nav-drawer-navbar
23
+ * @summary Always nested inside schmancy-nav-drawer. On desktop: pinned left sidebar. On mobile: modal overlay triggered by the hamburger button in schmancy-nav-drawer-appbar.
24
+ * @example
25
+ * <schmancy-nav-drawer-navbar>
26
+ * <schmancy-list>
27
+ * <schmancy-list-item href="/dashboard">Dashboard</schmancy-list-item>
28
+ * <schmancy-list-item href="/settings">Settings</schmancy-list-item>
29
+ * </schmancy-list>
30
+ * </schmancy-nav-drawer-navbar>
31
+ * @platform nav - Sidebar `<nav>` with responsive open/close behavior. Degrades to a plain sidebar div if the tag never registers.
32
+ */
19
33
  @customElement('schmancy-nav-drawer-navbar')
20
34
  export class SchmancyNavigationDrawerSidebar extends $LitElement() {
21
35
  // Consume context values. Renamed from "state" to "drawerState" to avoid confusion.
@@ -7,12 +7,11 @@ import { BehaviorSubject, fromEvent, merge, timer } from 'rxjs'
7
7
  import { takeUntil, tap, filter } from 'rxjs/operators'
8
8
 
9
9
  /**
10
- * `<schmancy-navigation-bar-item>` component
11
- *
12
- * Individual navigation item for use within a navigation bar.
13
- * Represents a single destination with an icon and optional label following Material Design 3 specifications.
10
+ * Single destination inside schmancy-navigation-bar — an icon + optional label representing one primary app destination.
14
11
  *
15
12
  * @element schmancy-navigation-bar-item
13
+ * @summary Always nested inside schmancy-navigation-bar. Use `icon` attr for a Material Symbols glyph or slot=icon for custom content.
14
+ * @platform button click - Styled navigation target. Degrades to a plain `<button>` if the tag never registers.
16
15
  * @slot icon - Slot for custom icon content
17
16
  * @slot - Default slot for custom content
18
17
  *
@@ -15,17 +15,11 @@ const NAV_BAR_HEIGHT = 80
15
15
  const MOBILE_BREAKPOINT = '(max-width: 767px)'
16
16
 
17
17
  /**
18
- * `<schmancy-navigation-bar>` component
19
- *
20
- * A horizontal navigation component following Material Design 3 specifications.
21
- * Navigation bars provide access to between 3-7 primary destinations.
22
- * Automatically hides in fullscreen mode when triggered via schmancyTheme.next({ fullscreen: true }).
23
- *
24
- * **IMPORTANT**: This component includes `z-10` by default (consistent with navigation-rail).
25
- * The consumer is responsible for positioning the navigation bar in their layout.
26
- * For typical bottom-fixed positioning, add: `class="fixed bottom-0 left-0 right-0"`.
18
+ * Bottom navigation bar — Material Design 3 horizontal nav for mobile primary destinations (3–7 items). Auto-hides in fullscreen mode.
27
19
  *
28
20
  * @element schmancy-navigation-bar
21
+ * @summary Use for mobile primary navigation (home, search, favorites, settings). For persistent desktop nav, prefer schmancy-navigation-rail or schmancy-nav-drawer. Consumer is responsible for fixed-bottom positioning via class.
22
+ * @platform nav - Styled horizontal nav with schmancy-navigation-bar-item children. Degrades to a plain flex container if the tag never registers.
29
23
  * @slot - Default slot for navigation bar items
30
24
  *
31
25
  * @fires navigation-change - When an item is selected