@manufosela/behaviour-accordion

@manufosela/behaviour-accordion

Accessible accordion web component with smooth animations

Behaviour Accordion

Accessible accordion with smooth animations and keyboard navigation.

Basic Usage

Click headers to expand/collapse sections. Only one open at a time.

Content for the first section. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Content for the second section. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.

Content for the third section. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.

Click an item...
<behaviour-accordion> <accordion-item header="Section 1"> <p>Content for the first section. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p> </accordion-item> <accordion-item header="Section 2"> <p>Content for the second section. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.</p> </accordion-item> <accordion-item header="Section 3"> <p>Content for the third section. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.</p> </accordion-item> </behaviour-accordion>

Multiple Open

Allow multiple sections to be open simultaneously.

Lit is a simple library for building fast, lightweight web components.

Web components are native browser features that allow you to create reusable custom elements.

Yes! This accordion supports keyboard navigation and ARIA attributes.

<behaviour-accordion multiple> <accordion-item header="FAQ: What is Lit?"> <p>Lit is a simple library for building fast, lightweight web components.</p> </accordion-item> <accordion-item header="FAQ: Why Web Components?"> <p>Web components are native browser features that allow you to create reusable custom elements.</p> </accordion-item> <accordion-item header="FAQ: Is it accessible?"> <p>Yes! This accordion supports keyboard navigation and ARIA attributes.</p> </accordion-item> </behaviour-accordion>

Initially Expanded

Pre-expand specific items on load.

This section starts expanded.

This section starts collapsed.

This section also starts expanded.

<behaviour-accordion expanded="0,2"> <accordion-item header="Expanded by default"> <p>This section starts expanded.</p> </accordion-item> <accordion-item header="Collapsed by default"> <p>This section starts collapsed.</p> </accordion-item> <accordion-item header="Also expanded"> <p>This section also starts expanded.</p> </accordion-item> </behaviour-accordion>

Custom Header Slot

Use the header slot for rich content.

🎨 Design System

Custom header with icon and styled text.

⚙️ Configuration

Another custom header example.

<behaviour-accordion> <accordion-item> <span slot="header" style="display: flex; align-items: center; gap: 0.5rem;"> <span style="font-size: 1.5rem;">🎨</span> <strong>Design System</strong> </span> <p>Custom header with icon and styled text.</p> </accordion-item> <accordion-item> <span slot="header" style="display: flex; align-items: center; gap: 0.5rem;"> <span style="font-size: 1.5rem;">⚙️</span> <strong>Configuration</strong> </span> <p>Another custom header example.</p> </accordion-item> </behaviour-accordion>

Disabled Item

Disable specific accordion items.

This item can be expanded.

This content cannot be accessed.

This item works normally.

<behaviour-accordion> <accordion-item header="Enabled Item"> <p>This item can be expanded.</p> </accordion-item> <accordion-item header="Disabled Item" disabled> <p>This content cannot be accessed.</p> </accordion-item> <accordion-item header="Another Enabled"> <p>This item works normally.</p> </accordion-item> </behaviour-accordion>

Programmatic Control

Control the accordion with JavaScript methods.

Content 0 Content 1 Content 2
<behaviour-accordion id="programmatic" multiple> <accordion-item header="Item 0">Content 0</accordion-item> <accordion-item header="Item 1">Content 1</accordion-item> <accordion-item header="Item 2">Content 2</accordion-item> </behaviour-accordion> <script> const accordion = document.getElementById('programmatic'); accordion.expand(1); // Expand Item 1 accordion.collapse(1); // Collapse Item 1 accordion.expandAll(); // Expand all items accordion.collapseAll(); // Collapse all items </script>

Custom Styling

Theme with CSS custom properties.

Custom styled accordion with purple theme.

Using CSS custom properties for theming.

