Build a great experience even faster with these useful tools and helpers. Import
hooks and functions from the utils
package:
import utils from '@balance-web/utils';
Ref management
useForkedRef
Passes or assigns a value to multiple refs (typically a DOM node). Useful for dealing with components that need an explicit ref for DOM calculations but also forwards refs assigned by an app.
function Component(props, consumerRef) { let internalRef = useRef(); let ref = useForkedRef(internalRef, consumerRef); return <div ref={ref} {...props} />;}
forwardRefWithAs
React.forwardRef
is re-exported from @balance-web/utils
as forwardRefWithAs
with different type definitions to work with components that have an as
prop.
It accepts two type arguments, DefaultElementType
and Props
.
import { forwardRefWithAs } from '@balance-web/utils';type Props = { color: string } & HTMLAttributes<HTMLButtonElement>;let Button = forwardRefWithAs<'button', Props>( ({ color, as: Tag = 'button', ...props }, ref) => { return <Tag css={{ color }} ref={ref} {...props} />; });
ID helpers
useId
Autogenerate IDs to facilitate WAI-ARIA and server rendering.
A string can be supplied as an argument to be useId
in lieu of the
auto-generated ID. This is handy for accepting user-provided prop IDs that need
to be deterministic.
function Component(props: { id?: string }) { // Pass in a user-supplied ID that will be used conditionally if provided const id = useId(props.id); return ( <> <label htmlFor={id}>Label</label> <input id={id} /> </> );}
makeId
Use the makeId
helper to prefix an existing ID for compound components.
function Component(props: { id?: string }) { const id = useId(props.id); const descriptionId = makeId('description', id); const inputId = makeId('input', id); const labelId = makeId('label', id); return ( <> <label id={labelId} htmlFor={inputId}> Label </label> <input id={inputId} aria-describedby={descriptionId} /> <div id={descriptionId}>Description</div> </> );}
createIdFactory
Use the createIdFactory
helper to create a factory function that generates
IDs with a specific structure.
By creating a factory, you also communicate to other developers the intended critical components.
import { createIdFactory } from '@balance-web/utils';import { getTestIdFromDataAttributes } from '@balance-web/core';const MyComponentTestIdFactory = createIdFactory('my-component', [ 'label', 'input',]);function MyInputComponent<T extends { id: string }>( props: PropsWithDataAttribute<{ id?: string; items: T[] }>) { const id = useId(props.id); const testids = MyComponentTestIdFactory.make( getTestIdFromDataAttributes(props.data) ); return ( <div data-testid={testids.base} id={id}> {props.items.map((item, index) => ( <div key={index}> <label id={testids.label(item.id)} htmlFor={testids.input(item.id)}> {item.label} </label> <input id={testids.input(item.id)} /> </div> ))} </div> );}
Color management
hexToRgb
Use the hexToRgb
helper for converting hex strings to rgb strings. Pass an
optional second argument for opacity.
getContrastText
Get the appropriate contrast text color (#000
, or #fff
) for a given background color.
Event handling
useKeyPress
The useKeyPress
hook makes it easy to detect when the user is pressing a
specific key on their keyboard. It also provides ways to hook into the up/down
handlers, when to bind the handlers, and which element to bind them to.
useClickOutside
wrapHandlers
Wraps a lib-defined event handler and a user-defined event handler, returning a single handler that allows a user to prevent lib-defined handlers from firing.
function Component({ onChange }) { const handleChange = wrapHandlers(onChange, (event) => { // internal handling }); return <input onChange={handleChange} />;}
Miscellaneous
useScrollLock
Prevent scroll on the <body />
for modal components.
useMediaQuery
The useMediaQuery
utility is covered by the theme documentation.