Skip to content

Alert

Display contextual feedback messages for typical user actions with flexible alert components. Supports multiple variants, colors, icons, titles, and dismissible functionality.

Import

tsx
import { Alert, Pulse } from '@odyssee/components';

Basic Usage

Code Éditable
Résultat

Variants

The Alert component supports three variants: solid, soft, and bordered.

Code Éditable
Résultat

Colors

Alerts support multiple color schemes: primary, secondary, success, danger, warning, info, light, and dark.

Code Éditable
Résultat

With Title

Code Éditable
Résultat

With Icon

Code Éditable
Résultat

With List Content

Code Éditable
Résultat

Dismissible Alert

Make alerts dismissible with a close button.

tsx
const isVisible = Pulse.signal(true);

const dismissibleAlert = (
  <Alert 
    variant="solid" 
    color="success"
    dismissible={true}
    isVisible={isVisible}
    onDismiss={() => isVisible(false)}
  >
    File has been successfully uploaded.
  </Alert>
);

With Actions

Add action buttons to alerts.

tsx
const alertWithActions = (
  <Alert 
    variant="soft" 
    color="info"
    title="New software update"
  >
    <p>A new software update is available.</p>
    <div class="mt-3 flex gap-2">
      <button class="px-3 py-1 bg-blue-600 text-white rounded text-sm">
        Update now
      </button>
      <button class="px-3 py-1 text-gray-600 hover:bg-gray-100 rounded text-sm">
        Remind me later
      </button>
    </div>
  </Alert>
);

Reactive Visibility

Control alert visibility with Pulse signals.

tsx
const showAlert = Pulse.signal(false);

// Show alert after some action
const handleAction = () => {
  showAlert(true);
  
  // Auto-hide after 3 seconds
  setTimeout(() => {
    showAlert(false);
  }, 3000);
};

const reactiveAlert = (
  <Alert 
    variant="solid" 
    color="success"
    isVisible={showAlert}
  >
    Action completed successfully!
  </Alert>
);

Complete Example

Here's a comprehensive example with multiple features:

tsx
import { Alert, Button, Pulse } from '@odyssee/components';

const NotificationSystem = () => {
  const alerts = Pulse.signal<Array<{
    id: number;
    type: 'success' | 'error' | 'warning' | 'info';
    message: string;
  }>>([]);

  const addAlert = (type: string, message: string) => {
    const id = Date.now();
    alerts([...alerts(), { id, type, message }]);
    
    // Auto-dismiss after 5 seconds
    setTimeout(() => {
      removeAlert(id);
    }, 5000);
  };

  const removeAlert = (id: number) => {
    alerts(alerts().filter(alert => alert.id !== id));
  };

  const container = (
    <div class="space-y-3">
      {/* Action buttons */}
      <div class="flex gap-2">
        <Button 
          color="success" 
          size="sm"
          onClick={() => addAlert('success', 'Operation successful!')}
        >
          Show Success
        </Button>
        <Button 
          color="danger" 
          size="sm"
          onClick={() => addAlert('error', 'An error occurred!')}
        >
          Show Error
        </Button>
        <Button 
          color="warning" 
          size="sm"
          onClick={() => addAlert('warning', 'Warning message!')}
        >
          Show Warning
        </Button>
      </div>

      {/* Alerts container */}
      <div id="alerts-container" class="space-y-2"></div>
    </div>
  ) as Pulse.JSX.Element;

  // Reactive rendering of alerts
  Pulse.effect(() => {
    const alertsContainer = container.querySelector('#alerts-container');
    if (!alertsContainer) return;

    alertsContainer.innerHTML = '';
    
    alerts().forEach(alert => {
      const alertElement = Alert({
        variant: 'solid',
        color: alert.type === 'error' ? 'danger' : alert.type,
        dismissible: true,
        onDismiss: () => removeAlert(alert.id),
        children: alert.message
      });
      
      alertsContainer.appendChild(alertElement as Pulse.JSX.Element);
    });
  });

  return container;
};

Props

PropTypeDefaultDescription
variant"solid" | "soft" | "bordered""soft"Alert variant style
color"primary" | "secondary" | "success" | "danger" | "warning" | "info" | "light" | "dark""info"Alert color scheme
titlestring-Alert title text
iconstring-Icon to display (emoji or text)
dismissiblebooleanfalseShow dismiss button
isVisibleboolean | Signal<boolean>trueControl visibility
onDismiss() => void-Dismiss callback
childrenstring | HTMLElement | Array<string | HTMLElement>-Alert content
classNamestring-Additional CSS classes
idstring-HTML id attribute

Accessibility

The Alert component follows accessibility best practices:

  • ✅ Uses semantic HTML with proper role attributes
  • role="alert" for important messages
  • aria-live="polite" for non-critical alerts
  • ✅ Dismiss button has aria-label="Close"
  • ✅ Sufficient color contrast ratios
  • ✅ Keyboard navigation support

ARIA Attributes

tsx
const accessibleAlert = (
  <Alert
    color="danger"
    role="alert"
    aria-live="assertive"
  >
    Critical error message
  </Alert>
);

Best Practices

✅ Do

  • Use appropriate colors for context (danger for errors, success for completions)
  • Provide clear, concise messages
  • Use titles to summarize the alert content
  • Make alerts dismissible for non-critical messages
  • Auto-dismiss temporary notifications
tsx
// Good: Clear context and message
const goodAlert = (
  <Alert 
    color="success"
    title="Profile Updated"
    dismissible={true}
  >
    Your profile information has been saved successfully.
  </Alert>
);

❌ Don't

  • Don't use too many alerts at once
  • Don't make critical alerts dismissible
  • Don't use vague messages
  • Don't forget to handle dismissal in reactive apps
tsx
// Bad: Vague and no context
const badAlert = (
  <Alert color="info">
    Something happened.
  </Alert>
);

// Better: Clear and specific
const betterAlert = (
  <Alert 
    color="success"
    icon="✓"
    title="Upload Complete"
  >
    Your document "report.pdf" has been uploaded successfully.
  </Alert>
);

Use Cases

Form Validation Errors

tsx
const formErrors = Pulse.signal<string[]>([]);

Pulse.effect(() => {
  if (formErrors().length > 0) {
    const errorAlert = Alert({
      variant: 'soft',
      color: 'danger',
      title: 'Please fix the following errors:',
      children: (
        <ul class="list-disc ml-4 mt-2">
          {formErrors().map(error => <li>{error}</li>)}
        </ul>
      ) as Pulse.JSX.Element
    });
  }
});

Success Messages

tsx
const showSuccess = (message: string) => {
  const alert = Alert({
    variant: 'solid',
    color: 'success',
    icon: '✓',
    dismissible: true,
    children: message
  });
  
  document.getElementById('notifications')?.appendChild(
    alert as Pulse.JSX.Element
  );
};

Warning Notifications

tsx
const warningAlert = (
  <Alert 
    variant: 'bordered',
    color: 'warning',
    icon: '⚠️',
    title: 'Session Expiring Soon'
  >
    Your session will expire in 5 minutes. Please save your work.
  </Alert>
);

Styling & Theming

All alert styles use Tailwind CSS classes and support dark mode automatically.

Custom Styling

tsx
const customAlert = (
  <Alert 
    className="shadow-lg border-l-4"
    color="primary"
  >
    Custom styled alert
  </Alert>
);
  • Button - Add action buttons to alerts
  • Modal - For more prominent notifications
  • Badge - For inline status indicators

Version: 1.0.0
Last Updated: January 2025

Released under the MIT License.