<behaviour-accordion style=" --accordion-border: #8b5cf6; --accordion-header-bg: #f3e8ff; --accordion-header-hover: #ede9fe; --accordion-header-text: #5b21b6; --accordion-icon: #8b5cf6; --accordion-focus: #8b5cf6; --accordion-radius: 12px; "> <accordion-item header="Purple Theme"> <p>Custom styled accordion with purple theme.</p> </accordion-item> <accordion-item header="CSS Variables"> <p>Using CSS custom properties for theming.</p> </accordion-item> </behaviour-accordion>
Demo code (CodePen-ready HTML, CSS, JS)
HTML (html)
<h1>Behaviour Accordion</h1>
<p class="subtitle">Accessible accordion with smooth animations and keyboard navigation.</p>
<div class="demo-links">
  <a href="https://manufosela.dev/ui-components/">← Back to components</a>
  <a href="https://github.com/manufosela/ui-components/tree/main/packages/behaviour-accordion" target="_blank" rel="noopener">GitHub Repo</a>
  <a href="playground.html">Playground</a>
  <a href="https://www.npmjs.com/package/@manufosela/behaviour-accordion" target="_blank" rel="noopener">npm</a>
</div>
<div class="demo-theme-toggle">
  <theme-toggle theme="dark"></theme-toggle>
</div>
<div class="demo-section">
    <h2>Basic Usage</h2>
    <p>Click headers to expand/collapse sections. Only one open at a time.</p>
    <behaviour-accordion id="basic">
      <accordion-item header="Section 1">
        <p>Content for the first section. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.</p>
      </accordion-item>
      <accordion-item header="Section 2">
        <p>Content for the second section. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip.</p>
      </accordion-item>
      <accordion-item header="Section 3">
        <p>Content for the third section. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="output" id="basicOutput">Click an item...</div>
    <div class="code-block">&lt;behaviour-accordion&gt;
  &lt;accordion-item header="Section 1"&gt;
    &lt;p&gt;Content for the first section. Lorem ipsum dolor sit amet,
    consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Section 2"&gt;
    &lt;p&gt;Content for the second section. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Section 3"&gt;
    &lt;p&gt;Content for the third section. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
      
  </div>

  <div class="demo-section">
    <h2>Multiple Open</h2>
    <p>Allow multiple sections to be open simultaneously.</p>
    <behaviour-accordion multiple>
      <accordion-item header="FAQ: What is Lit?">
        <p>Lit is a simple library for building fast, lightweight web components.</p>
      </accordion-item>
      <accordion-item header="FAQ: Why Web Components?">
        <p>Web components are native browser features that allow you to create reusable custom elements.</p>
      </accordion-item>
      <accordion-item header="FAQ: Is it accessible?">
        <p>Yes! This accordion supports keyboard navigation and ARIA attributes.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="code-block">&lt;behaviour-accordion multiple&gt;
  &lt;accordion-item header="FAQ: What is Lit?"&gt;
    &lt;p&gt;Lit is a simple library for building fast, lightweight web components.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="FAQ: Why Web Components?"&gt;
    &lt;p&gt;Web components are native browser features that allow you to create
    reusable custom elements.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="FAQ: Is it accessible?"&gt;
    &lt;p&gt;Yes! This accordion supports keyboard navigation and ARIA attributes.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
  </div>

  <div class="demo-section">
    <h2>Initially Expanded</h2>
    <p>Pre-expand specific items on load.</p>
    <behaviour-accordion expanded="0,2">
      <accordion-item header="Expanded by default">
        <p>This section starts expanded.</p>
      </accordion-item>
      <accordion-item header="Collapsed by default">
        <p>This section starts collapsed.</p>
      </accordion-item>
      <accordion-item header="Also expanded">
        <p>This section also starts expanded.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="code-block">&lt;behaviour-accordion expanded="0,2"&gt;
  &lt;accordion-item header="Expanded by default"&gt;
    &lt;p&gt;This section starts expanded.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Collapsed by default"&gt;
    &lt;p&gt;This section starts collapsed.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Also expanded"&gt;
    &lt;p&gt;This section also starts expanded.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
  </div>

  <div class="demo-section">
    <h2>Custom Header Slot</h2>
    <p>Use the header slot for rich content.</p>
    <behaviour-accordion>
      <accordion-item>
        <span slot="header" style="display: flex; align-items: center; gap: 0.5rem;">
          <span style="font-size: 1.5rem;">🎨</span>
          <strong>Design System</strong>
        </span>
        <p>Custom header with icon and styled text.</p>
      </accordion-item>
      <accordion-item>
        <span slot="header" style="display: flex; align-items: center; gap: 0.5rem;">
          <span style="font-size: 1.5rem;">⚙️</span>
          <strong>Configuration</strong>
        </span>
        <p>Another custom header example.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="code-block">&lt;behaviour-accordion&gt;
  &lt;accordion-item&gt;
    &lt;span slot="header" style="display: flex; align-items: center; gap: 0.5rem;"&gt;
      &lt;span style="font-size: 1.5rem;"&gt;🎨&lt;/span&gt;
      &lt;strong&gt;Design System&lt;/strong&gt;
    &lt;/span&gt;
    &lt;p&gt;Custom header with icon and styled text.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item&gt;
    &lt;span slot="header" style="display: flex; align-items: center; gap: 0.5rem;"&gt;
      &lt;span style="font-size: 1.5rem;"&gt;⚙️&lt;/span&gt;
      &lt;strong&gt;Configuration&lt;/strong&gt;
    &lt;/span&gt;
    &lt;p&gt;Another custom header example.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
  </div>

  <div class="demo-section">
    <h2>Disabled Item</h2>
    <p>Disable specific accordion items.</p>
    <behaviour-accordion>
      <accordion-item header="Enabled Item">
        <p>This item can be expanded.</p>
      </accordion-item>
      <accordion-item header="Disabled Item" disabled>
        <p>This content cannot be accessed.</p>
      </accordion-item>
      <accordion-item header="Another Enabled">
        <p>This item works normally.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="code-block">&lt;behaviour-accordion&gt;
  &lt;accordion-item header="Enabled Item"&gt;
    &lt;p&gt;This item can be expanded.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Disabled Item" disabled&gt;
    &lt;p&gt;This content cannot be accessed.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="Another Enabled"&gt;
    &lt;p&gt;This item works normally.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
  </div>

  <div class="demo-section">
    <h2>Programmatic Control</h2>
    <p>Control the accordion with JavaScript methods.</p>
    <behaviour-accordion id="programmatic" multiple>
      <accordion-item header="Item 0">Content 0</accordion-item>
      <accordion-item header="Item 1">Content 1</accordion-item>
      <accordion-item header="Item 2">Content 2</accordion-item>
    </behaviour-accordion>
    <div class="controls">
      <button onclick="document.getElementById('programmatic').expand(1)">Expand Item 1</button>
      <button onclick="document.getElementById('programmatic').collapse(1)">Collapse Item 1</button>
      <button onclick="document.getElementById('programmatic').expandAll()">Expand All</button>
      <button onclick="document.getElementById('programmatic').collapseAll()">Collapse All</button>
    </div>
    <div class="code-block">&lt;behaviour-accordion id="programmatic" multiple&gt;
  &lt;accordion-item header="Item 0"&gt;Content 0&lt;/accordion-item&gt;
  &lt;accordion-item header="Item 1"&gt;Content 1&lt;/accordion-item&gt;
  &lt;accordion-item header="Item 2"&gt;Content 2&lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;

&lt;script&gt;
  const accordion = document.getElementById('programmatic');
  accordion.expand(1);     // Expand Item 1
  accordion.collapse(1);   // Collapse Item 1
  accordion.expandAll();   // Expand all items
  accordion.collapseAll(); // Collapse all items
