CoolFace
Apppublic

lerobot/robot-learning-tutorial

sourceHugging Faceupdated 1y agoView on Hugging Face
508likes
Glossary.astro337 linesDownload Raw Back to components
1---2interface Props {3  /** The word or term to define */4  term: string;5  /** The definition of the term */6  definition: string;7  /** Optional CSS class to apply to the term */8  class?: string;9  /** Optional style to apply to the term */10  style?: string;11  /** Tooltip position (top, bottom, left, right) */12  position?: "top" | "bottom" | "left" | "right";13  /** Delay before showing tooltip in ms */14  delay?: number;15  /** Disable tooltip on mobile */16  disableOnMobile?: boolean;17}18 19const {20  term,21  definition,22  class: className = "",23  style: inlineStyle = "",24  position = "top",25  delay = 300,26  disableOnMobile = false,27} = Astro.props as Props;28 29// Generate a unique ID for this component30const tooltipId = `glossary-${Math.random().toString(36).slice(2)}`;31---32 33<div class="glossary-container" data-glossary-container-id={tooltipId}>34  <span35    class={`glossary-term ${className}`}36    style={inlineStyle}37    data-glossary-term={term}38    data-glossary-definition={definition}39    data-glossary-position={position}40    data-glossary-delay={delay}41    data-glossary-disable-mobile={disableOnMobile}42    data-glossary-id={tooltipId}43    tabindex="0"44    role="button"45    aria-describedby={`${tooltipId}-tooltip`}46  >47    {term}48  </span>49 50  <div51    id={`${tooltipId}-tooltip`}52    class="glossary-tooltip"53    data-glossary-tooltip-id={tooltipId}54    data-position={position}55    role="tooltip"56    aria-hidden="true"57  >58    <div class="glossary-tooltip__content">59      <div class="glossary-tooltip__term">{term}</div>60      <div class="glossary-tooltip__definition">{definition}</div>61    </div>62    <div class="glossary-tooltip__arrow"></div>63  </div>64</div>65 66<script is:inline>67  // Global script for all Glossary tooltips68  if (!window.glossaryInitialized) {69    window.glossaryInitialized = true;70 71    function initAllGlossaryTooltips() {72      const glossaryTerms = document.querySelectorAll(".glossary-term");73 74      glossaryTerms.forEach((termElement) => {75        const tooltipElement =76          termElement.parentElement.querySelector(".glossary-tooltip");77 78        if (!tooltipElement) return;79 80        const term = termElement.getAttribute("data-glossary-term");81        const definition = termElement.getAttribute("data-glossary-definition");82 83        if (!term || !definition) return;84 85        // Fonction pour afficher le tooltip au niveau de la souris86        const showTooltip = (event) => {87          tooltipElement.style.display = "block";88          tooltipElement.style.opacity = "1";89          tooltipElement.style.position = "fixed";90          tooltipElement.style.top = event.clientY + 10 + "px";91          tooltipElement.style.left = event.clientX + 10 + "px";92          tooltipElement.style.zIndex = "9999";93          tooltipElement.style.pointerEvents = "none";94        };95 96        const hideTooltip = () => {97          tooltipElement.style.display = "none";98          tooltipElement.style.opacity = "0";99        };100 101        // Add events102        termElement.addEventListener("mouseenter", showTooltip);103        termElement.addEventListener("mouseleave", hideTooltip);104        termElement.addEventListener("mousemove", showTooltip);105      });106    }107 108    // Initialize when DOM is ready109    if (document.readyState === "loading") {110      document.addEventListener("DOMContentLoaded", initAllGlossaryTooltips);111    } else {112      initAllGlossaryTooltips();113    }114 115    // Observe DOM changes for new elements116    if (window.MutationObserver) {117      const observer = new MutationObserver((mutations) => {118        mutations.forEach((mutation) => {119          if (mutation.type === "childList") {120            mutation.addedNodes.forEach((node) => {121              if (122                node.nodeType === 1 &&123                node.querySelector &&124                node.querySelector(".glossary-term")125              ) {126                initAllGlossaryTooltips();127              }128            });129          }130        });131      });132 133      observer.observe(document.body, {134        childList: true,135        subtree: true,136      });137    }138  }139</script>140 141<style>142  /* ============================================================================ */143  /* Glossary Component */144  /* ============================================================================ */145 146  .glossary-container {147    display: inline;148    position: relative;149  }150 151  .glossary-term {152    color: var(--primary-color) !important;153    text-decoration: none !important;154    background: color-mix(in srgb, var(--primary-color) 15%, transparent);155    border-bottom: 1px dashed156      color-mix(in srgb, var(--primary-color) 100%, transparent) !important;157    cursor: help;158    transition: all 0.2s ease;159    border-radius: 3px;160    margin: 0 2px;161    padding: 4px 8px;162  }163 164  .glossary-term:hover,165  .glossary-term:focus {166    color: var(--primary-color-hover) !important;167    text-decoration: none !important;168    background: color-mix(in srgb, var(--primary-color) 20%, transparent);169    outline: none;170  }171 172  .glossary-term:focus {173    box-shadow: 0 0 0 2px174      color-mix(in srgb, var(--primary-color) 20%, transparent);175  }176 177  .glossary-tooltip {178    position: fixed;179    top: -9999px;180    left: -9999px;181    z-index: var(--z-tooltip);182    opacity: 0;183    transform: translateY(-4px);184    transition:185      opacity 0.2s ease,186      transform 0.2s ease;187    pointer-events: none;188    max-width: 300px;189    min-width: 200px;190  }191 192  .glossary-tooltip.is-visible {193    opacity: 1;194    transform: translateY(0);195    pointer-events: auto;196  }197 198  .glossary-tooltip__content {199    background: var(--surface-bg);200    border: 1px solid var(--border-color);201    border-radius: 8px;202    padding: 12px 16px;203    box-shadow:204      0 8px 32px rgba(0, 0, 0, 0.12),205      0 2px 8px rgba(0, 0, 0, 0.06);206    backdrop-filter: saturate(1.12) blur(8px);207  }208 209  .glossary-tooltip__term {210    font-weight: 600;211    font-size: 14px;212    color: var(--primary-color);213    margin-bottom: 4px;214    line-height: 1.3;215  }216 217  .glossary-tooltip__definition {218    font-size: 13px;219    color: var(--text-color);220    line-height: 1.4;221    margin: 0;222  }223 224  .glossary-tooltip__arrow {225    position: absolute;226    width: 0;227    height: 0;228    border: 6px solid transparent;229  }230 231  /* Arrow positioning */232  .glossary-tooltip[data-position="top"] .glossary-tooltip__arrow {233    bottom: -6px;234    left: 50%;235    transform: translateX(-50%);236    border-top-color: var(--border-color);237  }238 239  .glossary-tooltip[data-position="top"] .glossary-tooltip__arrow::after {240    content: "";241    position: absolute;242    top: -7px;243    left: -6px;244    border: 6px solid transparent;245    border-top-color: var(--surface-bg);246  }247 248  .glossary-tooltip[data-position="bottom"] .glossary-tooltip__arrow {249    top: -6px;250    left: 50%;251    transform: translateX(-50%);252    border-bottom-color: var(--border-color);253  }254 255  .glossary-tooltip[data-position="bottom"] .glossary-tooltip__arrow::after {256    content: "";257    position: absolute;258    top: -5px;259    left: -6px;260    border: 6px solid transparent;261    border-bottom-color: var(--surface-bg);262  }263 264  .glossary-tooltip[data-position="left"] .glossary-tooltip__arrow {265    right: -6px;266    top: 50%;267    transform: translateY(-50%);268    border-left-color: var(--border-color);269  }270 271  .glossary-tooltip[data-position="left"] .glossary-tooltip__arrow::after {272    content: "";273    position: absolute;274    top: -6px;275    left: -7px;276    border: 6px solid transparent;277    border-left-color: var(--surface-bg);278  }279 280  .glossary-tooltip[data-position="right"] .glossary-tooltip__arrow {281    left: -6px;282    top: 50%;283    transform: translateY(-50%);284    border-right-color: var(--border-color);285  }286 287  .glossary-tooltip[data-position="right"] .glossary-tooltip__arrow::after {288    content: "";289    position: absolute;290    top: -6px;291    left: -5px;292    border: 6px solid transparent;293    border-right-color: var(--surface-bg);294  }295 296  /* Mode sombre */297  [data-theme="dark"] .glossary-tooltip__content {298    background: var(--surface-bg);299    border-color: var(--border-color);300  }301 302  [data-theme="dark"] .glossary-tooltip__term {303    color: var(--primary-color);304  }305 306  [data-theme="dark"] .glossary-tooltip__definition {307    color: var(--text-color);308  }309 310  /* Responsive - hide on mobile if disabled */311  @media (max-width: 768px) {312    .glossary-term[data-glossary-disable-mobile="true"] {313      border-bottom: none;314      color: inherit;315      cursor: default;316    }317 318    .glossary-term[data-glossary-disable-mobile="true"]:hover,319    .glossary-term[data-glossary-disable-mobile="true"]:focus {320      background: none;321      color: inherit;322      border-bottom: none;323    }324  }325 326  /* Accessibility improvement */327  @media (prefers-reduced-motion: reduce) {328    .glossary-tooltip {329      transition: none;330    }331 332    .glossary-term {333      transition: none;334    }335  }336</style>337