Migrate Avatar component from useStyles to useDefinition

Replace ComponentDefinition with defineComponent pattern, move CSS
module import and prop defaults into the definition, and switch the
component to useDefinition hook.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2026-02-24 09:33:05 +01:00
parent 03f7e74fe1
commit e363e8265d
4 changed files with 51 additions and 31 deletions
+16 -2
View File
@@ -256,13 +256,27 @@ export const Avatar: ForwardRefExoticComponent<
// @public
export const AvatarDefinition: {
readonly styles: {
readonly [key: string]: string;
};
readonly classNames: {
readonly root: 'bui-AvatarRoot';
readonly image: 'bui-AvatarImage';
readonly fallback: 'bui-AvatarFallback';
};
readonly dataAttributes: {
readonly size: readonly ['small', 'medium', 'large'];
readonly propDefs: {
readonly size: {
readonly dataAttribute: true;
readonly default: 'medium';
};
readonly purpose: {
readonly default: 'informative';
};
readonly src: {};
readonly name: {};
readonly children: {};
readonly className: {};
readonly style: {};
};
};
+10 -24
View File
@@ -15,24 +15,18 @@
*/
import { forwardRef, useState, useEffect } from 'react';
import clsx from 'clsx';
import { AvatarProps } from './types';
import { useStyles } from '../../hooks/useStyles';
import { useDefinition } from '../../hooks/useDefinition';
import { AvatarDefinition } from './definition';
import styles from './Avatar.module.css';
/** @public */
export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
const { classNames, dataAttributes, cleanedProps } = useStyles(
const { ownProps, restProps, dataAttributes } = useDefinition(
AvatarDefinition,
{
size: 'medium',
purpose: 'informative',
...props,
},
props,
);
const { className, src, name, purpose, ...rest } = cleanedProps;
const { classes, size, src, name, purpose, style } = ownProps;
const [imageStatus, setImageStatus] = useState<
'loading' | 'loaded' | 'error'
@@ -51,9 +45,7 @@ export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
};
}, [src]);
const initialsCount = ['x-small', 'small'].includes(cleanedProps.size)
? 1
: 2;
const initialsCount = ['x-small', 'small'].includes(size) ? 1 : 2;
const initials = name
.split(' ')
@@ -68,21 +60,15 @@ export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
role="img"
aria-label={purpose === 'informative' ? name : undefined}
aria-hidden={purpose === 'decoration' ? true : undefined}
className={clsx(classNames.root, styles[classNames.root], className)}
className={classes.root}
style={style}
{...dataAttributes}
{...rest}
{...restProps}
>
{imageStatus === 'loaded' ? (
<img
src={src}
alt=""
className={clsx(classNames.image, styles[classNames.image])}
/>
<img src={src} alt="" className={classes.image} />
) : (
<div
aria-hidden="true"
className={clsx(classNames.fallback, styles[classNames.fallback])}
>
<div aria-hidden="true" className={classes.fallback}>
{initials}
</div>
)}
@@ -14,19 +14,28 @@
* limitations under the License.
*/
import type { ComponentDefinition } from '../../types';
import { defineComponent } from '../../hooks/useDefinition';
import type { AvatarOwnProps } from './types';
import styles from './Avatar.module.css';
/**
* Component definition for Avatar
* @public
*/
export const AvatarDefinition = {
export const AvatarDefinition = defineComponent<AvatarOwnProps>()({
styles,
classNames: {
root: 'bui-AvatarRoot',
image: 'bui-AvatarImage',
fallback: 'bui-AvatarFallback',
},
dataAttributes: {
size: ['small', 'medium', 'large'] as const,
propDefs: {
size: { dataAttribute: true, default: 'medium' },
purpose: { default: 'informative' },
src: {},
name: {},
children: {},
className: {},
style: {},
},
} as const satisfies ComponentDefinition;
});
@@ -14,6 +14,17 @@
* limitations under the License.
*/
/** @public */
export type AvatarOwnProps = {
size?: AvatarProps['size'];
purpose?: AvatarProps['purpose'];
src: string;
name: string;
children?: React.ReactNode;
className?: string;
style?: React.CSSProperties;
};
/** @public */
export interface AvatarProps extends React.ComponentPropsWithoutRef<'div'> {
/**