⚠️ Design system CSS not found. Check the path in cms/docs.config.js → designSystemPath, then re-run npm run docgen.

BD Cursor

Desktop custom cursor system

Website / BD Cursor
Download .md file
Open .md in new tab
On this page
  • Anatomy
  • Configuration
  • Basic usage
  • JavaScript
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product

BD Cursor renders one overlay element as every author-driven cursor: a text LABEL beside the native pointer, an icon BADGE, a two-colour GRAPHIC that replaces the OS pointer, and a click-feedback HALO. Authoring is pure data-cursor-* attributes; the engine is assets/js/bd-cursor.js with companion styles in bd-cursor.css. Desktop pointer devices only — the CSS gates everything behind a hover/fine-pointer media query, and reduced-motion visitors keep the OS cursor.


Anatomy

Axis Mechanism Example
Atom data-cursor-label / data-cursor-badge / data-cursor-graphic data-cursor-badge="play"
Glyph slots data-cursor-icon, data-cursor-icon-end data-cursor-icon="arrow-right"
Replace pointer data-cursor-replace (boolean; graphic always replaces) data-cursor-replace
Native carve-out data-cursor-native (boolean, wins over everything) data-cursor-native

The component consumes design-system tokens only through namespaced --bd-cursor-* tokens with literal fallbacks, so it works on pages without design-system.css.

Configuration

Define window.bdCursorConfig before the script loads. Every key is optional.

Key Default Meaning
spritePath "/assets/images/svg-icons/_sprite.svg" Icon sprite for badge/label glyphs (currentColor, recolourable)
cursorSpritePath "/assets/images/svg-cursors/_sprite.svg" Two-colour cursor sprite for GRAPHIC glyphs — ships in the package as dist/cursors.svg
autoInjectMarkup false Create the overlay + halo elements when the page doesn't carry them
suppressScrollBodyClass "is-animating" Skip scroll re-resolution while <body> carries this class (router transitions); null disables
reducedMotion "hide" "hide" keeps the overlay DOM recoverable; "remove" strips it

Both sprites must be served same-origin — <use href> does not load cross-origin.

Basic usage

<script>
  window.bdCursorConfig = { autoInjectMarkup: true };
</script>
<script src="/assets/js/bd-cursor.js" defer></script>

<a href="/work" data-cursor-label="View work" data-cursor-icon-end="arrow-right">…</a>
<section data-cursor-badge="play" data-cursor-replace>…</section>
<div data-cursor-graphic="cursor-hand-pointing">…</div>

Without autoInjectMarkup, place the overlay markup in the page chrome before the scripts:

<div class="cursor-overlay" aria-hidden="true">
  <div class="cursor-overlay-icon cursor-overlay-icon-lead"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true" width="100%" height="100%"><use href=""/></svg></div>
  <span class="cursor-overlay-text"></span>
  <div class="cursor-overlay-icon cursor-overlay-icon-end"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true" width="100%" height="100%"><use href=""/></svg></div>
</div>
<div class="cursor-halo" aria-hidden="true"></div>

JavaScript

initBdCursor() runs automatically and is idempotent; destroyBdCursor() detaches all listeners and root flags so a client-side app can re-initialise.

Signal Direction Purpose
bd:before-nav (legacy alias studio:before-nav) listened Clear a riding badge/graphic before a router swaps page content
bd-cursor:refresh listened Re-read the hovered element's data-cursor-* after runtime mutation (bd-video swaps play↔pause this way)

Glyph contract: a badge/graphic value must resolve to a symbol in its sprite. A missing symbol renders nothing while the CSS still hides the native cursor — a cursorless region with no error. When pairing with BD Video, the icon sprite must contain play, pause, sound-off, sound-on, full-screen and arrow-top-right.

Accessibility

  • The overlay is presentation only: aria-hidden="true" on both elements, pointer-events: none, and no keyboard or screen-reader surface — all interaction semantics stay on the underlying elements.
  • Reduced-motion visitors keep the OS cursor; the engine never hides the native pointer for them.
  • Must keep data-cursor-native on precise controls inside replace regions (scrubbers, inputs) — the carve-out restores the OS pointer and works without consumer CSS.
  • The native-cursor hide is gated behind , which the engine adds only after confirming the overlay is live — no-JS visitors never lose their pointer.

Usage rules

Do

  • Author through the data attributes; treat the engine as a black box
  • Keep GRAPHIC glyphs in the cursor sprite and badge/label glyphs in the icon sprite — they have different colour models
  • Dispatch bd-cursor:refresh after mutating a hovered element's cursor attributes

Don't

  • Point a badge or graphic at a symbol that isn't in the sprite — verify against the sprite before shipping
  • Use data-cursor-replace on an element with no glyph or label — the engine warns and keeps the overlay hidden
  • Re-theme by overriding rules — override the --bd-cursor-* tokens instead

CSS reference

Ships as its own file (dist/css/bd-cursor.css), linked after design-system.css. Component tokens, all overridable:

Token Default Used for
var(--text-accent, #3485cd) Label box + badge fill
var(--text-inverted, #fffdfa) Label text + badge glyph
var(--text-primary, #1f1f1f) currentColor graphics
var(--duration-2xs, 100ms) Overlay fade (JS reads the same token)
var(--duration-xs, 200ms) Halo press feedback
var(--ease-out, …) All transitions
--bd-cursor-tint-5/10/20 color-mix of the accent Halo fills and borders

Structure classes the JS writes: and on the root, / / on the overlay, on icon slots, on the halo.


Use in another product

The design system installs once per product:

npm install github:bydefaultstudio/design-system-dist#semver:^4.7.0

This component's styles ship as dist/css/bd-cursor.css — copy it into the product's served assets and link it after design-system.css. Its behaviour ships as dist/js/bd-cursor.js — copy it into the product's served assets and include it once per page:

<script src="assets/js/bd-cursor.js" defer></script>
On this page
  • Anatomy
  • Configuration
  • Basic usage
  • JavaScript
  • Accessibility
  • Usage rules
  • CSS reference
  • Use in another product
Previous BD Audio
Next BD Video

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default