GitHub npm

Solid Buttons

Filled background with high contrast text

Primary Secondary Danger Warning Info Success Disabled Loading

Outlined Buttons

Transparent background with colored border, fills with subtle color on hover

Primary Secondary Danger Warning Info Success

Ghost Buttons

No border or background initially, shows subtle background on hover

Primary Secondary Danger Warning Info Success

Link Buttons

Text-only styling, changes color on hover like a link

Primary Secondary Danger Warning Info Success

Full Width

Full Width Button

Code Usage

Copy and paste the following code to use buttons in your project

  • click: Fired when the button is clicked

<!-- Solid Button -->
<base-button variant="solid-primary">Primary</base-button>
<base-button variant="solid-secondary">Secondary</base-button>
<base-button variant="solid-danger">Danger</base-button>

<!-- Outlined Button -->
<base-button variant="outlined-primary">Primary</base-button>

<!-- Ghost Button -->
<base-button variant="ghost-primary">Primary</base-button>

<!-- Link Button -->
<base-button variant="link-primary">Primary</base-button>

<!-- With States -->
<base-button variant="solid-primary" disabled>Disabled</base-button>
<base-button variant="solid-primary" loading>Loading</base-button>

<!-- Sizes -->
<base-button variant="solid-primary" size="sm">Small</base-button>
<base-button variant="solid-primary" size="md">Medium</base-button>
<base-button variant="solid-primary" size="lg">Large</base-button>

<!-- Full Width -->
<base-button variant="solid-primary" full-width>Full Width</base-button>

Inputs

Code Usage

Copy and paste the following code to use inputs in your project

  • input: Fired when the input value changes
  • focus: Fired when the input receives focus
  • blur: Fired when the input loses focus

<!-- Basic Input -->
<base-input
  label="Email"
  type="email"
  placeholder="Enter your email"
  size="md"
></base-input>

<!-- With Value -->
<base-input
  label="Website"
  type="url"
  value="https://example.com"
  size="md"
></base-input>

<!-- Required Field -->
<base-input
  label="Password"
  type="password"
  placeholder="Enter your password"
  required
  size="md"
></base-input>

<!-- With Hint -->
<base-input
  label="Phone"
  type="tel"
  placeholder="+1 (555) 000-0000"
  hint="We'll never share your phone number"
  size="md"
></base-input>

<!-- Error State -->
<base-input
  label="Username"
  type="text"
  error="This field is required"
  size="md"
></base-input>

<!-- Disabled -->
<base-input
  label="Disabled"
  type="text"
  value="Cannot edit this"
  disabled
  size="md"
></base-input>

Selects

Code Usage

Copy and paste the following code to use selects in your project

  • change: Fired when the input value changes

<!-- Basic Select -->
<base-select
  id="select-country"
  label="Country"
  placeholder="Select a country"
  size="md"
></base-select>

<!-- Searchable Select -->
<base-select
  id="select-searchable"
  label="Searchable Select"
  placeholder="Search for a fruit..."
  searchable
  size="md"
></base-select>

<!-- Required Field -->
<base-select
  id="select-required"
  label="Required Field"
  placeholder="Choose an option"
  required
  size="md"
></base-select>

<!-- With Hint -->
<base-select
  id="select-hint"
  label="With Hint"
  placeholder="Select a priority"
  hint="Choose the urgency level"
  size="md"
></base-select>

<!-- Error State -->
<base-select
  id="select-error"
  label="Error State"
  placeholder="Select an option"
  error="This field is required"
  size="md"
></base-select>

<!-- Disabled -->
<base-select
  id="select-disabled"
  label="Disabled"
  placeholder="Cannot select"
  disabled
  size="md"
></base-select>

Textareas

Code Usage

Copy and paste the following code to use textareas in your project

  • input: Fired when the input value changes
  • focus: Fired when the input receives focus
  • blur: Fired when the input loses focus

<!-- Basic Textarea -->
<base-textarea
  label="Description"
  placeholder="Enter a description..."
  size="md"
  rows="4"
></base-textarea>

