121
GitHub
Brand

AnimatedLogo

Reveals any inline SVG logo with accessible, reduced-motion-aware animation.

FrameworksAstro · React · Elements

Registry commandlumen add AnimatedLogo

InteractionNative markup

01

See it in context

Preview

Generic reveal
Sequenced layers
02

Copy a working example

Usage

astro
---
/* eslint-disable better-tailwindcss/no-unknown-classes */
import { AnimatedLogo, Button } from '@santi020k/lumen-astro'
---

<section class="animated-logo-demo" data-animated-logo-demo>
  <div class="animated-logo-demo__grid">
    <figure>
      <AnimatedLogo class="animated-logo-demo__lumen">
        <svg
          aria-labelledby="lumen-logo-title lumen-logo-description"
          role="img"
          viewBox="0 0 318 80"
          xmlns="http://www.w3.org/2000/svg"
        >
          <title id="lumen-logo-title">Lumen UI</title>
          <desc id="lumen-logo-description">The Lumen UI lowercase wordmark with a small lu monogram.</desc>
          <text
            fill="currentColor"
            font-family="ui-serif, Georgia, Cambria, serif"
            font-size="42"
            font-weight="700"
            x="8"
            y="51"
          >lu</text>
          <circle cx="69" cy="22" fill="#f59e0b" r="3.75"></circle>
          <path d="M90 19v42" stroke="currentColor" stroke-linecap="round" stroke-opacity="0.22" stroke-width="1.5"></path>
          <text
            fill="currentColor"
            font-family="ui-serif, Georgia, Cambria, serif"
            font-size="38"
            font-weight="700"
            x="112"
            y="51"
          >lumen</text>
          <text
            fill="hsl(var(--accent))"
            font-family="Inter, ui-sans-serif, system-ui, sans-serif"
            font-size="20"
            font-weight="850"
            x="238"
            y="51"
          >UI</text>
        </svg>
      </AnimatedLogo>
      <figcaption>Generic reveal</figcaption>
    </figure>

    <figure>
      <AnimatedLogo animation="sequence" class="animated-logo-demo__santi">
        <svg
          aria-label="Santi020k"
          role="img"
          viewBox="0 0 504 80"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g>
            <rect
              data-ui-logo-pop
              fill="#5a0fdb"
              height="80"
              rx="18"
              width="80"
            ></rect>
            <path
              d="M26 28 40 40 26 52"
              data-ui-logo-draw
              fill="none"
              stroke="#fff"
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="8"
              style="--ui-logo-delay: 300ms; --ui-logo-path-length: 60;"
            ></path>
            <line
              data-ui-logo-draw
              stroke="#fff"
              stroke-linecap="round"
              stroke-width="8"
              style="--ui-logo-delay: 500ms; --ui-logo-path-length: 60;"
              x1="48"
              x2="62"
              y1="52"
              y2="52"
            ></line>
          </g>
          <text
            data-ui-logo-reveal
            fill="currentColor"
            font-family="Inter, ui-sans-serif, system-ui, sans-serif"
            font-size="48"
            font-weight="800"
            letter-spacing="-0.04em"
            style="--ui-logo-delay: 700ms;"
            x="100"
            y="56"
          >
            Santi<tspan fill="#713bf7" font-weight="700" letter-spacing="-0.02em">020k</tspan>
          </text>
        </svg>
      </AnimatedLogo>
      <figcaption>Sequenced layers</figcaption>
    </figure>
  </div>

  <Button data-animated-logo-replay size="sm" variant="outline">
    Replay animation
  </Button>
</section>

<script>
  for (const demo of document.querySelectorAll('[data-animated-logo-demo]')) {
    const replayButton = demo.querySelector<HTMLButtonElement>('[data-animated-logo-replay]')

    replayButton?.addEventListener('click', () => {
      for (const logo of demo.querySelectorAll('[data-ui-animated-logo]')) {
        logo.replaceWith(logo.cloneNode(true))
      }
    })
  }
</script>

<style>
  .animated-logo-demo {
    display: grid;
    gap: 1.25rem;
    justify-items: start;
    width: 100%;
  }

  .animated-logo-demo__grid {
    display: grid;
    gap: 1rem;
    width: 100%;
  }

  figure {
    align-items: center;
    background: hsl(var(--surface-muted));
    border: 1px solid hsl(var(--line));
    border-radius: var(--ui-radius-lg);
    color: hsl(var(--ink));
    display: grid;
    gap: 1rem;
    justify-items: center;
    margin: 0;
    min-height: 12rem;
    padding: 1.5rem;
  }

  figcaption {
    color: hsl(var(--ink-muted));
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .animated-logo-demo__lumen {
    height: 4rem;
    max-width: 19rem;
  }

  .animated-logo-demo__santi {
    height: 4.5rem;
    max-width: 28rem;
    width: 100%;
  }

  @media (min-width: 48rem) {
    .animated-logo-demo__grid {
      grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    }
  }
</style>
---
/* eslint-disable better-tailwindcss/no-unknown-classes */
import { AnimatedLogo, Button } from '@santi020k/lumen-astro'
---

<section class="animated-logo-demo" data-animated-logo-demo>
  <div class="animated-logo-demo__grid">
    <figure>
      <AnimatedLogo class="animated-logo-demo__lumen">
        <svg
          aria-labelledby="lumen-logo-title lumen-logo-description"
          role="img"
          viewBox="0 0 318 80"
          xmlns="http://www.w3.org/2000/svg"
        >
          <title id="lumen-logo-title">Lumen UI</title>
          <desc id="lumen-logo-description">The Lumen UI lowercase wordmark with a small lu monogram.</desc>
          <text
            fill="currentColor"
            font-family="ui-serif, Georgia, Cambria, serif"
            font-size="42"
            font-weight="700"
            x="8"
            y="51"
          >lu</text>
          <circle cx="69" cy="22" fill="#f59e0b" r="3.75"></circle>
          <path d="M90 19v42" stroke="currentColor" stroke-linecap="round" stroke-opacity="0.22" stroke-width="1.5"></path>
          <text
            fill="currentColor"
            font-family="ui-serif, Georgia, Cambria, serif"
            font-size="38"
            font-weight="700"
            x="112"
            y="51"
          >lumen</text>
          <text
            fill="hsl(var(--accent))"
            font-family="Inter, ui-sans-serif, system-ui, sans-serif"
            font-size="20"
            font-weight="850"
            x="238"
            y="51"
          >UI</text>
        </svg>
      </AnimatedLogo>
      <figcaption>Generic reveal</figcaption>
    </figure>

    <figure>
      <AnimatedLogo animation="sequence" class="animated-logo-demo__santi">
        <svg
          aria-label="Santi020k"
          role="img"
          viewBox="0 0 504 80"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g>
            <rect
              data-ui-logo-pop
              fill="#5a0fdb"
              height="80"
              rx="18"
              width="80"
            ></rect>
            <path
              d="M26 28 40 40 26 52"
              data-ui-logo-draw
              fill="none"
              stroke="#fff"
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="8"
              style="--ui-logo-delay: 300ms; --ui-logo-path-length: 60;"
            ></path>
            <line
              data-ui-logo-draw
              stroke="#fff"
              stroke-linecap="round"
              stroke-width="8"
              style="--ui-logo-delay: 500ms; --ui-logo-path-length: 60;"
              x1="48"
              x2="62"
              y1="52"
              y2="52"
            ></line>
          </g>
          <text
            data-ui-logo-reveal
            fill="currentColor"
            font-family="Inter, ui-sans-serif, system-ui, sans-serif"
            font-size="48"
            font-weight="800"
            letter-spacing="-0.04em"
            style="--ui-logo-delay: 700ms;"
            x="100"
            y="56"
          >
            Santi<tspan fill="#713bf7" font-weight="700" letter-spacing="-0.02em">020k</tspan>
          </text>
        </svg>
      </AnimatedLogo>
      <figcaption>Sequenced layers</figcaption>
    </figure>
  </div>

  <Button data-animated-logo-replay size="sm" variant="outline">
    Replay animation
  </Button>
</section>

<script>
  for (const demo of document.querySelectorAll('[data-animated-logo-demo]')) {
    const replayButton = demo.querySelector<HTMLButtonElement>('[data-animated-logo-replay]')

    replayButton?.addEventListener('click', () => {
      for (const logo of demo.querySelectorAll('[data-ui-animated-logo]')) {
        logo.replaceWith(logo.cloneNode(true))
      }
    })
  }
</script>

<style>
  .animated-logo-demo {
    display: grid;
    gap: 1.25rem;
    justify-items: start;
    width: 100%;
  }

  .animated-logo-demo__grid {
    display: grid;
    gap: 1rem;
    width: 100%;
  }

  figure {
    align-items: center;
    background: hsl(var(--surface-muted));
    border: 1px solid hsl(var(--line));
    border-radius: var(--ui-radius-lg);
    color: hsl(var(--ink));
    display: grid;
    gap: 1rem;
    justify-items: center;
    margin: 0;
    min-height: 12rem;
    padding: 1.5rem;
  }

  figcaption {
    color: hsl(var(--ink-muted));
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  .animated-logo-demo__lumen {
    height: 4rem;
    max-width: 19rem;
  }

  .animated-logo-demo__santi {
    height: 4.5rem;
    max-width: 28rem;
    width: 100%;
  }

  @media (min-width: 48rem) {
    .animated-logo-demo__grid {
      grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    }
  }
</style>
03

Choose your target

Add this component

Choose the package for your runtime. All adapters share the Lumen stylesheet. Use the matching registry command when you want a local wrapper for that framework.

bash@santi020k/lumen-astro
pnpm add @santi020k/lumen-astro
pnpm add @santi020k/lumen-astro
bashAstro wrapper
lumen add AnimatedLogo
lumen add AnimatedLogo

API reference

Lumen-specific props and runtime attributes for the Astro primitive. React props follow the same names; Elements use equivalent kebab-case attributes where custom elements expose them.

AttributeValuesDefaultDescription
childreninline SVGrequiredWraps any inline SVG logo and applies the reveal animation without changing its artwork.
animation"reveal" | "sequence""reveal"Uses a whole-logo reveal, or enables opt-in pop, draw, and reveal hooks inside the SVG.
data-ui-logo-pop, data-ui-logo-draw, data-ui-logo-revealSVG attributes-Marks SVG layers for the matching effect when animation="sequence".
--ui-animated-logo-durationCSS time"700ms"Customizes the reveal duration.
--ui-animated-logo-delayCSS time"0ms"Delays the reveal for coordinated compositions.
class, classNamestring""Merges custom classes with the generated ui-* root classes.
...native attributesHTML attributes-Forwards standard attributes to the root element unless the component consumes them.