@denizeffects/bracket-cursor
v0.1.0
Published
Bracket cursor for React. A dot that follows the pointer and brackets that snap around whatever you point at.
Maintainers
Readme
bracket-cursor
bracket cursor for react. a small dot follows the pointer, and two bracket marks leave its side to embrace whatever interactive element you rest on. magnetic targeting, four glyph shapes, hover labels and a blend mode for mixed grounds. zero dependencies, ssr safe, desktop only by design.
install
npm install @denizeffects/bracket-cursorquick start
import { BracketCursor } from "@denizeffects/bracket-cursor";
// mount once, near the root of your app
<BracketCursor />that is all. links, buttons and anything with data-cursor get embraced automatically. styles are injected on first mount.
glyphs
<BracketCursor glyphs="square" /> // [ ] the default
<BracketCursor glyphs="round" /> // ( ) soft
<BracketCursor glyphs="angle" /> // < > sharp
<BracketCursor glyphs="corners" /> // corner ticks, frames without walls
<BracketCursor glyphs={["{", "}"]} /> // any pair of stringslabels
give any target a small caption that rides under the brackets:
<button data-cursor-label="save draft">save</button>turn the feature off entirely with labels={false}.
blend
pages that mix light and dark sections can run the cursor in difference mode, so it stays visible on any ground:
<BracketCursor blend />scoped previews
hand the cursor a container and it lives only inside it. useful for demos, docs and product pages:
const ref = useRef<HTMLDivElement>(null);
<div ref={ref} data-cursor-void>
...
<BracketCursor within={ref} />
</div>data-cursor-void makes any page level cursor yield inside that region, so two instances never fight.
opting out
<video data-cursor="none" />the custom cursor hides and the native cursor returns over that element.
props
| prop | type | default | notes |
| --- | --- | --- | --- |
| glyphs | "square" \| "round" \| "angle" \| "corners" \| [string, string] | "square" | |
| speed | "calm" \| "normal" \| "quick" | "normal" | tuned presets, not multipliers |
| targets | string | links, buttons, labels, [data-cursor] | selector for what gets embraced |
| padding | number | 9 | gap between bracket and target edge, px |
| maxHeight | number | 96 | brackets stop growing past this, px |
| dot | boolean | true | the trailing dot |
| labels | boolean | true | read data-cursor-label from targets |
| blend | boolean | false | mix-blend-mode difference |
| zIndex | number | 100 | |
| within | RefObject<HTMLElement> | | confine the cursor to one container |
theming
a few css custom properties, all optional:
:root {
--bc-ink: #1b1a17; /* color, defaults to currentColor */
--bc-stroke: 1.5px; /* line weight */
--bc-dot: 5px; /* dot size */
--bc-glyph: 9px; /* bracket width */
--bc-label: 10px; /* label font size */
}accessibility
never mounts on touch or coarse pointers, so phones and tablets keep their native behavior. never mounts under prefers-reduced-motion. the native cursor is only hidden while the component is actually active, and every rendered part is aria-hidden and pointer-events: none.
license
mit
