Files
community-rule/app/hooks/useComponentStyles.ts
T
2026-01-26 12:51:27 -07:00

112 lines
2.7 KiB
TypeScript

import { useMemo } from "react";
/**
* Configuration for component size styles
*/
export interface SizeStyleConfig {
[key: string]: string | Record<string, string>;
}
/**
* Configuration for component state styles
*/
export interface StateStyleConfig {
[key: string]: string | Record<string, string>;
}
/**
* Options for useComponentStyles hook
*/
export interface UseComponentStylesOptions {
size: string;
state?: string;
disabled?: boolean;
error?: boolean;
sizeStyles: SizeStyleConfig;
stateStyles: StateStyleConfig;
getStateStyles?: (params: {
state?: string;
disabled: boolean;
error: boolean;
}) => Record<string, string>;
}
/**
* Hook for managing component size and state styles
* Provides a consistent pattern for styling components based on size, state, and error/disabled status
*
* @param options - Configuration object with size, state, and style definitions
*
* @returns Object with computed style classes
*
* @example
* ```tsx
* const sizeStyles = {
* small: { input: "h-8 text-xs", label: "text-xs" },
* medium: { input: "h-10 text-sm", label: "text-sm" },
* };
*
* const stateStyles = {
* default: { input: "border-gray-300", label: "text-gray-700" },
* focus: { input: "border-blue-500", label: "text-gray-700" },
* };
*
* const { sizeClasses, stateClasses } = useComponentStyles({
* size: "medium",
* state: "default",
* disabled: false,
* error: false,
* sizeStyles,
* stateStyles,
* });
* ```
*/
export function useComponentStyles(
options: UseComponentStylesOptions,
): {
sizeClasses: Record<string, string>;
stateClasses: Record<string, string>;
} {
const {
size,
state = "default",
disabled = false,
error = false,
sizeStyles,
stateStyles,
getStateStyles,
} = options;
const sizeClasses = useMemo(() => {
const sizeConfig = sizeStyles[size] || sizeStyles.medium || {};
return typeof sizeConfig === "string"
? { base: sizeConfig }
: (sizeConfig as Record<string, string>);
}, [size, sizeStyles]);
const stateClasses = useMemo(() => {
if (getStateStyles) {
return getStateStyles({ state, disabled, error });
}
// Default state style resolution
if (disabled) {
return (stateStyles.disabled || {}) as Record<string, string>;
}
if (error) {
return (stateStyles.error || {}) as Record<string, string>;
}
const stateConfig = stateStyles[state] || stateStyles.default || {};
return typeof stateConfig === "string"
? { base: stateConfig }
: (stateConfig as Record<string, string>);
}, [state, disabled, error, stateStyles, getStateStyles]);
return {
sizeClasses,
stateClasses,
};
}