Clever Components Web Components Library

repository·master·Indexed 42 days ago

https://github.com/clevercloud/clever-components

A collection of Web Components developed by Clever Cloud, ranging from low-level UI atoms like <cc-button> and <cc-input-text> to high-level domain-specific components. Built with LitElement, the library includes features for internationalization (i18n), a high-performance relative datetime component, and a slot-based layout system for presentational components. Version 26.4.0.

Tokens
79.7K
Snippets
208
Records
335
Agent score
49%

What's inside Clever Components

  1. Understand the accessibility status of Clever Components

    master

    As of the current version, most components in the @clevercloud/components library cannot be considered fully accessible. While the project follows WCAG 2.1 principles and aims for high accessibility standards, many components still have pending issues.

    Key takeaways for developers:

    • Production Readiness: Only components explicitly marked as accessible should be considered production-ready for accessibility-critical applications.
    • Ongoing Improvements: Accessibility is treated as a continuous process. Components may receive updates to patch issues or improve usability even after release.
    • Transparency: When a component has known limitations, these are documented in its specific documentation with recommendations for mitigation.
    • Issue Tracking: You can monitor known accessibility gaps by checking the a11y label on the GitHub repository.
  2. What is a smart component?

    master

    Smart components are Web Components that wrap standard UI components to separate presentation from data logic. While UI components focus on rendering and user interaction, smart components manage the data layer automatically.

    Key capabilities of smart components:

    • Automatic Data Fetching: Fetches initial data upon mounting.
    • State Management: Handles loading and error states automatically.
    • Reactive UI: Updates the UI when data changes.
    • API Interaction: Executes API calls in response to user actions.
    • Event Emission: Emits events for state changes and API results (which can be used by components like cc-toaster for notifications).
  3. How `cc-toggle` implements group semantics via ARIA

    master

    The cc-toggle component (a group of radio buttons or checkboxes) has moved away from using the standard HTML <fieldset> and <legend> elements in favor of a more robust ARIA-based implementation. This change was made to allow for easier styling (such as displaying the legend inline) without the layout limitations and browser inconsistencies associated with the <legend> element.

    To maintain accessibility, the component uses role="group" on a container <div> and associates it with a label using aria-labelledby. This ensures that screen readers can still identify the group and announce its context when a user focuses on the inputs within the group.

    Implementation Pattern

    When building similar custom components or understanding the cc-toggle structure, use the following pattern to ensure accessibility:

    <div role="group" aria-labelledby="legend-id">
      <p id="legend-id">Our legend text</p>
      <!-- inputs and labels go here -->
    </div>
    <div role="group" aria-labelledby="legend">
      <p id="legend">Our legend</p>
      <!-- inputs and labels -->
    </div>
  4. Understand the input and textarea wrapper architecture

    master

    In @clevercloud/components, <input> and <textarea> elements are wrapped in a div.wrapper. This architectural decision was made to ensure consistent cross-browser behavior for padding and margin, specifically to match Firefox's behavior where margins and padding are not part of the scrollable zone (avoiding discrepancies in Chrome and Safari).

    By using a wrapper, the components achieve:

    • Consistent Styling: All styles, including :focus and :hover states, are applied to the div.wrapper rather than the raw input element.
    • Event Handling: Events can be listened to directly on the wrapper.
    • Simplified Auto-height: The wrapper simplifies the logic for computing auto-height in multiline <textarea> elements.
  5. Design pattern for presentational components in Clever Components

    master

    The project follows a pattern where "presentational" components (those that group other components using only HTML/CSS and minimal JavaScript) utilize the Web Components slot mechanism rather than an abstraction layer.

    This approach is used when:

    • A component groups other components.
    • There is no state or data linking between the grouped components.
    • The primary purpose is layout/arrangement.

    By using slots, consumers can add or remove parts of the layout without modifying the parent component and can interact with child component APIs (properties, attributes, and events) directly.

  6. Why use the datetime relative component?

    master

    The datetime relative component is designed to display dates as "humanized time ago" (e.g., "2 minutes ago") with a focus on minimal bundle size and high performance.

    Key characteristics include:

    • Small Footprint: Less than 1.5 KB (min+gzip), including English and French locales.
    • Auto-refresh: Automatically updates the displayed time every 10 seconds.
    • Accessibility/UX: Includes a title attribute containing the full human-readable date (using Intl.DateTimeFormat).
    • Standard-based: Leverages the native Intl.RelativeTimeFormat API where available, with a lightweight fallback for older browsers like Safari 12+.
    • Optimized Output: Provides short, concise strings and handles weeks, unlike some other lightweight libraries.
  7. How pricing components and smart containers work together

    master

    Pricing components in this library rely on a nested <cc-smart-container> architecture to manage shared state like zoneId and currency.

    The Hierarchy Model

    1. Global Context: A top-level <cc-smart-container> wraps the entire pricing implementation. This provides the apiConfig, zoneId, and currency to all child components.
    2. Product Context: Individual <cc-smart-container> elements wrap specific components like <cc-pricing-product> or <cc-pricing-product-consumption> to provide product-specific context (e.g., productId).
    3. Inheritance: Because <cc-smart-container> components inherit context from their parents, all pricing-related components (cc-pricing-product, cc-pricing-product-consumption, and cc-pricing-estimation) automatically receive the correct zoneId and currency to fetch the appropriate priceSystem data.

    Synchronization

    When a user changes the zoneId or currency (for example, via a dropdown in <cc-pricing-header>), the global <cc-smart-container> context is updated. This triggers all components that display prices to refresh their data. Redundant network calls are avoided because the /v4/price-system API response is cached.

    <cc-smart-container context='{
      "apiConfig": {
        "API_HOST": ""
      },
      "zoneId": "mtl",
      "currency": "USD"
    }'>
      <cc-pricing-page>
        <cc-pricing-header currencies="..." temporalities="..."></cc-pricing-header>
        
        <!-- Product specific context -->
        <cc-smart-container context="{ productId: 'php'}">
          <cc-pricing-product mode="runtime" action="add"></cc-pricing-product>
        </cc-smart-container>
    
        <cc-smart-container context="{ productId: 'redis-addon'}">
          <cc-pricing-product mode="addon" action="add"></cc-pricing-product>
        </cc-smart-container>
    
        <!-- Estimation component using global context -->
        <cc-pricing-estimation currencies="..." temporalities="..."></cc-pricing-estimation>
      </cc-pricing-page>
    </cc-smart-container>
  8. How to manage component states using the `state` property

    master

    To avoid 'impossible states' (such as a component being simultaneously in a loading and error state), Clever Cloud components use a single state object property instead of multiple independent boolean flags like error or loading.

    This state object must contain a type property that defines the current mutually exclusive state of the component. Common state types include:

    • loading: Initial data is being fetched.
    • loaded: Data has been successfully fetched and is ready for display.
    • error: An error occurred during data fetching.
    • saving: An async operation (like a form submission) is pending.

    By using a single state object, the component's API ensures that data is only accessible when the type is set to loaded, providing better type safety and preventing UI inconsistencies.

    // Example of the state object structure
    // The state type is a string that represents the state of the component
    
    // Loading state
    const loadingState = { type: 'loading' };
    
    // Error state
    const errorState = { type: 'error' };
    
    // Loaded state (includes the actual data)
    const loadedState = {
      type: 'loaded',
      avatar: 'https://example.com/avatar.png',
      name: 'John Doe'
    };
  9. How localization works in Clever Components

    master

    Localization is managed through a dedicated system that is agnostic to both the component implementation and your application's tech stack.

    Key characteristics of the localization system:

    • API Surface: Components use a simple i18n(key, params) function which accepts two arguments.
    • Application of changes: Users must reload the page to apply a language change.
    • Loading: Currently, translations cannot be loaded for a specific subset of components; the system loads the translation set globally.
  10. Implementation details of copy to clipboard in <cc-input-text>

    master

    The <cc-input-text> component implements a 'copy to clipboard' feature using the clipboard-copy library. This library provides a lightweight wrapper that attempts to use the modern navigator.clipboard.writeText() API and falls back to the legacy document.execCommand() method to ensure compatibility (specifically addressing issues in Safari 12+).

    UI/UX Behavior:

    • The feature is presented as an icon button aligned to the top right of the input field, regardless of the input's height.
    • Upon a successful click, the icon temporarily changes to a green tick for approximately one second to provide visual feedback, similar to the behavior seen in GitHub.
  11. How the icon system works (Rollup plugin and ES modules)

    master

    The icon system replaces the old new URL(..., import.meta.url) pattern with an ES module-based approach.

    1. Build Time: A Rollup plugin parses icon assets, optimizes them using SVGO, and transforms them into ES objects.
    2. Output: The plugin writes these into a valid ES module file (e.g., assets/icon-library.js).
    3. Usage: Developers import specific icons from this library. This enables tree-shaking, ensuring only the icons actually used in your application are included in your final bundle.
  12. How the toast notification system works

    master

    The toast system is composed of two Web Components designed to provide decoupled user feedback:

    1. <cc-toast>: The individual component that displays a specific message.
    2. <cc-toaster>: The container component that manages and displays multiple <cc-toast> elements.

    Lifecycle:

    • The <cc-toaster> displays a <cc-toast> when instructed.
    • The <cc-toast> automatically dispatches a cc-toast-dismiss event after a set duration, or when the user clicks the close button.
    • The <cc-toaster> listens for this event and removes the corresponding toast from the UI.

    This architecture allows you to use the notification system with any technology stack (React, Vue, jQuery, etc.) because it relies on standard Web Component APIs.

    <!-- The system requires a toaster element to be present in your DOM -->
    <cc-toaster></cc-toaster>