Skip to content

eduardocruzpalacios/edu-webcomponents

Repository files navigation

🎨 Edu Web Components Library

npm version License: MIT Built with Lit

A modern, lightweight collection of reusable web components built with Lit following open-wc recommendations.

πŸ“– View Live Demo & Documentation

✨ Features

  • πŸš€ Lightweight - Built with Lit for minimal bundle size
  • β™Ώ Accessible - ARIA-compliant components with keyboard support
  • 🎯 Framework-agnostic - Works with any JavaScript framework or vanilla JS
  • 🎨 Customizable - CSS custom properties for easy theming
  • πŸŒ“ Dark mode support - Automatic theme switching with @media (prefers-color-scheme: dark)
  • πŸ“¦ Tree-shakeable - Import only what you need
  • βœ… Well-tested - Comprehensive test coverage

πŸ“¦ Installation

npm install edu-webcomponents

πŸš€ Quick Start

Import all components:

<script type="module">
  import 'edu-webcomponents/index.js';
</script>

<edu-button text="Click me"></edu-button>

Or import individual components:

<script type="module">
  import 'edu-webcomponents/src/edu-button/index.js';
</script>

<edu-button text="Click me"></edu-button>

πŸ“š Components

πŸ“’ Banner

A full-width notification banner for displaying important messages and alerts with multiple types and positioning options.

Properties:

  • type (String) - Banner type: 'info', 'success', 'warning', 'error', or 'neutral' (default: 'info')
  • message (String) - Banner message content (default: '')
  • dismissible (Boolean) - Shows close button to dismiss the banner (default: false)
  • position (String) - Position variant: 'static', 'sticky', or 'fixed' (default: 'static')
  • icon (String) - Custom icon (uses default icon per type if not provided)
  • aria-label (String) - Accessibility label

Accessibility:

  • Uses role="alert" for immediate screen reader announcements
  • Customizable ARIA labels for context
  • Keyboard-accessible close button with visible focus indicators
  • Semantic color choices with sufficient contrast ratios
  • Full dark mode support

Usage:

<!-- Basic info banner -->
<edu-banner 
  type="info" 
  message="This is an informational message">
</edu-banner>

<!-- Success notification -->
<edu-banner 
  type="success" 
  message="Your changes have been saved successfully!">
</edu-banner>

<!-- Warning with dismiss button -->
<edu-banner 
  type="warning" 
  message="Your session will expire in 5 minutes" 
  dismissible>
</edu-banner>

<!-- Error banner -->
<edu-banner 
  type="error" 
  message="Unable to process your request. Please try again.">
</edu-banner>

<!-- Sticky banner (sticks to top when scrolling) -->
<edu-banner 
  type="info" 
  message="New features available!" 
  position="sticky" 
  dismissible>
</edu-banner>

<!-- Fixed banner (always at top of viewport) -->
<edu-banner 
  type="warning" 
  message="Scheduled maintenance tonight at 10 PM" 
  position="fixed">
</edu-banner>

<!-- Custom icon -->
<edu-banner 
  type="success" 
  message="Achievement unlocked!" 
  icon="πŸ†">
</edu-banner>

JavaScript:

import { EduBanner } from 'edu-webcomponents';

const banner = document.querySelector('edu-banner');

// Listen for close event
banner.addEventListener('banner-close', () => {
  console.log('Banner dismissed');
});

// Programmatically update banner
banner.message = 'Updated message';
banner.type = 'error';

🍞 Toast

A lightweight toast notification for brief status messages, with positioning, auto-hide, and dismissal options.

Properties:

  • message (String) - Toast message content (default: '')
  • type (String) - Toast type: 'info', 'success', 'warning', 'error', or 'neutral' (default: 'info')
  • duration (Number) - Auto-hide duration in ms (0 disables auto-hide) (default: 3000)
  • open (Boolean) - Shows or hides the toast (default: false)
  • dismissible (Boolean) - Shows close button (default: false)
  • position (String) - Position: 'top-right', 'top-left', 'bottom-right', 'bottom-left' (default: 'top-right')
  • aria-label (String) - Accessibility label

Accessibility:

  • Uses role="status" (or role="alert" for error) with aria-live for announcements
  • Customizable ARIA labels for context
  • Keyboard-accessible close button with visible focus indicators
  • Semantic color choices with sufficient contrast ratios
  • Full dark mode support

Usage:

<!-- Success toast (auto-hide in 3s) -->
<edu-toast
  type="success"
  message="Changes saved"
  duration="3000"
  open
  dismissible
></edu-toast>

<!-- Error toast (manual dismiss) -->
<edu-toast
  type="error"
  message="Something went wrong"
  duration="0"
  open
  dismissible
  position="bottom-left"
></edu-toast>

JavaScript:

import { EduToast } from 'edu-webcomponents';

const toast = document.querySelector('edu-toast');

toast.message = 'Saved!';
toast.type = 'success';
toast.duration = 3000;
toast.show();