&lt;/script&gt;</div>
  </div>

  <div class="demo-section">
    <h2>Custom Styling</h2>
    <p>Theme with CSS custom properties.</p>
    <behaviour-accordion style="
      --accordion-border: #8b5cf6;
      --accordion-header-bg: #f3e8ff;
      --accordion-header-hover: #ede9fe;
      --accordion-header-text: #5b21b6;
      --accordion-icon: #8b5cf6;
      --accordion-focus: #8b5cf6;
      --accordion-radius: 12px;
    ">
      <accordion-item header="Purple Theme">
        <p>Custom styled accordion with purple theme.</p>
      </accordion-item>
      <accordion-item header="CSS Variables">
        <p>Using CSS custom properties for theming.</p>
      </accordion-item>
    </behaviour-accordion>
    <div class="code-block">&lt;behaviour-accordion style="
  --accordion-border: #8b5cf6;
  --accordion-header-bg: #f3e8ff;
  --accordion-header-hover: #ede9fe;
  --accordion-header-text: #5b21b6;
  --accordion-icon: #8b5cf6;
  --accordion-focus: #8b5cf6;
  --accordion-radius: 12px;
"&gt;
  &lt;accordion-item header="Purple Theme"&gt;
    &lt;p&gt;Custom styled accordion with purple theme.&lt;/p&gt;
  &lt;/accordion-item&gt;
  &lt;accordion-item header="CSS Variables"&gt;
    &lt;p&gt;Using CSS custom properties for theming.&lt;/p&gt;
  &lt;/accordion-item&gt;
&lt;/behaviour-accordion&gt;</div>
  </div>
CSS (css)
:root {
  --bg: #0c0f14;
  --bg-elevated: #141923;
  --bg-panel: #171d28;
  --border: #262f3f;
  --text: #f4f6fb;
  --text-muted: #a7b0c2;
  --text-dim: #7d879b;
  --accent: #ff8a3d;
  --accent-strong: #ff6a00;
  --accent-soft: rgba(255, 138, 61, 0.16);
  --shadow: 0 20px 50px rgba(5, 8, 14, 0.45);
  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 10px;
  --max-width: 1160px;
}

