Core design system components and utilities for KeystoneJS applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Utility hooks and functions for managing component state, particularly in controlled/uncontrolled component patterns common in form elements and interactive components.
Hook for managing component state that can be either controlled (managed by parent) or uncontrolled (managed internally), with automatic detection and warnings for improper usage patterns.
/**
* Hook for controlled/uncontrolled component state management
* @param controlledValue - Value controlled by parent component
* @param defaultValue - Default value for uncontrolled mode
* @param onChange - Change handler function
* @returns Tuple of current value and change handler
*/
function useManagedState<V, E = ChangeEvent>(
controlledValue: V | undefined,
defaultValue: V,
onChange: ManagedChangeHandler<V, E> | undefined
): [V, ManagedChangeHandler<V, E>];
/**
* Type for change handler functions
*/
type ManagedChangeHandler<V = string, E = ChangeEvent> = (value: V, event: E) => void;Usage Examples:
import { useManagedState, ManagedChangeHandler } from "@keystone-ui/core";
// Custom input component supporting controlled and uncontrolled modes
interface CustomInputProps {
value?: string;
defaultValue?: string;
onChange?: ManagedChangeHandler<string>;
placeholder?: string;
}
function CustomInput({
value: controlledValue,
defaultValue = '',
onChange,
placeholder
}: CustomInputProps) {
const [value, setValue] = useManagedState(
controlledValue,
defaultValue,
onChange
);
return (
<input
value={value}
onChange={(e) => setValue(e.target.value, e)}
placeholder={placeholder}
/>
);
}
// Controlled usage
function ControlledExample() {
const [inputValue, setInputValue] = useState('');
return (
<CustomInput
value={inputValue}
onChange={(value) => setInputValue(value)}
/>
);
}
// Uncontrolled usage
function UncontrolledExample() {
return (
<CustomInput
defaultValue="initial value"
onChange={(value) => console.log('Changed to:', value)}
/>
);
}
// Complex value types
interface ToggleProps {
checked?: boolean;
defaultChecked?: boolean;
onChange?: ManagedChangeHandler<boolean, MouseEvent>;
}
function Toggle({ checked: controlledChecked, defaultChecked = false, onChange }: ToggleProps) {
const [checked, setChecked] = useManagedState(
controlledChecked,
defaultChecked,
onChange
);
return (
<button
role="switch"
aria-checked={checked}
onClick={(e) => setChecked(!checked, e)}
>
{checked ? 'On' : 'Off'}
</button>
);
}Key Features:
Development-only warning utility that logs messages to console when conditions are met, automatically disabled in production builds.
/**
* Logs warning message in development mode only
* @param condition - When true, the warning will be logged
* @param message - Warning message to display
*/
function devWarning(condition: boolean, message: string): void;Usage Examples:
import { devWarning } from "@keystone-ui/core";
function FormField({ required, value, onChange }) {
// Warn about missing required props
devWarning(
required && !value,
'FormField: required field is empty'
);
devWarning(
value !== undefined && typeof onChange !== 'function',
'FormField: controlled field is missing onChange handler'
);
// Warn about deprecated patterns
devWarning(
props.hasOwnProperty('color') && props.hasOwnProperty('variant'),
'FormField: color prop is deprecated, use variant instead'
);
return <input value={value} onChange={onChange} required={required} />;
}
// Custom hook with validation warnings
function useFormValidation(schema, values) {
devWarning(
!schema,
'useFormValidation: schema is required'
);
devWarning(
Object.keys(values).length === 0,
'useFormValidation: no values provided for validation'
);
// Validation logic...
}Utilities for generating unique, accessible IDs with server-side rendering support and compound ID creation.
/**
* Hook for generating unique IDs with SSR support
* @param idFromProps - Optional ID provided via props
* @returns Unique string ID or undefined during SSR
*/
function useId(idFromProps?: string | null): string | undefined;
/**
* Creates compound ID from multiple inputs, filtering out null/undefined values
* @param args - Values to combine into compound ID
* @returns Compound ID string with components joined by '--'
*/
function makeId(...args: (string | number | null | undefined)[]): string;Usage Examples:
import { useId, makeId } from "@keystone-ui/core";
// Form field with auto-generated IDs
function FormField({
id: providedId,
label,
helperText,
errorMessage,
required
}) {
const baseId = useId(providedId);
const inputId = baseId;
const labelId = makeId(baseId, 'label');
const helperId = makeId(baseId, 'helper');
const errorId = makeId(baseId, 'error');
return (
<div>
<label id={labelId} htmlFor={inputId}>
{label} {required && '*'}
</label>
<input
id={inputId}
aria-labelledby={labelId}
aria-describedby={makeId(
helperText && helperId,
errorMessage && errorId
)}
aria-invalid={!!errorMessage}
aria-required={required}
/>
{helperText && (
<div id={helperId} className="helper-text">
{helperText}
</div>
)}
{errorMessage && (
<div id={errorId} className="error-text" role="alert">
{errorMessage}
</div>
)}
</div>
);
}
// Modal with related IDs
function Modal({ titleId: providedTitleId, children }) {
const baseId = useId();
const titleId = useId(providedTitleId) || makeId(baseId, 'title');
const contentId = makeId(baseId, 'content');
return (
<div
role="dialog"
aria-labelledby={titleId}
aria-describedby={contentId}
>
<h2 id={titleId}>Modal Title</h2>
<div id={contentId}>
{children}
</div>
</div>
);
}
// Compound IDs with filtering
makeId('modal', null, 'content'); // 'modal--content'
makeId('field', 123, undefined, 'input'); // 'field--123--input'
makeId(null, undefined); // ''Hook that provides SSR-safe useLayoutEffect functionality, automatically falling back to useEffect in server environments.
/**
* SSR-safe version of useLayoutEffect
* Falls back to no-op on server, useLayoutEffect on client
*/
const useSafeLayoutEffect: typeof useLayoutEffect;Usage Examples:
import { useSafeLayoutEffect } from "@keystone-ui/core";
// Measuring DOM elements safely
function AutoResizeTextarea({ value, onChange }) {
const textareaRef = useRef<HTMLTextAreaElement>(null);
useSafeLayoutEffect(() => {
if (textareaRef.current) {
// Reset height to get accurate scrollHeight
textareaRef.current.style.height = 'auto';
// Set height to content height
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
}
}, [value]);
return (
<textarea
ref={textareaRef}
value={value}
onChange={onChange}
style={{ resize: 'none', overflow: 'hidden' }}
/>
);
}
// Focus management after render
function FocusOnMount({ autoFocus, children }) {
const elementRef = useRef<HTMLElement>(null);
useSafeLayoutEffect(() => {
if (autoFocus && elementRef.current) {
elementRef.current.focus();
}
}, [autoFocus]);
return React.cloneElement(children, { ref: elementRef });
}Using managed state for compound component patterns:
function TabsProvider({ selectedTab, defaultSelectedTab, onTabChange, children }) {
const [activeTab, setActiveTab] = useManagedState(
selectedTab,
defaultSelectedTab || 0,
onTabChange
);
const contextValue = {
activeTab,
setActiveTab,
registerTab: useCallback((index) => {
// Tab registration logic
}, [])
};
return (
<TabsContext.Provider value={contextValue}>
{children}
</TabsContext.Provider>
);
}
function Tab({ index, children }) {
const { activeTab, setActiveTab } = useContext(TabsContext);
const id = useId();
const panelId = makeId(id, 'panel');
return (
<button
id={id}
role="tab"
aria-selected={activeTab === index}
aria-controls={panelId}
onClick={() => setActiveTab(index)}
>
{children}
</button>
);
}Combining multiple managed state hooks for complex forms:
function useFormState(initialValues, validationSchema) {
const [values, setValues] = useState(initialValues);
const [errors, setErrors] = useState({});
const [touched, setTouched] = useState({});
const createFieldProps = useCallback((name) => {
const fieldId = useId();
const errorId = makeId(fieldId, 'error');
return {
id: fieldId,
value: values[name] || '',
onChange: (value) => {
setValues(prev => ({ ...prev, [name]: value }));
// Validate on change...
},
onBlur: () => {
setTouched(prev => ({ ...prev, [name]: true }));
// Validate on blur...
},
'aria-invalid': !!(errors[name] && touched[name]),
'aria-describedby': errors[name] && touched[name] ? errorId : undefined
};
}, [values, errors, touched]);
return { values, errors, touched, createFieldProps };
}