Anchor
A heading paired with an in-page anchor link that copies the URL fragment when clicked.
Renders a semantic heading with a visually-hidden anchor link revealed on hover/focus; respects prefers-reduced-motion when scrolling.
import { Anchor } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Anchor id="introduction" level={2}>
Introduction
</Anchor>
);
}
import { Anchor } from "@arshad-shah/cynosure-react";
<Anchor id="introduction" level={2}> Introduction</Anchor>The id is required — it is applied to the heading element so URL fragments can target it directly. Clicking the icon scrolls to the heading and copies the absolute URL (origin + path + #id) to the clipboard.
Variants
Section titled “Variants”Heading levels
Section titled “Heading levels”Use the level prop to render h1 through h6. Visual styling stays consistent; only the underlying tag changes for document outline.
import { Anchor } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<Anchor id="anchor-h1" level={1}>
Heading 1
</Anchor>
<Anchor id="anchor-h2" level={2}>
Heading 2
</Anchor>
<Anchor id="anchor-h3" level={3}>
Heading 3
</Anchor>
<Anchor id="anchor-h4" level={4}>
Heading 4
</Anchor>
</div>
);
}
Sticky-header offset
Section titled “Sticky-header offset”Pass offsetTop (a number in pixels or any CSS length string) when a fixed header would otherwise overlap the scrolled-into-view heading. The value is exposed as --cynosure-anchor-offset on the wrapper.
import { Anchor } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
<Anchor id="anchor-offset-px" offsetTop={80} level={2}>
Offset by 80 pixels
</Anchor>
<Anchor id="anchor-offset-rem" offsetTop="4rem" level={3}>
Offset by 4rem (matches a sticky header)
</Anchor>
</div>
);
}
Copy callback
Section titled “Copy callback”The onCopy handler fires after the URL fragment is written to the clipboard — useful for a toast confirmation.
import { Anchor } from '@arshad-shah/cynosure-react';
import { useState } from 'react';
export default function Example() {
const [copied, setCopied] = useState(false);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
<Anchor
id="anchor-on-copy"
level={2}
onCopy={() => {
setCopied(true);
window.setTimeout(() => setCopied(false), 1500);
}}
>
Click the link icon
</Anchor>
<span style={{ fontSize: '0.875rem', color: 'var(--cynosure-color-fg-muted)' }}>
{copied ? 'URL copied to clipboard.' : 'Hover the heading to reveal the link.'}
</span>
</div>
);
}
Accessibility
Section titled “Accessibility”- The wrapping element is a real
<h1>–<h6>so it appears in the document outline. - The reveal link carries a descriptive
aria-label("Copy link to section"by default); override via thelabelprop for localisation. - The link is keyboard-focusable; tabbing onto it reveals it just like a hover.
- When
prefers-reduced-motion: reduceis set the scroll behaviour falls back fromsmoothtoauto. - Clipboard failures are swallowed silently — the hash still updates so the URL remains shareable.
Recipes
Section titled “Recipes”- Pair with a top-of-page
BackToTopbutton so long-form pages get both forward (jump-to-section) and backward (return-to-top) affordances. - Use the
onCopycallback to surface a Toast confirming the URL was copied. - Set
offsetTopto the height of any sticky page header so the scrolled heading clears it. - Wrap inline
<Code>inside the heading children to render code-decorated section titles.