Table Switch Buttons

Horizontal group of tab-like switch buttons for changing table/card content views. Each button displays an icon (left), count number, and descriptive label (right) in a wide horizontal layout. Designed for glassy app-shell context in Offer Edit and similar CRUD pages where users switch between different data tables (Units, Extras, Dates, Prices, Translations).

Default Active With Icons Glassy Only

📐 Context & Usage

Context: Glassy signed-in app pages (Offer Edit, Property Management).
Purpose: Switch between different content sections/tables without page reload (UI-only component).

In the application, these buttons map to URL parameters to control which table/content is displayed: ?tab=units, ?tab=offer_extras, ?tab=unit_extras, ?tab=dates, ?tab=prices, ?tab=translations.

🎯 Design Intent

Table Switch Buttons provide quick visual navigation between related data sections.

Not the same as Tabs: These are styled as individual button-like tiles with prominent counts, rather than traditional tab strips. They're designed to fit the glassy app-shell aesthetic.

1. Default Table Switch Buttons

Complete set of 6 switch buttons for Offer Edit page. Shows all possible sections with one button in active state. Each button displays an icon, count number, and descriptive label. Buttons wrap on smaller screens.

1.1 Glassy Layout Preview

Glassy Context (Signed-in App)

For use in app-shell pages with glassy background. One button is active (Rent Units).

1.2 Glassy Layout HTML Snippet

HTML
<div class="table-switch-buttons">
  <!-- Rent Units - Active -->
  <button class="table-switch-btn table-switch-btn--active" aria-current="page">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">2</div>
      <div class="table-switch-btn__label">Rent Units</div>
    </div>
  </button>

  <!-- Offer Extras -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">6</div>
      <div class="table-switch-btn__label">Offer Extras</div>
    </div>
  </button>

  <!-- Unit Extras -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">4</div>
      <div class="table-switch-btn__label">Unit Extras</div>
    </div>
  </button>

  <!-- Offer Dates -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">3</div>
      <div class="table-switch-btn__label">Offer Dates</div>
    </div>
  </button>

  <!-- Prices -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">2</div>
      <div class="table-switch-btn__label">Prices</div>
    </div>
  </button>

  <!-- Translations -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">2</div>
      <div class="table-switch-btn__label">Translations</div>
    </div>
  </button>
</div>

2. Individual Button States

Demonstrates different states for individual switch buttons: default, hover (CSS), active/selected, and focus (keyboard navigation).

2.1 Glassy Layout Preview

Glassy Context (Signed-in App)

Three buttons showing: Default, Active (with aria-current), and another Default. Hover over buttons to see hover state. Tab through to see focus state.

2.2 Glassy Layout HTML Snippet

HTML
<div class="table-switch-buttons">
  <!-- Default state -->
  <button class="table-switch-btn">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
        d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">2</div>
      <div class="table-switch-btn__label">Rent Units</div>
    </div>
  </button>

  <!-- Active state -->
  <button class="table-switch-btn table-switch-btn--active" aria-current="page">
    <svg class="table-switch-btn__icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
    </svg>
    <div class="table-switch-btn__content">
      <div class="table-switch-btn__count">6</div>
      <div class="table-switch-btn__label">Offer Extras</div>
    </div>
  </button>
</div>

Usage Guidelines

✅ Do

  • • Use in glassy app-shell context (Offer Edit, Property Management pages)
  • • Show meaningful count numbers that represent actual data
  • • Use Heroicons SVG inline for consistent icon styling
  • • Mark active button with aria-current="page" for accessibility
  • • Keep labels short and descriptive (1-3 words)
  • • Use button element for proper keyboard navigation
  • • Map to URL parameters in application logic (?tab=units)
  • • Allow wrapping on smaller screens (flexbox wrap)

❌ Don't

  • • Don't use on standard (non-glassy) pages - designed for app-shell only
  • • Don't show fake or placeholder counts - update dynamically from data
  • • Don't omit icons - visual identification is important for quick scanning
  • • Don't have more than one active button at a time
  • • Don't use for primary navigation - these are for content switching within a page
  • • Don't disable buttons - if a section has 0 items, show "0" instead
  • • Don't create custom variants - stick to the base component styling
  • • Don't use with too many buttons (>8) - consider alternative UI pattern

⚠️ Layering Contract

Table Switch Buttons styles are shown inline in this DS preview. In production, extract to a dedicated CSS file (e.g., /assets/css/table-switch-buttons.css) or include in app-shell styles. Do not re-style locally. If you need new variants or behavior, extend the Design System component definition instead of overriding in page CSS.

♿ Accessibility Requirements

  • Semantic HTML: Use <button> elements for proper keyboard navigation
  • Active state: Mark selected button with aria-current="page"
  • Focus visible: Clear focus outline (2px blue) for keyboard navigation
  • Color contrast: Meets WCAG AA standards on glassy background
  • Icon alternative: Count and label provide context, icon is supplementary
  • Keyboard navigation: Tab through buttons, Enter/Space to activate

🔧 Implementation Notes

  • CSS Location: Component styles shown inline for DS preview. In production, extract to dedicated CSS file.
  • Layout: Compact horizontal flexbox (icon left, content right) with 8px gap between icon and text. All buttons equal width, filling 100% of container.
  • Glassy styling: Uses semi-transparent backgrounds with backdrop-filter for glass effect
  • DS Tokens: Uses var(--spacing-*), var(--font-size-*), var(--radius-*) from design tokens
  • Colors: Uses DS glass text tokens: --color-text-glass-primary (count), --color-text-glass-secondary (icon), --color-text-glass-muted (label)
  • Icons: Heroicons inline SVG 28×28px (22×22px on mobile) with currentColor inheritance
  • Active state: Blue accent using --color-info for icon with semi-transparent blue background
  • Responsive: Flexbox with wrap, buttons use flex: 1 1 0 for equal width distribution
  • Application integration: In app code, handle button clicks to update URL param and show/hide corresponding tables

CSS Location

Table Switch Buttons component styles are currently inline in this DS preview:

/assets/ui/collections/table-switch-buttons.html (lines 18-145)

Production recommendation: Extract to /assets/css/table-switch-buttons.css or include in app-shell stylesheet.

Includes: Container flexbox layout, button horizontal layout (icon left, content right), icon/count/label structure with content wrapper, hover and focus states, active/selected state (blue accent), responsive behavior (mobile wrapping), and glassy background integration.

Dependencies: Uses DS design tokens from /assets/css/tokens.css (spacing, typography, border-radius variables).

Related Documentation