h1 { color: #1d1d1f; }
    .demo-section {
      background: white;
      padding: 2rem;
      border-radius: 12px;
      margin-bottom: 2rem;
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
    }
    h2 { margin-top: 0; color: #1d1d1f; }
    p { color: #86868b; line-height: 1.6; }
    a { color: #3b82f6; }
    .code-block {
      background: #1d1d1f;
      color: #f5f5f7;
      padding: 1rem;
      border-radius: 8px;
      font-family: monospace;
      font-size: 0.8rem;
      margin-top: 1rem;
      overflow: auto;
      max-height: 300px;
      white-space: pre;
    }
    .output {
      margin-top: 1rem;
      padding: 1rem;
      background: #f5f5f7;
      border-radius: 8px;
      font-family: monospace;
    }
    .controls {
      display: flex;
      gap: 0.5rem;
      margin-top: 1rem;
    }
    .controls button {
      padding: 0.5rem 1rem;
      border: 1px solid #e5e7eb;
      border-radius: 6px;
      background: white;
      cursor: pointer;
      transition: background-color 0.2s;
    }
    .controls button:hover {
      background: #f3f4f6;
    }
  
    footer {
      text-align: center;
      margin-top: 3rem;
      padding-top: 2rem;
      border-top: 1px solid #d2d2d7;
      color: #86868b;
      font-size: 0.9rem;
    }
    footer a { color: #1d1d1f; text-decoration: none; }
    footer a:hover { text-decoration: underline; }
  


@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;600;700&display=swap');

:root {
  --bg: #f5f5f7;
  --bg-2: #ffffff;
  --bg-spot-1: #f8e9d0;
  --bg-spot-2: #e8eef8;
  --card: #ffffff;
  --text: #1d1d1f;
  --muted: #6b7280;
  --line: #e5e7eb;
  --accent: #ffb000;
  --accent-2: #00a7d6;
  --accent-soft: rgba(255, 176, 0, 0.18);
  --surface-1: #f3f4f6;
  --surface-2: #eef2f7;
  --code-bg: #111827;
  --code-text: #f9fafb;
  --panel-bg: rgba(255, 255, 255, 0.85);
  --overlay-bg: rgba(255, 255, 255, 0.98);
}

:root.dark {
  --bg: #0f1117;
  --bg-2: #151a26;
  --bg-spot-1: #1a2136;
  --bg-spot-2: #1d1b34;
  --card: #1c2233;
  --text: #f3f6ff;
  --muted: #b8c0d9;
  --line: #2b3247;
  --accent: #ffb000;
  --accent-2: #00d0ff;
  --accent-soft: rgba(255, 176, 0, 0.25);
  --surface-1: #0b0f1a;
  --surface-2: #263046;
  --code-bg: #0b0f1a;
  --code-text: #d6d9e6;
  --panel-bg: rgba(28, 34, 51, 0.8);
  --overlay-bg: rgba(15, 17, 23, 0.98);
}

* {
  box-sizing: border-box;
}

a {
  color: var(--accent);
}

h1 {
  color: var(--accent);
}

.demo-links {
  margin-top: 12px;
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

.demo-links a {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 12px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.demo-links a:hover {
  color: var(--text);
  border-color: var(--accent-2);
}

.demo-theme-toggle {
  margin-top: 12px;
  display: flex;
  justify-content: center;
}

header {
  border-bottom: 1px solid var(--line);
}

.demo-card,
.section,
.demo-section,
.panel,
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 16px;
  color: var(--text);
  box-shadow: 0 18px 36px rgba(6, 10, 24, 0.45);
}

.demo-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.demo-card .code-block {
  margin-top: auto;
}

.demo-grid,
.grid {
  align-items: stretch;
}

.demo-card h2,
.demo-card h3,
.section h2,
.demo-section h2,
.panel-header {
  color: var(--text);
}

.label,
.stat-label,
.category-title,
.subtitle,
.hint,
.note {
  color: var(--muted);
}

.info-item,
.capability,
.preference,
.option-group,
.output,
.current-url,
.event-log,
.result-card,
.log,
.stat {
  background: var(--surface-1);
  border: 1px solid var(--line);
  color: var(--text);
}

.info-item .label,
.capability .name {
  color: var(--muted);
}

.panel-header,
.options,
.topbar,
.top-links {
  background: var(--panel-bg);
  border-bottom: 1px solid var(--line);
  color: var(--text);
}

.subtitle,
.hint,
.note,
.demo-card p,
.section p,
.demo-section p {
  color: var(--muted);
}

.code-block,
pre,
code {
  background: var(--code-bg);
  color: var(--code-text);
  border-radius: 8px;
}

.value-display,
.output,
.result,
.demo-output {
  background: var(--surface-1);
  border: 1px solid var(--line);
  color: var(--text);
}

button {
  background: linear-gradient(120deg, var(--accent), #ff6a00);
  color: #111;
  border: none;
}

button:hover {
  filter: brightness(1.05);
}

input,
select,
textarea {
  background: var(--surface-1);
  color: var(--text);
  border: 1px solid var(--line);
}

footer {
  color: var(--muted);
}

footer a {
  color: var(--text);
}

arc-slider {
  --arc-slider-text-color: var(--text);
  --arc-slider-value-bg: var(--surface-1);
  --arc-slider-value-border: var(--line);
  --arc-slider-value-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
}

rich-select {
  --caller-background: var(--card);
  --caller-color: var(--text);
  --caller-border: 1px solid var(--line);
  --caller-hover-background: var(--surface-2);
  --caller-hover-color: var(--text);
  --caller-hover-border-color: var(--line);
  --caller-focus-border-color: var(--accent-2);
  --caller-focus-shadow: 0 0 0 3px rgba(0, 208, 255, 0.25);
  --caller-disabled-background: var(--surface-1);
  --caller-disabled-color: #6b7280;
  --caller-disabled-border-color: var(--line);
  --arrow-color: var(--muted);
  --selectOptions-background: var(--card);
  --selectOptions-border: 1px solid var(--line);
  --selectOptions-shadow: 0 10px 22px rgba(0, 0, 0, 0.45);
  --input-background: var(--surface-1);
  --input-border: 1px solid var(--line);
  --input-color: var(--text);
  --input-placeholder-color: #6b7280;
  --option-color: var(--text);
  --option-hover-background: var(--surface-2);
  --option-hover-color: var(--text);
  --option-active-background: var(--accent);
  --option-active-color: #111;
  --option-selected-background: var(--accent-soft);
  --option-selected-color: var(--text);
  --option-disabled-background: var(--surface-1);
  --option-disabled-color: #6b7280;
}

multi-select {
  --multi-select-bg: var(--card);
  --multi-select-border-color: var(--line);
  --multi-select-border-hover: var(--line);
  --multi-select-border-focus: var(--accent-2);
  --multi-select-text-color: var(--text);
  --multi-select-placeholder-color: #6b7280;
  --multi-select-arrow-color: var(--muted);
  --multi-select-dropdown-bg: var(--card);
  --multi-select-shadow: 0 10px 22px rgba(0, 0, 0, 0.45);
  --multi-select-option-hover-bg: var(--surface-2);
  --multi-select-option-selected-bg: var(--accent-soft);
}

tab-nav {
  --tab-bg: var(--card);
  --tab-border: var(--line);
  --tab-text: var(--muted);
  --tab-active-text: var(--text);
  --tab-hover-bg: var(--surface-2);
  --tab-active-border: var(--accent);
  --tab-disabled: #9ca3af;
}

slider-underline {
  --slider-track: var(--surface-2);
  --slider-fill: var(--accent);
  --slider-thumb: var(--accent);
  --slider-label-color: var(--text);
  --slider-tick-color: #9ca3af;
  --slider-tick-value-color: var(--muted);
}

header-nav {
  --header-bg: var(--card);
  --header-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
  --header-link-color: var(--text);
  --header-link-hover: var(--accent);
  --header-mobile-hover-bg: var(--surface-2);
}

calendar-inline {
  --calendar-bg: var(--card);
  --calendar-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
  --calendar-text: var(--text);
  --calendar-accent: var(--accent);
  --calendar-today: var(--accent-soft);
  --calendar-selected: var(--accent);
  --calendar-hover-bg: var(--surface-2);
  --calendar-muted: var(--muted);
  --calendar-muted-strong: #9ca3af;
  --calendar-other-month: #9ca3af;
  --calendar-disabled: #cbd5e1;
  --calendar-holiday: #ef4444;
  --calendar-holiday-selected: #111;
}

marked-calendar {
  --calendar-bg: var(--card);
  --calendar-border: var(--line);
  --calendar-title: var(--text);
  --calendar-muted: var(--muted);
  --calendar-surface: var(--surface-1);
  --calendar-accent: var(--accent);
  --calendar-accent-hover: #ff7a1a;
  --calendar-border-strong: var(--line);
  --calendar-contrast: #111;
  --calendar-nav-bg: var(--surface-1);
  --calendar-nav-hover: var(--surface-2);
}

radar-chart {
  --radar-bg: var(--card);
  --radar-grid-color: var(--line);
  --radar-axis-color: #94a3b8;
  --radar-label-color: var(--muted);
}

multi-carousel {
  --carousel-bg: var(--card);
  --carousel-arrow-bg: var(--surface-1);
  --carousel-arrow-color: var(--text);
  --carousel-arrow-hover-bg: var(--surface-2);
  --carousel-arrow-hover-color: var(--text);
  --carousel-nav-bg: var(--surface-1);
  --carousel-nav-color: var(--muted);
  --carousel-nav-hover: #9ca3af;
  --carousel-nav-active: var(--accent);
  --carousel-focus-color: var(--accent-2);
}

nav-list {
  --nav-list-bg: var(--card);
  --nav-list-border-color: var(--line);
  --nav-list-selected-border-color: var(--accent);
  --nav-list-selected-bg: var(--surface-2);
  --nav-list-hover-bg: var(--surface-2);
  --nav-list-selected-color: var(--text);
}

theme-toggle {
  --theme-toggle-bg: var(--card);
  --theme-toggle-icon-color: var(--muted);
  --theme-toggle-hover-bg: var(--surface-2);
  --theme-toggle-active-bg: var(--surface-1);
  --theme-toggle-active-color: var(--text);
  --theme-toggle-dark-bg: var(--card);
  --theme-toggle-dark-border: var(--line);
  --theme-toggle-dark-icon-color: var(--muted);
  --theme-toggle-dark-active-bg: var(--surface-1);
  --theme-toggle-dark-active-color: var(--text);
  --theme-toggle-dark-hover-bg: var(--surface-2);
}

qr-code {
  --qr-fg: #0f1117;
  --qr-bg: #f3f6ff;
}

click-clock {
  --clock-color: var(--text);
  --clock-bg: var(--card);
  --clock-muted-color: var(--muted);
}

historical-line {
  --title-color: var(--text);
  --border-color: var(--line);
  --year-bg: var(--surface-1);
}

circle-steps {
  --steps-muted: var(--muted);
  --steps-text: var(--text);
  --steps-pending: var(--surface-2);
}

rich-inputfile {
  --input-border: var(--line);
  --input-border-focus: var(--accent-2);
  --input-bg: var(--card);
  --input-label-color: var(--text);
  --input-hover-bg: var(--surface-2);
  --input-drag-bg: var(--accent-soft);
  --input-disabled-bg: var(--surface-1);
  --input-success-border: #22c55e;
  --input-success-bg: rgba(34, 197, 94, 0.12);
  --input-icon-color: #94a3b8;
  --input-text-color: var(--muted);
  --input-accent-color: var(--accent-2);
  --input-file-bg: var(--surface-1);
  --input-preview-bg: var(--surface-1);
  --input-file-name-color: var(--text);
  --input-file-size-color: var(--muted);
  --input-error-color: #ef4444;
  --input-hint-color: var(--muted);
}

data-card {
  --data-card-bg: var(--card);
  --data-card-border-color: var(--line);
  --data-card-title-color: var(--text);
  --data-card-desc-color: var(--muted);
  --data-card-info-bg: var(--overlay-bg);
  --data-card-info-close-bg: var(--surface-2);
  --data-card-info-close-color: var(--text);
  --data-card-info-close-hover-bg: var(--surface-1);
  --data-card-info-text: var(--text);
  --data-card-loading-color: var(--muted);
  --data-card-info-trigger-hover: var(--accent);
}

app-modal {
  --app-modal-bg: var(--card);
  --app-modal-body-color: var(--text);
  --app-modal-standalone-bg: rgba(255, 176, 0, 0.35);
  --app-modal-standalone-color: #111;
  --app-modal-standalone-hover-bg: rgba(255, 176, 0, 0.6);
}
JS (js)
document.querySelectorAll('.footer-year').forEach(el => el.textContent = new Date().getFullYear());
  

    import "https://esm.sh/@manufosela/behaviour-accordion";

    // Basic event listener
    const basic = document.getElementById('basic');
    const basicOutput = document.getElementById('basicOutput');
    basic.addEventListener('item-toggle', (e) => {
      basicOutput.textContent = `Item ${e.detail.index} ${e.detail.expanded ? 'expanded' : 'collapsed'}. Open: [${e.detail.expandedItems.join(', ')}]`;
    });
  

  import '../../theme-toggle/src/theme-toggle.js';

  const root = document.documentElement;
  root.classList.add('dark');

  const toggle = document.querySelector('theme-toggle');
  if (toggle) {
    toggle.theme = root.classList.contains('dark') ? 'dark' : 'light';
    toggle.addEventListener('theme-changed', (event) => {
      const theme = event.detail?.theme;
      if (!theme) return;
      root.classList.toggle('dark', theme === 'dark');
    });
  }