Skip to main content
The link() function is a higher-order function that generates animated SVG badges for social media links with rotating arrow indicators.

Function Signature

export const link = (
  props: Props & { index: number }
) => (label: string) => string
This is a curried function that takes props first, then returns a function that accepts a label.

Type Definitions

Props

interface Props {
  width?: number;
  height: number;
  theme: "light" | "dark";
}

Parameters

First Call (Configuration)

height
number
required
The height of the SVG in pixels (typically 18-20px)
width
number
required
The width of the SVG in pixels (typically 100px)
theme
'light' | 'dark'
required
Color theme for the link badge
index
number
required
Numeric index used for staggered animation delays. Each link should have a unique index.

Second Call (Label)

label
string
required
The text to display (e.g., “LinkedIn”, “Twitter”, “Resume”)

What It Renders

The link() function renders a compact SVG badge with:
  • Link label: Displays the social platform or link name
  • Animated arrow: A rotating ”↗” arrow that spins periodically
  • Shine effect: The label text has an animated gradient shine
  • Staggered animations: Each link animates in with a delay based on its index

Real Usage Examples

From worker.ts:25-42:
// Resume link (index 0)
if (section === "link-resume") {
  const index = Number(searchParams.get("i")) ?? 0;
  content = link({ height: 18, width: 100, index, theme })("Resume");
}

// Website link (index 1)
else if (section === "link-website") {
  const index = Number(searchParams.get("i")) ?? 0;
  content = link({ height: 18, width: 100, index, theme })("Website");
}

// LinkedIn link (index 2)
else if (section === "link-linkedin") {
  const index = Number(searchParams.get("i")) ?? 0;
  content = link({ height: 18, width: 100, index, theme })("LinkedIn");
}

// Instagram link (slightly taller)
else if (section === "link-instagram") {
  const index = Number(searchParams.get("i")) ?? 0;
  content = link({ height: 20, width: 100, index, theme })("Instagram");
}

Usage in GitHub README

<a href="https://linkedin.com/in/username">
  <picture>
    <source media="(prefers-color-scheme: dark)" 
            srcset="https://readme.aidre.com/?section=link-linkedin&i=0&theme=dark">
    <source media="(prefers-color-scheme: light)" 
            srcset="https://readme.aidre.com/?section=link-linkedin&i=0&theme=light">
    <img alt="LinkedIn" src="https://readme.aidre.com/?section=link-linkedin&i=0">
  </picture>
</a>

Animation Details

Staggered Fade-In

Each link fades in with a delay based on its index:
.wrapper {
  --delay: calc(var(--animate-in-links-delay) + var(--i) * 1.2s);
}
With an index of 0, 1, 2, etc., links appear sequentially with 1.2s between each.

Rotating Arrow

The arrow rotates 360° periodically with randomized timing:
.link__arrow {
  animation-name: rotate;
  animation-duration: 5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-delay: ${Math.random() * 5}s; /* Random 0-5s delay */
}

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  10%, 100% {
    transform: rotate(360deg);
  }
}
The rotation happens in the first 10% of the animation cycle (0.5s), then stays rotated.

Shine Effect on Label

The label text uses the shared .shine class:
.link__label {
  animation-delay: ${Math.random() * 10}s; /* Random 0-10s delay */
}
Each link’s shine animation starts at a random time, creating visual variety.

Firefox Compatibility

Unlike other render functions, link badges are explicitly enabled in Firefox:
@-moz-document url-prefix() {
  /* Override default, allow this to show in FF */
  .wrapper {
    display: block;
  }
}
This ensures social media links remain visible even if the main contribution graph is hidden in Firefox.

Returns

Type: string (returned from inner function) Returns a complete SVG string with:
  • Fixed width and height
  • Animated arrow indicator
  • Shine effect on text
  • Theme-aware colors
  • Staggered entrance animation

Design Considerations

  1. Consistent sizing: Most links use 18px height and 100px width
  2. Index management: Ensure each link has a unique index for proper animation timing
  3. Label length: Keep labels short (6-10 characters) to fit within the 100px width
  4. Theme support: Links automatically adapt to light/dark themes