Filled background with high contrast text
Transparent background with colored border, fills with subtle color on hover
No border or background initially, shows subtle background on hover
Text-only styling, changes color on hover like a link
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>
Copy and paste the following code to use inputs in your project
input: Fired when the input value changesfocus: Fired when the input receives focusblur: 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>
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>
Copy and paste the following code to use textareas in your project
input: Fired when the input value changesfocus: Fired when the input receives focusblur: 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>
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
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>
Click buttons to open drawers. Drag down or click overlay to close.
Copy and paste the following code to use drawers in your project
drawer-close: Emitted when the drawer is closeddrawer-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>
Click the buttons to check out the different toast variants.
Click buttons to show toasts in different screen positions
Click buttons to show toasts with different durations
Copy and paste the following code to use toasts in your project
toast-shown: Emitted when the toast is showntoast-hidden: Emitted when the toast is hidden<!-- Basic Toast -->
<base-button id="show-toast" variant="outlined-primary">
Show Toast
</base-button>
<base-toast id="demo-toast">
This is a toast message!
</base-toast>
<!-- Toast Variants -->
<base-toast id="primary-toast" variant="primary">Primary toast</base-toast>
<base-toast id="success-toast" variant="success">Success toast</base-toast>
<base-toast id="warning-toast" variant="warning">Warning toast</base-toast>
<base-toast id="danger-toast" variant="danger">Danger toast</base-toast>
<base-toast id="info-toast" variant="info">Info toast</base-toast>
<!-- Toast Positions -->
<base-toast id="top-left-toast" position="top-left">Top Left</base-toast>
<base-toast id="top-center-toast" position="top-center">Top Center</base-toast>
<base-toast id="top-right-toast" position="top-right">Top Right</base-toast>
<base-toast id="bottom-left-toast" position="bottom-left">Bottom Left</base-toast>
<base-toast id="bottom-center-toast" position="bottom-center">Bottom Center</base-toast>
<base-toast id="bottom-right-toast" position="bottom-right">Bottom Right</base-toast>
<!-- Toast Durations -->
<base-toast id="manual-toast" dismiss="manual">Manual dismiss only</base-toast>
<base-toast id="quick-toast" dismiss="500ms">500ms duration</base-toast>
<base-toast id="short-toast" dismiss="2s">2 second duration</base-toast>
<base-toast id="long-toast" dismiss="10s">10 second duration</base-toast>
<!-- Using JavaScript -->
<script>
// Show a toast
const toast = document.getElementById('demo-toast');
const showButton = document.getElementById('show-toast');
showButton.addEventListener('click', () => {
toast.show();
});
// Manually hide a toast
toast.hide();
// Listen to toast events
toast.addEventListener('toast-shown', () => {
console.log('Toast is now visible');
});
toast.addEventListener('toast-hidden', () => {
console.log('Toast has been hidden');
});
</script>
Try toggling the variant of the main tabs component on this page
Copy and paste the following code to use tabs in your project
tab-change: Emitted when the active tab changestab-register: Emitted when a tab is registered to the base-tabs componenttab-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>
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>
No border or shadow. Clean and minimal appearance.
Has border and shadow for depth and separation.
Perfect for custom layouts or full-width content.
Compact spacing (var(--space-4))
Default spacing (var(--space-6))
Generous spacing (var(--space-8))
Try hovering over me! The shadow increases on hover.
Hover to see the expand button appear in the top-right corner.
Demonstrates a card with custom internal structure
This card uses padding="none" to create custom sections with individual padding and borders.
Copy and paste the following code to use cards in your project
card-expanded: Emitted when the card is expandedcard-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>
This component library uses CSS custom properties (variables) for theming. All components automatically adapt to the active theme through the BaseElement class.
Fun Themes:
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);
}
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>
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.
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>
This is a small drawer (320px wide on desktop). Perfect for quick actions or notifications.
This is a medium drawer (480px wide on desktop). Good for forms and detailed content.
This is a large drawer (640px wide on desktop). Ideal for complex forms or multi-step processes.
Large drawers can contain extensive content like: