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:
@@ -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: {};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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'> {
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user