<!-- With Hint -->
<base-textarea
  label="Comments"
  placeholder="Add your comments here..."
  hint="Maximum 500 characters"
  maxlength="500"
  size="md"
  rows="4"
></base-textarea>

<!-- Required Field -->
<base-textarea
  label="Required Field"
  placeholder="This field is required"
  required
  size="md"
  rows="4"
></base-textarea>

<!-- Error State -->
<base-textarea
  label="Error State"
  error="This field cannot be empty"
  size="md"
  rows="4"
></base-textarea>

<!-- Disabled -->
<base-textarea
  label="Disabled"
  value="This content cannot be edited"
  disabled
  size="md"
  rows="4"
></base-textarea>

<!-- Resizable -->
<base-textarea
  label="Both Resize"
  placeholder="Resize both ways"
  resize="both"
  size="md"
  rows="4"
></base-textarea>

Quantity Selects

Extra Small (xs)

Current value: 0

Small (sm)

Current value: 1

Medium (md) - Default

Current value: 5

Large (lg)

Current value: 10

Limited Range (0-10)

Current value: 5

Input Read-Only (buttons only)

Current value: 3

Code Usage

Copy and paste the following code to use quantity selects in your project

  • change: Fired when the input value changes

<!-- Basic Quantity Select -->
<quantity-select
  id="quantity-basic"
  value="0"
  min="0"
  max="99"
  size="md"
></quantity-select>

<!-- With Default Value -->
<quantity-select
  id="quantity-default"
  value="5"
  min="0"
  max="99"
  size="md"
></quantity-select>

<!-- Limited Range -->
<quantity-select
  id="quantity-limited"
  value="5"
  min="0"
  max="10"
  size="md"
></quantity-select>

<!-- Different Sizes -->
<quantity-select value="0" min="0" max="99" size="xs"></quantity-select>
<quantity-select value="0" min="0" max="99" size="sm"></quantity-select>
<quantity-select value="0" min="0" max="99" size="md"></quantity-select>
<quantity-select value="0" min="0" max="99" size="lg"></quantity-select>

<!-- Listening to Changes -->
<script>
const quantitySelect = document.getElementById('quantity-basic');
quantitySelect.addEventListener('quantity-change', (e) => {
  console.log('New quantity:', e.detail.value);
});
</script>

Drawers

Click buttons to open drawers. Drag down or click overlay to close.

Small Drawer Medium Drawer Large Drawer Drawer with Form

Code Usage

Copy and paste the following code to use drawers in your project

  • drawer-close: Emitted when the drawer is closed
  • drawer-open: Emitted when the drawer is opened

<!-- Button to Open Drawer -->
<base-button variant="solid-primary" onclick="document.getElementById('my-drawer').open()">
  Open Drawer
</base-button>

<!-- Drawer Component -->
<base-drawer id="my-drawer" size="md">
  <div style="padding: var(--space-4);">
    <h2>Drawer Title</h2>
    <p>Drawer content goes here</p>
    <base-button
      variant="solid-primary"
      onclick="document.getElementById('my-drawer').close()"
    >
      Close
    </base-button>
  </div>
</base-drawer>

<!-- Different Sizes -->
<base-drawer size="sm"></base-drawer> <!-- 320px -->
<base-drawer size="md"></base-drawer> <!-- 480px -->
<base-drawer size="lg"></base-drawer> <!-- 640px -->

<!-- Using JavaScript -->
<script>
const drawer = document.getElementById('my-drawer');

// Open drawer
drawer.open();

// Close drawer
drawer.close();

// Listen to events
drawer.addEventListener('drawer-open', () => {
  console.log('Drawer opened');
});

drawer.addEventListener('drawer-close', () => {
  console.log('Drawer closed');
});
</script>

Tab Controls

Try toggling the variant of the main tabs component on this page

Toggle Layout (Horizontal/Sidebar)

Code Usage

Copy and paste the following code to use tabs in your project

  • tab-change: Emitted when the active tab changes
  • Base Tab
    • tab-register: Emitted when a tab is registered to the base-tabs component
    • tab-badge-update: Emitted when a tab's badge is updated

<!-- Basic Tabs -->
<base-tabs variant="horizontal" aria-label="Example tabs">
  <base-tab id="tab1" label="Tab 1">
    <p>Content for tab 1</p>
  </base-tab>

  <base-tab id="tab2" label="Tab 2">
    <p>Content for tab 2</p>
  </base-tab>

  <base-tab id="tab3" label="Tab 3">
    <p>Content for tab 3</p>
  </base-tab>
</base-tabs>

<!-- Tabs with Icons -->
<base-tabs variant="horizontal">
  <base-tab
    id="home"
    label="Home"
    icon='<svg viewBox="0 0 24 24"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>'
  >
    <p>Home content</p>
  </base-tab>
</base-tabs>

<!-- Sidebar Variant -->
<base-tabs variant="sidebar">
  <base-tab id="settings" label="Settings">
    <p>Settings content</p>
  </base-tab>
</base-tabs>

<!-- Programmatic Control -->
<script>
const tabs = document.querySelector('base-tabs');

// Switch to specific tab
tabs.switchTab('tab2');

// Listen for tab changes
tabs.addEventListener('tab-change', (e) => {
  console.log('Active tab:', e.detail.activeTab);
});
</script>

Date Pickers

Time Pickers

DateTime Pickers

Code Usage

Copy and paste the following code to use date and time pickers in your project

  • change: Emitted when the value changes

<!-- Date Picker -->
<base-date-picker
  id="date-picker"
  label="Select Date"
  placeholder="Choose a date"
  size="md"
></base-date-picker>

<!-- Time Picker (12-hour) -->
<base-time-picker
  id="time-picker-12"
  label="Select Time"
  placeholder="Choose a time"
  format="12"
  size="md"
></base-time-picker>

<!-- Time Picker (24-hour) -->
<base-time-picker
  id="time-picker-24"
  label="Select Time"
  placeholder="Choose a time"
  format="24"
  size="md"
></base-time-picker>

<!-- DateTime Picker -->
<base-datetime-picker
  id="datetime-picker"
  label="Select Date and Time"
  placeholder="Choose date and time"
  format="12"
  size="md"
></base-datetime-picker>

<!-- With Hints and Required -->
<base-date-picker
  label="Appointment Date"
  placeholder="Select appointment date"
  hint="Choose your preferred date"
  required
  size="md"
></base-date-picker>

<!-- Get Values -->
<script>
const datePicker = document.getElementById('date-picker');
const timePicker = document.getElementById('time-picker-12');
const dateTimePicker = document.getElementById('datetime-picker');

// Get selected values
console.log('Date:', datePicker.value);
console.log('Time:', timePicker.value);
console.log('DateTime:', dateTimePicker.value);

// Listen for changes
datePicker.addEventListener('change', (e) => {
  console.log('Date changed:', e.target.value);
});
</script>

Auth Controls