🏷️ Badge

A small status indicator or label component perfect for displaying counts, categories, or status information.

Properties:

  • text (String) - Badge text content (default: '')
  • variant (String) - Color variant: 'default', 'primary', 'success', 'warning', 'error', or 'info' (default: 'default')
  • size (String) - Size variant: 'small', 'medium', or 'large' (default: 'medium')
  • aria-label (String) - Accessibility label
  • aria-live (String) - Announces dynamic changes to screen readers: 'polite' or 'assertive'
  • decorative (Boolean) - Marks badge as decorative (hidden from screen readers)

Accessibility:

  • Uses role="status" for screen reader announcements (non-decorative badges)
  • Supports aria-live attribute for dynamic content announcements
  • Automatically adds aria-atomic="true" when aria-live is set
  • Decorative mode (decorative property) hides badge from screen readers with aria-hidden="true"
  • Customizable ARIA labels for better context
  • Semantic color choices with sufficient contrast ratios
  • Full dark mode support with optimized color schemes

Usage:

<!-- Basic badge -->
<edu-badge text="New"></edu-badge>

<!-- Colored variants -->
<edu-badge text="Active" variant="success"></edu-badge>
<edu-badge text="Pending" variant="warning"></edu-badge>
<edu-badge text="Error" variant="error"></edu-badge>
<edu-badge text="Info" variant="info"></edu-badge>
<edu-badge text="Primary" variant="primary"></edu-badge>

<!-- Different sizes -->
<edu-badge text="Small" size="small" variant="primary"></edu-badge>
<edu-badge text="Medium" size="medium" variant="primary"></edu-badge>
<edu-badge text="Large" size="large" variant="primary"></edu-badge>

<!-- Notification count with live updates -->
<span>Messages 
  <edu-badge 
    text="5" 
    variant="primary" 
    size="small"
    aria-live="polite"
    aria-label="5 unread messages">
  </edu-badge>
</span>

<!-- Decorative badge (category tag) -->
<edu-badge text="JavaScript" variant="info" decorative></edu-badge>

JavaScript:

import { EduBadge } from 'edu-webcomponents';

const badge = document.querySelector('edu-badge');
badge.text = '10';
badge.variant = 'error';

πŸ”˜ Button

A customizable button component with hover effects and disabled state.

Properties:

  • text (String) - Button text content (default: 'Default text')
  • type (String) - Button type attribute (default: 'button')
  • disabled (Boolean) - Whether the button is disabled (default: false)
  • aria-label (String) - Accessibility label

Accessibility:

  • WCAG-compliant touch targets (44Γ—44px minimum)
  • Clear focus indicators with focus-visible
  • Proper ARIA labels and disabled state
  • Keyboard accessible

Usage:

<!-- Basic button -->
<edu-button text="Click me"></edu-button>

<!-- Disabled button -->
<edu-button text="Disabled" disabled></edu-button>

<!-- Submit button with aria-label -->
<edu-button 
  text="Submit Form" 
  type="submit" 
  aria-label="Submit the form">
</edu-button>

JavaScript:

import { EduButton } from 'edu-webcomponents';

const button = document.querySelector('edu-button');
button.addEventListener('click', () => {
  console.log('Button clicked!');
});

βž– Divider

A horizontal divider to visually separate content sections.

Properties:

  • label (String) - Optional text label displayed in the center (default: '')

Accessibility:

  • Uses semantic separator role with aria-orientation
  • Decorative visual elements hidden from screen readers
  • Optional label for additional context

Usage:

<!-- Simple divider -->
<edu-divider></edu-divider>

<!-- Divider with label -->
<edu-divider label="OR"></edu-divider>

⏳ Loading Spinner

An animated circular loading spinner with smooth rotation animation. Includes screen reader announcements and respects reduced motion preferences.

Properties:

  • label (String) - Screen reader label for the loading state (default: 'Loading')

Accessibility:

  • Announces loading state to screen readers with role="status"
  • Slows animation speed when prefers-reduced-motion is enabled
  • Customizable label for context-specific loading messages

Usage:

<!-- Default loading spinner -->
<edu-loading-spinner></edu-loading-spinner>

<!-- Custom accessibility label -->
<edu-loading-spinner label="Loading user data"></edu-loading-spinner>

πŸ“Š Progress Bar

A progress bar component to visualize task completion or loading progress.

Properties:

  • value (Number) - Current progress value (default: 0)
  • max (Number) - Maximum value (default: 100)
  • showLabel (Boolean) - Whether to display percentage label (default: false)
  • progressbarName (String) - Accessibility label (default: 'Progress bar')

Accessibility:

  • Full ARIA progressbar implementation with role="progressbar"
  • Dynamic aria-valuenow, aria-valuemin, and aria-valuemax attributes
  • Customizable labels for context-specific progress tracking

Usage:

