Documentation
Brand
AnimatedLogo
Reveals any inline SVG logo with accessible, reduced-motion-aware animation.
01
See it in context
Preview
02
Copy a working example
Usage
---
/* 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>import { AnimatedLogo, Button } from '@santi020k/lumen-react'
export const Example = () => (
<>
<section className="animated-logo-demo" data-animated-logo-demo>
<div className="animated-logo-demo__grid">
<figure>
<AnimatedLogo className="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" strokeWidth="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" className="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"
strokeWidth="8"
style={{ -UiLogoDelay: '300ms', -UiLogoPathLength: '60' }}
></path>
<line
data-ui-logo-draw
stroke="#fff"
stroke-linecap="round"
strokeWidth="8"
style={{ -UiLogoDelay: '500ms', -UiLogoPathLength: '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={{ -UiLogoDelay: '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>
</>
)import { AnimatedLogo, Button } from '@santi020k/lumen-react'
export const Example = () => (
<>
<section className="animated-logo-demo" data-animated-logo-demo>
<div className="animated-logo-demo__grid">
<figure>
<AnimatedLogo className="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" strokeWidth="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" className="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"
strokeWidth="8"
style={{ -UiLogoDelay: '300ms', -UiLogoPathLength: '60' }}
></path>
<line
data-ui-logo-draw
stroke="#fff"
stroke-linecap="round"
strokeWidth="8"
style={{ -UiLogoDelay: '500ms', -UiLogoPathLength: '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={{ -UiLogoDelay: '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>
</>
)<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<section class="animated-logo-demo" data-animated-logo-demo>
<div class="animated-logo-demo__grid">
<figure>
<lumen-animated-logo 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>
</lumen-animated-logo>
<figcaption>Generic reveal</figcaption>
</figure>
<figure>
<lumen-animated-logo 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>
</lumen-animated-logo>
<figcaption>Sequenced layers</figcaption>
</figure>
</div>
<lumen-button data-animated-logo-replay size="sm" variant="outline">
Replay animation
</lumen-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><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<section class="animated-logo-demo" data-animated-logo-demo>
<div class="animated-logo-demo__grid">
<figure>
<lumen-animated-logo 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>
</lumen-animated-logo>
<figcaption>Generic reveal</figcaption>
</figure>
<figure>
<lumen-animated-logo 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>
</lumen-animated-logo>
<figcaption>Sequenced layers</figcaption>
</figure>
</div>
<lumen-button data-animated-logo-replay size="sm" variant="outline">
Replay animation
</lumen-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.
pnpm add @santi020k/lumen-astropnpm add @santi020k/lumen-astrolumen add AnimatedLogolumen add AnimatedLogopnpm add @santi020k/lumen-reactpnpm add @santi020k/lumen-reactlumen add AnimatedLogo --target reactlumen add AnimatedLogo --target reactpnpm add @santi020k/lumen-elementspnpm add @santi020k/lumen-elementslumen add AnimatedLogo --target elementslumen add AnimatedLogo --target elementsAPI 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.
| Attribute | Values | Default | Description |
|---|---|---|---|
| children | inline SVG | required | Wraps 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-reveal | SVG attributes | - | Marks SVG layers for the matching effect when animation="sequence". |
| --ui-animated-logo-duration | CSS time | "700ms" | Customizes the reveal duration. |
| --ui-animated-logo-delay | CSS time | "0ms" | Delays the reveal for coordinated compositions. |
| class, className | string | "" | Merges custom classes with the generated ui-* root classes. |
| ...native attributes | HTML attributes | - | Forwards standard attributes to the root element unless the component consumes them. |