# Getting started · Introduction
Subtle highlights for your UI, with your existing colors, layout and interactions.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/
## A little more alive.
Group elements under one shared light and choose which surfaces respond. Give an area its own light when it should react independently.
## Start using Edge
Start with [Installation](https://edge.bolerish.com/docs/installation/), learn the concepts in [Usage](https://edge.bolerish.com/docs/usage/), then follow [React](https://edge.bolerish.com/docs/react/usage/). Find settings in the [API reference](https://edge.bolerish.com/docs/react/api/).
---
# Getting started · Installation
Install Edge and start using it in React.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/installation/
## Installation
The React adapter requires React 18 or 19. Other framework adapters are not available yet.
npm
```bash
npm install @bolerish/edge
```
pnpm
```bash
pnpm add @bolerish/edge
```
Yarn
```bash
yarn add @bolerish/edge
```
Bun
```bash
bun add @bolerish/edge
```
## Default styles
React prepares the default CSS automatically when a surface connects, with or without Edge.Provider. No stylesheet import is required. For SSR, render Edge.Styles once per document before application styles. If CSP requires a nonce, pass the same request nonce on the server and during hydration.
```tsx
```
```css
@import "@bolerish/edge/style.css";
```
Existing CSS imports remain supported. The CSS file is also available for framework-independent use. When loading it explicitly, put it before application and utility styles; a reset may load first. Package CSS imports require a build tool that resolves package paths.
## Start using Edge
Choose an area and its surfaces in [Usage](https://edge.bolerish.com/docs/usage/), then connect them with [React](https://edge.bolerish.com/docs/react/usage/).
---
# Getting started · Usage
Understand lights and surfaces before connecting your components.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/usage/
## Choose an area
A light controls a group of surfaces that respond together. Choose a section or a few elements to share one light.
A surface is an element connected to that light. Only connected surfaces respond. Use a separate light for an independent area.
## Keep your UI
Edge keeps your background, text, spacing and base border. Its highlight uses each surface’s own text color and border radius by default. Keep existing interactions and keyboard focus indicators.
Choose the surface response in [Style](https://edge.bolerish.com/docs/styles/) and how the light moves in [Motion](https://edge.bolerish.com/docs/motion/).
For input wrappers and decoration conflicts, see [Integration considerations](https://edge.bolerish.com/docs/integration/#wrap-inputs-you-own).
For application-controlled position changes, see [layout changes](https://edge.bolerish.com/docs/integration/#refresh-after-layout-changes).
## Choose your framework
Follow the guide for your framework.
[
### React
](https://edge.bolerish.com/docs/react/usage/)
---
# React · Usage
Start with Edge.Provider and Edge.Surface. Use useSurface to connect an existing component directly.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/react/usage/
## Connect an area
Complete [Installation](https://edge.bolerish.com/docs/installation/) first. In Server Component frameworks, use Edge from a client module marked with `"use client"`.
Wrap the area in `Edge.Provider` and mark each responding element with `Edge.Surface`. The two cards below share one light; nested providers create independent lights.
One light, your components
```tsx
Example card
Another example card
```
## Keep your styles and events
Use `as` to choose the HTML element. Native attributes, events and refs follow that element. Optional `className` and `style` props apply your styles. The provider adds no DOM; each surface renders one element.
```tsx
Example button
```
Inputs need a wrapper. If an existing decoration conflicts, see [Integration considerations](https://edge.bolerish.com/docs/integration/). Choose appearance and movement in [Style](https://edge.bolerish.com/docs/styles/) and [Motion](https://edge.bolerish.com/docs/motion/).
## Connect an existing component
If a Card or Button already renders its own HTML element, call [useSurface(options)](https://edge.bolerish.com/docs/react/use-surface/#use-surface) inside it and attach the returned ref to that element. Keep the component inside Edge.Provider. React 18 function components must forward the ref with `forwardRef`.
For position changes, see [layout updates](https://edge.bolerish.com/docs/integration/#refresh-after-layout-changes).
---
# React · Edge.Provider
Creates a shared light for descendant surfaces.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/react/provider/
## Edge.Styles
Render once per SSR document, before application styles. React reuses this stylesheet when surfaces connect. Keep this component mounted while Edge is in use; use nonce when your CSP requires it. Without it or an explicit CSS import, the default CSS is added on the client when a surface connects.
```tsx
```
| Prop / option | Type | Default | Description |
| --- | --- | --- | --- |
| `nonce` | `string` | `undefined` | Optional request nonce for the style element. Use the same value on the server and during hydration. Required when your CSP permits inline style elements only with a nonce. |
## Edge.Provider
Lets descendant Edge.Surface elements share one light without adding DOM elements. Each nested Edge.Provider creates an independent light.
```tsx
{/* Your surfaces */}
```
| Prop / option | Type | Default | Description |
| --- | --- | --- | --- |
| `motion` | `'system' \| 'dynamic' \| 'static'` | `'system'` | System respects reduced-motion and device preferences. Dynamic follows mouse or pen input, even with reduced motion enabled. Static keeps a fixed direction. Touch updates the light position in viewport coordinates. Scrolling and lifting the finger preserve the last position; surfaces respond as they move beneath it. A new touch updates the position. Touch tracking follows the selected motion mode: static stays fixed, and system stays fixed when reduced motion is enabled. |
| `staticDirection` | `number \| 'random'` | `315` | Direction in degrees for fixed lighting. Random chooses one shared direction per mount and keeps it across ordinary rerenders. Numbers must be finite. |
| `direction` | `'toward' \| 'away'` | `'toward'` | toward faces highlights toward the pointer; away reverses them by 180 degrees. All surface styles preserve this choice. Only affects pointer-driven lighting; staticDirection controls fixed lighting. |
| `range` | `number` | `480` | Distance over which dynamic lighting fades outside a surface, in viewport CSS pixels. Must be positive and finite. |
| `intensity` | `number` | `0.75` | Shared light strength. Must be finite and between 0 and 1; invalid values throw a RangeError. |
| `children` | `ReactNode` | `Required` | The area that shares this light. Ordinary children stay unchanged; only explicit surfaces respond. |
| `ref` | `Ref` | `Unset` | Optional ref for the stable light handle. Call its refresh() method after position-only layout changes. |
Pointer input comes from the document. The scope chooses which surfaces respond; it does not clip input to a wrapper rectangle. `staticDirection` applies whenever fixed lighting is active, including when `motion="system"` respects reduced motion.
---
# React · Edge.Surface
Applies lighting to a DOM element.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/react/surface/
## Edge.Surface
Renders one HTML element connected to the nearest provider. Native attributes and events follow the tag selected by `as`.
```tsx
Your content
```
| Prop / option | Type | Default | Description |
| --- | --- | --- | --- |
| `pseudoElement` | `'after' \| 'before'` | `'after'` | Decoration slot. Choose before to preserve an existing ::after. If both slots are occupied, or the element is a native input, use a wrapper. Invalid values throw a RangeError. |
| `edgeStyle` | `'raised' \| 'recessed' \| 'matte'` | `'raised'` | How the edge responds to light. All three styles preserve your component appearance. |
| `color` | `string` | `currentColor` | Highlight color. Follows the element's text color by default. Accepts any CSS color string, including a CSS variable. |
| `shadowColor` | `string` | `#0008` | Color on the opposite edge. Accepts any CSS color string; use transparent to remove this shadow on a light surface. |
| `borderWidth` | `number` | `1` | Decorative edge thickness in pixels; it does not change the element's border. Negative values clamp to 0. Non-finite values use the default. |
| `intensity` | `number` | `1` | Multiplier for the shared light strength. Finite values clamp to 0–1; non-finite values use the default. |
| `as` | `HTML tag name` | `'div'` | The HTML element to render. Native attributes and the ref follow the chosen tag; custom React components are not accepted here. |
| `children` | `ReactNode` | `Unset` | Content rendered inside the element. Use a wrapper for inputs and other elements that cannot display the decoration themselves. |
| `ref` | `Ref` | `Unset` | Forwarded to the rendered element alongside the internal registration ref. React 19 callback-ref cleanup is preserved. |
| `className` | `string` | `Unset` | Your classes, combined with the decoration classes. |
| `style` | `CSSProperties` | `Unset` | Your inline styles, merged after the decoration bindings. Keep Edge-owned CSS variables intact unless deliberately overriding them. |
Place every `Edge.Surface` inside a `Edge.Provider` owner; rendering it outside one throws an error. For native inputs and occupied pseudo-elements, see [Integration considerations](https://edge.bolerish.com/docs/integration/).
Decoration aligns with the outside of the element's border. To connect an existing component’s HTML element, use [useSurface](https://edge.bolerish.com/docs/react/use-surface/#use-surface).
---
# React · useLight
Creates and configures a light handle.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/react/use-light/
## useLight(options?)
Returns a stable `Light` handle for explicit ownership without a provider. Pass it to `useSurface(light, options)`. Option changes update the existing light; use `Edge.Provider` for ordinary component trees.
```tsx
function useLight(options?: LightOptions): Light;
```
| Prop / option | Type | Default | Description |
| --- | --- | --- | --- |
| `motion` | `'system' \| 'dynamic' \| 'static'` | `'system'` | System respects reduced-motion and device preferences. Dynamic follows mouse or pen input, even with reduced motion enabled. Static keeps a fixed direction. Touch updates the light position in viewport coordinates. Scrolling and lifting the finger preserve the last position; surfaces respond as they move beneath it. A new touch updates the position. Touch tracking follows the selected motion mode: static stays fixed, and system stays fixed when reduced motion is enabled. |
| `staticDirection` | `number \| 'random'` | `315` | Direction in degrees for fixed lighting. Random chooses one shared direction per mount and keeps it across ordinary rerenders. Numbers must be finite. |
| `direction` | `'toward' \| 'away'` | `'toward'` | toward faces highlights toward the pointer; away reverses them by 180 degrees. All surface styles preserve this choice. Only affects pointer-driven lighting; staticDirection controls fixed lighting. |
| `range` | `number` | `480` | Distance over which dynamic lighting fades outside a surface, in viewport CSS pixels. Must be positive and finite. |
| `intensity` | `number` | `0.75` | Shared light strength. Must be finite and between 0 and 1; invalid values throw a RangeError. |
`range` affects dynamic lighting only. Fixed lighting uses `staticDirection` without distance attenuation.
## light.refresh()
Remeasures surfaces on the next frame, even with a stationary pointer. Call after React commits changes to an element’s position or border thickness without a size notification.
```tsx
interface Light {
refresh(): void;
}
```
Size changes and scrolling are handled automatically; see [layout updates](https://edge.bolerish.com/docs/integration/#refresh-after-layout-changes) for details.
---
# React · useSurface
Returns a ref that connects an existing DOM element to a light.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/react/use-surface/
## useSurface(options?)
Returns a callback ref that connects an existing HTML element to the nearest provider. Attach it to the element displaying the border and keep your existing `className` and `style`.
```tsx
const ref = useSurface(options);
```
```tsx
function Area() {
return ;
}
function ExistingCard() {
const ref = useSurface();
return Your existing component;
}
```
In React 18, an existing function component must use `forwardRef` to pass the ref to its HTML element. React 19 also supports receiving ref as a prop.
Without an explicit light, this hook requires an Edge.Provider. For advanced ownership, use `useSurface(light, options)` with a handle returned by `useLight`. The explicit light takes precedence over the provider.
| Prop / option | Type | Default | Description |
| --- | --- | --- | --- |
| `pseudoElement` | `'after' \| 'before'` | `'after'` | Decoration slot. Choose before to preserve an existing ::after. If both slots are occupied, or the element is a native input, use a wrapper. Invalid values throw a RangeError. |
| `edgeStyle` | `'raised' \| 'recessed' \| 'matte'` | `'raised'` | How the edge responds to light. All three styles preserve your component appearance. |
| `color` | `string` | `currentColor` | Highlight color. Follows the element's text color by default. Accepts any CSS color string, including a CSS variable. |
| `shadowColor` | `string` | `#0008` | Color on the opposite edge. Accepts any CSS color string; use transparent to remove this shadow on a light surface. |
| `borderWidth` | `number` | `1` | Decorative edge thickness in pixels; it does not change the element's border. Negative values clamp to 0. Non-finite values use the default. |
| `intensity` | `number` | `1` | Multiplier for the shared light strength. Finite values clamp to 0–1; non-finite values use the default. |
A DOM element can connect to only one light. Do not attach the ref to a parent element with different dimensions.
Options update without replacing the element. Hook decoration attaches after hydration; use `Edge.Surface` to include appearance classes and variables in server output.
---
# Styles · Style
Choose how a surface responds to light without changing its base styles.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/styles/
## Compare the edge response
Choose a style and move your pointer around the card. The selection also updates this site’s cards, code blocks and navigation surfaces.
Compare edge styles
```tsx
const light = useLight();
const surface = useSurface(light, { edgeStyle: "raised" });
Your component
```
## Style values
| Value | Behavior |
| --- | --- |
| `raised` | Highlights the edge facing the light. Default. |
| `recessed` | Draws the highlight one decorative edge thickness inward. Preserves the selected light direction. |
| `matte` | Softens the edge response. |
For additional settings, see the [API reference](https://edge.bolerish.com/docs/react/surface/#lighting-surface).
## Raised
Use `edgeStyle: 'raised'` for an outward-facing edge highlight.
## Recessed
Use `edgeStyle: 'recessed'` for a highlight inset by one decorative edge thickness, such as on input wrappers. It preserves the selected light direction.
## Matte
Use `edgeStyle: 'matte'` for a softer, quieter border.
## Customize the highlight
Each surface uses its own text color, even when nested, and follows its element's border radius. Set `color` to override the highlight, or `intensity` to multiply the shared light strength. Use `shadowColor="transparent"` to remove the opposite-edge shadow. `borderWidth` changes the decoration thickness in pixels, not the element's border. Pass options to [Edge.Surface](https://edge.bolerish.com/docs/react/surface/#lighting-surface); no CSS variable declarations are needed.
The effect approximates a direction on axis-aligned rectangles, not a physical point light. Near the center, directional intensity fades over a region proportional to the surface size.
For existing decorations and input wrappers, see [Integration considerations](https://edge.bolerish.com/docs/integration/).
---
# Styles · Motion
Choose whether a shared light follows the pointer or keeps a fixed direction.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/motion/
## Choose motion behavior
Use `system` to respect reduced motion. Touch updates the light position in viewport coordinates. Scrolling and lifting the finger preserve the last position; surfaces respond as they move beneath it. A new touch updates the position. Offer `dynamic` only as an explicit choice because it overrides reduced motion. See [Motion](https://edge.bolerish.com/docs/motion/) for details.
## Choose motion behavior
Try each mode below. The selection updates the shared light across this site, including the example card.
Compare motion
```tsx
const light = useLight({ motion: "dynamic" });
const surface = useSurface(light, { edgeStyle: "raised" });
Your component
```
## Pointer lighting
toward lights the edge facing the pointer; away lights the opposite edge. range is the fade distance outside each surface. For example, range: 40 fades to zero when the pointer is 40 CSS pixels outside the card; it does not create a 40-pixel bright circle around the pointer. Move the pointer outside the card to compare values. Fixed lighting ignores these settings.
Pointer lighting
```tsx
const light = useLight({ motion: 'dynamic', direction: "toward", range: 480 });
```
## Motion values
| Value | Behavior |
| --- | --- |
| `system` | Respects reduced motion and input preferences. Library default. |
| `dynamic` | Follows mouse, pen or touch contact, including with reduced motion enabled. |
| `static` | Keeps a fixed direction; ignores pointer movement. |
For additional settings, see the [API reference](https://edge.bolerish.com/docs/react/provider/#lighting).
## System
Without a precise hover device, lighting starts fixed. Mouse or pen input can enable tracking when reduced motion is off. Touch updates the light position in viewport coordinates. Scrolling and lifting the finger preserve the last position; surfaces respond as they move beneath it. A new touch updates the position.
## Dynamic
Offer this mode as an explicit choice because it overrides reduced motion. The effect stays hidden until mouse, pen or touch contact arrives.
## Static
Set `staticDirection` to any finite angle in degrees or `"random"`. The demo offers 0°, 90°, 180°, 270° and 315°. Random chooses one shared direction per mount; rerenders and appearance changes preserve it. Remount to choose a new direction.
Static
```tsx
const light = useLight({ motion: 'static', staticDirection: "random" });
```
## Respect user preferences
Keep focus, selection and validation visible independently of lighting. See [Accessibility](https://edge.bolerish.com/docs/integration/#preserve-native-interactions) for input and forced-colors behavior.
---
# Guides · Integration considerations
Handle decoration conflicts, native inputs and layout changes.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/integration/
## Choose motion behavior
System respects reduced-motion and device preferences. Dynamic follows mouse or pen input, even with reduced motion enabled. Static keeps a fixed direction. Touch updates the light position in viewport coordinates. Scrolling and lifting the finger preserve the last position; surfaces respond as they move beneath it. A new touch updates the position. Touch tracking follows the selected motion mode: static stays fixed, and system stays fixed when reduced motion is enabled.
## Understand rendering cost
Each light queues at most one frame, reads geometry before writing styles, and skips unchanged output. Gradient changes still require browser rendering work; this does not guarantee a frame rate or battery cost.
## Preserve native interactions
Keep labels, text contrast, base borders and visible keyboard focus. Decoration does not capture pointer events; input values, selection, keyboard handling and portals remain under your control.
Forced-colors mode hides decoration. Communicate selection, validation and availability independently of the highlight.
## Keep existing decorations
Edge uses `::after` by default. Set `pseudoElement: 'before'` to keep an existing `::after`. If both pseudo-elements are occupied, decorate a wrapper.
Keep existing pseudo-elements
```tsx
import { Edge } from '@bolerish/edge';
Your existing ::after stays intact.
```
## Wrap native inputs
Native inputs do not reliably display pseudo-element decoration. Connect a surrounding `label` or `div` with a matching radius instead. Keep the input’s label, focus, validation and keyboard behavior. Use `recessed` for an inset appearance.
## Refresh after layout changes
Size changes, nested scrolling, viewport resizing, font loading and resource loads update geometry automatically. After a position-only change or a element's border-thickness change without a size notification, call `light.refresh()` once the new layout is applied. It updates even with a stationary pointer.
See [light.refresh()](https://edge.bolerish.com/docs/react/use-light/#refresh) for the React call.
## Geometry and document boundaries
Edge approximates axis-aligned rectangles. Rotation, perspective transforms and cross-document portals are unsupported. Portals within the same document can share a light. For focus, selection and validation, see [Accessibility](https://edge.bolerish.com/docs/integration/#preserve-native-interactions).
---
# Guides · AI Integration
Give your assistant current Edge documentation before it changes your UI.
Package: @bolerish/edge 0.4.0
Source: https://edge.bolerish.com/docs/ai-integration/
## Read the documentation
Start with [llms.txt](https://edge.bolerish.com/llms.txt) for a short index linking to Markdown versions of each guide and API reference. Use [llms-full.txt](https://edge.bolerish.com/llms-full.txt) when your assistant needs all the documentation in one file.
These files are generated from the same content as this site and identify the package version they describe. Publishing them does not guarantee that an assistant reads them automatically; include the URL in your request.
## Write a prompt
Paste the component you want to update and describe which elements should respond to the light. For example:
```text
Read https://edge.bolerish.com/llms.txt and follow the relevant Markdown links.
Check the installed @bolerish/edge version and its types before choosing APIs.
Add Edge to the component below, preserving its markup, colors and interactions.
Connect only the surfaces I specify. Keep native controls and focus indicators.
Use the library's default motion="system" unless I ask for another mode.
```
## Match the installed version
Check your package manifest or lockfile. Web documentation may describe a newer release; if versions differ, use the installed package’s declarations and matching documentation. Do not upgrade dependencies just to match an example.