Important: This playground uses mock-mode for demonstration. In production, you must implement /api/auth/* proxy endpoints.

The auth component requires your application to implement same-origin auth endpoints that proxy to your auth service. This ensures HttpOnly cookies work correctly for security.

Open Drawer (Mock Mode) Logout Refresh Tokens

Code Usage

Production Setup: Your application must implement /api/auth/login, /api/auth/logout, /api/auth/refresh, /api/auth/check-session, /api/auth/register, and /api/auth/reset-password endpoints that proxy to your auth service.

Session Check Endpoint: The /api/auth/check-session endpoint is automatically called when the auth-form component loads. It should check for valid HTTP-only cookies and return user data if a session exists, or 401 if no valid session. This allows the component to restore login state on page load.

<!-- Auth Form in Drawer (Production) -->
<base-drawer id="auth-drawer" size="sm">
  <auth-form
    id="auth-form"
    logo-url="https://example.com/logo.svg"
    oauth-domain="https://auth.example.com"
    oauth-region="us-east-1"
    oauth-user-pool-id="us-east-1_XXXXXXXXX"
    oauth-client-id="your-client-id"
    oauth-spa-domain="https://oauth.example.com/"
  ></auth-form>
</base-drawer>

<!-- For Static Sites/Demos (Mock Mode) -->
<auth-form mock-mode logo-url="logo.svg"></auth-form>

<!-- Button to Open Auth Drawer -->
<base-button
  variant="solid-primary"
  onclick="document.getElementById('auth-drawer').open()"
>
  Login
</base-button>

<!-- Auth Methods -->
<script>
const authForm = document.getElementById('auth-form');

// Handle authentication events
authForm.addEventListener('auth-success', (e) => {
  console.log('User authenticated:', e.detail);
  console.log('Access token:', e.detail.accessToken);
  console.log('ID token:', e.detail.idToken);
  console.log('Refresh token:', e.detail.refreshToken);
});

authForm.addEventListener('auth-error', (e) => {
  console.error('Auth error:', e.detail);
});

// Logout
authForm.logout();

// Refresh tokens
authForm.refreshTokens();

// Get current tokens
const tokens = authForm.getTokens();
</script>

Theming System

This component library uses CSS custom properties (variables) for theming. All components automatically adapt to the active theme through the BaseElement class.

Current Themes

  • Light - Clean, minimal light theme
  • Dark - Modern dark theme with high contrast
  • Retro - Vintage theme with warm colors and blocky shadows
  • Neo Tokyo - Cyberpunk-inspired theme with neon glows
  • Editorial Serif - Professional theme with serif typography
  • Tropical Clay - Warm, earthy theme with natural tones
  • Ocean - Cool, calming theme with blue tones

Theme Toggle

Ghost

Outlined

Solid

Fun Themes:

Creating Your Own Theme

Create a new theme by defining CSS custom properties. Here's a complete example:

/* Create a new theme in your CSS file */
[data-theme='ocean'] {
  /* Brand colors */
  --color-primary: #0077be;
  --color-primary-hover: #005a8e;
  --color-primary-light: #e6f3ff;
  --color-secondary: #00a896;
  --color-secondary-hover: #008577;

  /* Semantic colors */
  --color-success: #28a745;
  --color-warning: #ffa500;
  --color-error: #dc3545;
  --color-info: #17a2b8;

  /* Text colors */
  --color-text-primary: #1a1a2e;
  --color-text-secondary: #4a5568;
  --color-text-muted: #718096;
  --color-text-inverse: #ffffff;

  /* Background colors */
  --color-bg-primary: #f0f8ff;
  --color-bg-secondary: #e6f3ff;
  --color-bg-muted: #d9ecff;
  --color-bg-inverse-muted: #1a1a2e;
  --color-bg-overlay: rgba(26, 26, 46, 0.8);

  /* Border colors */
  --color-border: #b8d4e8;
  --color-border-hover: #99c2de;
  --color-border-focus: #0077be;

  /* Typography */
  --font-family-sans: 'Inter', system-ui, sans-serif;
  --font-family-mono: 'JetBrains Mono', monospace;

  /* Spacing (optional - override if needed) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;

  /* Border radius */
  --radius-sm: 0.125rem;
  --radius-base: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1rem;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-xs: 0 1px 2px 0 rgba(26, 26, 46, 0.05);
  --shadow-sm: 0 2px 4px -1px rgba(26, 26, 46, 0.1);
  --shadow-base: 0 4px 6px -1px rgba(26, 26, 46, 0.1);
  --shadow-md: 0 8px 12px -2px rgba(26, 26, 46, 0.12);
  --shadow-lg: 0 16px 24px -4px rgba(26, 26, 46, 0.15);
  --shadow-xl: 0 24px 40px -8px rgba(26, 26, 46, 0.18);
}

Using the Theme Toggle

Add the theme-toggle component to your application:

<!-- Basic usage with default light/dark themes -->
<theme-toggle size="md" variant="ghost"></theme-toggle>

<!-- Custom themes with custom icons -->
<script>
  const toggle = document.querySelector('theme-toggle');
  toggle.themes = [
    {
      theme: 'light',
      icon: `<svg viewBox="0 0 20 20" fill="currentColor" class="theme-icon">
        <path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/>
      </svg>`
    },
    {
      theme: 'dark',
      icon: `<svg viewBox="0 0 20 20" fill="currentColor" class="theme-icon">
        <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
      </svg>`
    },
    {
      theme: 'ocean',
      icon: `<svg viewBox="0 0 20 20" fill="currentColor" class="theme-icon">
        <path d="M10 18a8 8 0 100-16 8 8 0 000 16zM4.332 8.027a6.012 6.012 0 011.912-2.706C6.512 5.73 6.974 6 7.5 6A1.5 1.5 0 019 7.5V8a2 2 0 004 0 2 2 0 011.523-1.943A5.977 5.977 0 0116 10c0 .34-.028.675-.083 1H15a2 2 0 00-2 2v2.197A5.973 5.973 0 0110 16v-2a2 2 0 00-2-2 2 2 0 01-2-2 2 2 0 00-1.668-1.973z"/>
      </svg>`
    }
  ];
</script>

<!-- Sizes -->
<theme-toggle size="sm" variant="ghost"></theme-toggle>
<theme-toggle size="md" variant="ghost"></theme-toggle>
<theme-toggle size="lg" variant="ghost"></theme-toggle>

<!-- Variants -->
<theme-toggle size="md" variant="ghost"></theme-toggle>
<theme-toggle size="md" variant="outline"></theme-toggle>
<theme-toggle size="md" variant="solid"></theme-toggle>

Cards

Default Card

No border or shadow. Clean and minimal appearance.

Elevated Card

Has border and shadow for depth and separation.

Padding Variants

No Padding

Perfect for custom layouts or full-width content.

Small Padding

Compact spacing (var(--space-4))

Medium Padding

Default spacing (var(--space-6))

Large Padding

Generous spacing (var(--space-8))

Interactive Cards

Hoverable Card

Try hovering over me! The shadow increases on hover.

Click Me

Expandable Card

Hover to see the expand button appear in the top-right corner.

Complex Card Example

Product Card

Demonstrates a card with custom internal structure

$99.99 In Stock

This card uses padding="none" to create custom sections with individual padding and borders.

Add to Cart

Code Usage

Copy and paste the following code to use cards in your project

  • card-expanded: Emitted when the card is expanded
  • card-collapsed: Emitted when the card is collapsed

<!-- Basic Card -->
<base-card variant="default" padding="md">
  <h4>Card Title</h4>
  <p>Card content goes here</p>
</base-card>

<!-- Elevated Card -->
<base-card variant="elevated" padding="md">
  <h4>Elevated Card</h4>
  <p>Has border and shadow</p>
</base-card>

<!-- Padding Variants -->
<base-card variant="elevated" padding="none"></base-card>
<base-card variant="elevated" padding="sm"></base-card>
<base-card variant="elevated" padding="md"></base-card>
<base-card variant="elevated" padding="lg"></base-card>

<!-- Hoverable Card -->
<base-card variant="elevated" padding="md" hoverable>
  <h4>Hoverable Card</h4>
  <p>Hover effect on mouse over</p>
</base-card>

<!-- Expandable Card -->
<base-card variant="elevated" padding="md" expandable>
  <h4>Expandable Card</h4>
  <p>Can be expanded on hover</p>
</base-card>

<!-- Card with Custom Layout -->
<base-card variant="elevated" padding="none">
  <div style="padding: var(--space-6); border-bottom: 1px solid var(--color-border);">
    <h4>Header Section</h4>
  </div>
  <div style="padding: var(--space-6);">
    <p>Content section</p>
    <base-button variant="solid-primary">Action</base-button>
  </div>
</base-card>

Small Drawer

This is a small drawer (320px wide on desktop). Perfect for quick actions or notifications.

Close Drawer

Medium Drawer

This is a medium drawer (480px wide on desktop). Good for forms and detailed content.

Close Cancel

Large Drawer

This is a large drawer (640px wide on desktop). Ideal for complex forms or multi-step processes.

Example Content

Large drawers can contain extensive content like:

  • Multi-step wizards
  • Detailed forms
  • Rich media content
  • Settings panels
Got it!

Contact Form

Send Message Cancel