<!-- Basic progress bar -->
<edu-progress-bar value="50" max="100"></edu-progress-bar>

<!-- With percentage label -->
<edu-progress-bar 
  value="75" 
  max="100" 
  showLabel>
</edu-progress-bar>

<!-- Custom accessibility label -->
<edu-progress-bar 
  value="3" 
  max="5" 
  showLabel 
  progressbarName="File upload progress">
</edu-progress-bar>

JavaScript:

const progressBar = document.querySelector('edu-progress-bar');
let progress = 0;

const interval = setInterval(() => {
  progress += 10;
  progressBar.value = progress;
  
  if (progress >= 100) {
    clearInterval(interval);
  }
}, 500);

πŸ’€ Skeleton Text

Animated skeleton loader for content placeholders during loading states. Includes screen reader announcements and respects reduced motion preferences.

Properties:

  • width (String) - Width of skeleton lines (default: '100%')
  • lineHeight (String) - Height of each line (default: '1em')
  • lines (Number) - Number of skeleton lines to display (default: 1)

Accessibility:

  • Announces loading state to screen readers with role="status"
  • Automatically pauses animation when prefers-reduced-motion is enabled

Usage:

<!-- Single line skeleton -->
<edu-skeleton-text></edu-skeleton-text>

<!-- Multiple lines -->
<edu-skeleton-text lines="3"></edu-skeleton-text>

<!-- Custom width and height -->
<edu-skeleton-text 
  width="60%" 
  lineHeight="1.5em" 
  lines="2">
</edu-skeleton-text>

Common Patterns:

<!-- Loading a card -->
<div class="card">
  <edu-skeleton-text width="80%" lineHeight="2em" lines="1"></edu-skeleton-text>
  <edu-skeleton-text width="100%" lines="3"></edu-skeleton-text>
</div>

<!-- Loading a profile -->
<div class="profile">
  <edu-skeleton-text width="150px" lineHeight="150px" lines="1"></edu-skeleton-text>
  <edu-skeleton-text width="200px" lines="2"></edu-skeleton-text>
</div>

πŸ’¬ Tooltip

A flexible tooltip component that displays contextual information on hover.

Properties:

  • text (String) - Tooltip content to display
  • position (String) - Tooltip position: 'top', 'bottom', 'left', or 'right' (default: 'bottom')

Accessibility:

  • Semantic tooltip role with proper ARIA relationships
  • Full keyboard support (hover, focus, Escape to dismiss)
  • Screen reader announcements via aria-describedby

Usage:

<!-- Bottom tooltip (default) -->
<edu-tooltip text="This is helpful information">
  <button>Hover me</button>
</edu-tooltip>

<!-- Top tooltip -->
<edu-tooltip text="Tooltip on top" position="top">
  <span>🎯 Target element</span>
</edu-tooltip>

<!-- Left and right tooltips -->
<edu-tooltip text="Left side tooltip" position="left">
  <edu-button text="Button with tooltip"></edu-button>
</edu-tooltip>

<edu-tooltip text="Right side tooltip" position="right">
  <a href="#">Link with tooltip</a>
</edu-tooltip>

🎨 Theming

Components use CSS custom properties for easy theming. Override these in your CSS:

:root {
  --primary: #1976d2;
  --primaryHover: #1565c0;
  --primaryForeground: #ffffff;
  --disabled: #bdbdbd;
  --greyLight: #e0e0e0;
  --greyDark: #757575;
  --blackLight: #424242;
  --skeletonBase: #e0e0e0;
  --skeletonHighlight: #f0f0f0;
}

πŸŒ“ Dark Mode Support

All components automatically support dark mode via @media (prefers-color-scheme: dark). When your operating system or browser is set to dark mode, the components will automatically adapt with optimized color schemes:

@media (prefers-color-scheme: dark) {
  :host {
    --primary: #4db8ff;
    --primaryHover: #66c2ff;
    --primaryForeground: #000;
    --blackLight: #e0e0e0;
    --greyLight: #3d3d3d;
    --greyDark: #666;
    --disabled: #555;
    --skeletonBase: #3d3d3d;
    --skeletonHighlight: #4d4d4d;
  }
}

No additional configuration required - dark mode works out of the box!

πŸ§ͺ Development

Local Demo

Run the local development server with live demo:

npm start

Opens a development server at http://localhost:8000 with the demo page.

Storybook

View components in Storybook with interactive controls:

npm run storybook

Build Storybook for deployment:

npm run build-storybook

Testing

Run tests once:

npm run test

Run tests in watch mode:

npm run test:watch

Linting & Formatting

Check for linting/formatting errors:

npm run lint

Auto-fix linting/formatting errors:

npm run format

πŸ“ Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Modern browsers with ES2015+ support

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ”— Links

πŸ™ Acknowledgments

Built with Lit and following open-wc recommendations for modern web component development.


Made with ❀️ by Eduardo de la Cruz Palacios

Packages

 
 
 

Contributors