Corncob

Corncob Design Language

Corncob is a framework-neutral design language built with tokens, CSS, and plain JavaScript behavior.

Expandables

Expandables allow hiding and showing content, reducing UI clutter by letting users reveal additional details on demand. Common patterns include accordions, collapsible panels, dropdowns, and tree views.

Corncob’s <corn-expandable> web component builds on native <details>/<summary> elements. This provides excellent accessibility and performance—no JavaScript needed for basic expand/collapse.

However, native elements lack smooth height transition animations. <corn-expandable> adds these via JavaScript-driven CSS class toggling on open/close.

Usage

The component requires:

  • <corn-expandable class="corn-expandable">
  • Inside: <details slot="details">
    • <summary class="corn-expandable-button"> (header + icon)
    • Content in <div class="corn-expandable--content">

Corncob’s CSS handles the expand/collapse animation by toggling classes on the content div when the details element opens/closes.

Default (Closed)

Summary

heading

content
<corn-expandable class="corn-expandable">
  <details slot="details">
    <summary class="corn-expandable-button">
      Summary
      <ChevronRight class="corn-icon" />
    </summary>
    <div class="corn-expandable--content">
      <div>
        <h3>heading</h3>
        <div>content</div>
      </div>
    </div>
  </details>
</corn-expandable>

Open by Default

Add open attribute to <corn-expandable>.

Summary

heading

content
<corn-expandable class="corn-expandable" open>
  <details slot="details">
    <summary class="corn-expandable-button">
      Summary
      <ChevronRight class="corn-icon" />
    </summary>
    <div class="corn-expandable--content">
      <div>
        <h3>heading</h3>
        <div>content</div>
      </div>
    </div>
  </details>
</corn-expandable>

Accordion (Single Open)

Wrap multiple in <div class="corn-accordion">. Add name="corn-single" to each <details> for mutual exclusivity, same as native details behavior.

Summary
details
Summary 2
details 2
Summary 3
details
  <div class="corn-accordion">
    <corn-expandable class="corn-expandable">
      <details slot="details" name="corn-single">
        <summary class="corn-expandable-button">
          Summary
          <ChevronRight class="corn-icon" />
        </summary>
        <div class="corn-expandable--content">details</div>
      </details>
    </corn-expandable>
    <corn-expandable class="corn-expandable">
      <details slot="details" name="corn-single">
        <summary class="corn-expandable-button">
          Summary 2
          <ChevronRight class="corn-icon" />
        </summary>
        <div class="corn-expandable--content">details 2</div>
      </details>
    </corn-expandable>
    <corn-expandable class="corn-expandable">
      <details slot="details" name="corn-single">
        <summary class="corn-expandable-button">
          Summary 3
          <ChevronRight class="corn-icon" />
        </summary>
        <div class="corn-expandable--content">details</div>
      </details>
    </corn-expandable>
  </div>

Nested / Tree View

Supports recursion. Add corn-tree-view class for styling.

Summary
Summary 2
More details
  <corn-expandable class="corn-expandable corn-tree-view">
    <details slot="details">
      <summary class="corn-expandable-button">
        <ChevronRight class="corn-icon" />
        Summary
      </summary>
      <div class="corn-expandable--content">
        <corn-expandable class="corn-expandable corn-tree-view">
          <details slot="details">
            <summary class="corn-expandable-button">
              <ChevronRight class="corn-icon" />
              Summary 2
            </summary>
            <div class="corn-expandable--content">More details</div>
          </details>
        </corn-expandable>
      </div>
    </details>
  </corn-expandable>

Expandable Tokens

:root {
  --cc-expandable--border-radius: var(--cc-border--radius);
  --cc-expandable--border-width: var(--cc-border--width);
  --cc-expandable--border-style: var(--cc-border--style);
  --cc-expandable--border-color: rgb(from var(--cc-border--color) r g b / 21%);
  --cc-expandable--color: var(--cc-gray-90);
  --cc-expandable--color--hover: var(--cc-gray-100);
  --cc-expandable--color--active: var(--cc-black);
  --cc-expandable--focus-ring: var(--cc-form--item--focus-ring);
  --cc-expandable--icon--background: var(--cc-gray-20);
  --cc-expandable--icon--background--hover: var(--cc-gray-30);
  --cc-expandable--icon--background--active: transparent;
}