From c1f8aa048c004744973f23dff8c7eaff806b6a58 Mon Sep 17 00:00:00 2001 From: Costi Date: Mon, 26 Aug 2024 15:34:19 +0300 Subject: [PATCH 1/5] add props to override avatar and header content style --- src/components/surfaces/Card/Card.tsx | 22 +++++- .../Card/CardHeader/CardHeaderStyles.ts | 71 ++++++++++++------- src/components/surfaces/Card/types.ts | 16 +++++ src/stories/surfaces/Card/Card.stories.tsx | 11 +-- 4 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/components/surfaces/Card/Card.tsx b/src/components/surfaces/Card/Card.tsx index a1478be9..a0259f12 100644 --- a/src/components/surfaces/Card/Card.tsx +++ b/src/components/surfaces/Card/Card.tsx @@ -45,6 +45,8 @@ const Card: React.FC = ({ icon: Icon, iconColor = 'secondary', mediaProps, + avatarProps, + headerContentStyle, ...props }) => { const hasIcon = !!Icon @@ -64,7 +66,13 @@ const Card: React.FC = ({ return ( {hasHeader && ( - + )} {mediaProps && } {disablePadding ? children : } @@ -148,7 +156,17 @@ Card.propTypes = { /* * Props applied to the CardMedia component. */ - mediaProps: PropTypes.object + mediaProps: PropTypes.object, + /** + * @default {} + * Props applied to the avatar. + */ + avatarProps: PropTypes.object, + /** + * @default {} + * Props applied to the CardHeader component. + */ + headerContentStyle: PropTypes.object } export default Card diff --git a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts index fe5a974f..ce3ae5bd 100644 --- a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts +++ b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts @@ -4,33 +4,52 @@ import { styled } from '@mui/material/styles' import { includes } from 'ramda' import { CardColor } from '../types' -type StyledProps = { theme: Theme; filled: boolean; hasIcon: boolean; iconColor: CardColor } +type StyledProps = { + theme: Theme + filled: boolean + hasIcon: boolean + iconColor: CardColor + avatarProps: any + headerContentStyle: any +} const CardHeader = styled(MuiCardHeader, { - shouldForwardProp: prop => !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled']) -})(({ theme, filled, hasIcon, iconColor = 'secondary' as CardColor & keyof Palette }: Partial) => ({ - ['&.MuiCardHeader-root']: { - ...(filled && { backgroundColor: theme?.palette.grey[200], minHeight: '48px' }) - }, - ['& .MuiCardHeader-avatar']: { - ...(hasIcon && { - width: '3rem', - height: '3rem', - borderRadius: '0.75rem', - background: `linear-gradient(195deg, ${theme?.palette[iconColor].light}, ${theme?.palette[iconColor].main})`, - position: 'absolute', - top: '-20px' - }) - }, - ['& .MuiCardHeader-content']: { - ...(hasIcon && { - paddingLeft: '80px' - }) - }, - ['& .MuiCardHeader-action']: { - display: 'flex', - alignItems: 'center' - } -})) + shouldForwardProp: prop => + !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled', 'avatarProps', 'headerContentStyle']) +})( + ({ + theme, + filled, + hasIcon, + iconColor = 'secondary' as CardColor & keyof Palette, + avatarProps, + headerContentStyle + }: Partial) => ({ + ['&.MuiCardHeader-root']: { + ...(filled && { backgroundColor: theme?.palette.grey[200], minHeight: '48px' }) + }, + ['& .MuiCardHeader-avatar']: { + ...(hasIcon && { + width: '3rem', + height: '3rem', + borderRadius: '0.75rem', + background: `linear-gradient(195deg, ${theme?.palette[iconColor].light}, ${theme?.palette[iconColor].main})`, + position: 'absolute', + top: '-20px', + ...avatarProps + }) + }, + ['& .MuiCardHeader-content']: { + ...(hasIcon && { + paddingLeft: '80px' + }), + ...headerContentStyle + }, + ['& .MuiCardHeader-action']: { + display: 'flex', + alignItems: 'center' + } + }) +) export default CardHeader diff --git a/src/components/surfaces/Card/types.ts b/src/components/surfaces/Card/types.ts index 8d8776df..a804dccf 100644 --- a/src/components/surfaces/Card/types.ts +++ b/src/components/surfaces/Card/types.ts @@ -62,6 +62,14 @@ export interface CardHeaderProps extends Omit { * Icon color. */ iconColor?: CardColor + /** + * Props applied to the avatar. + */ + avatarProps?: any + /** + * Style applied to the header content. + */ + headerContentStyle?: any } export interface CardProps extends Omit { @@ -134,4 +142,12 @@ export interface CardProps extends Omit { * Props applied to the CardContent component */ contentProps?: MuiCardContentProps + /** + * Props applied to the avatar. + */ + avatarProps?: any + /** + * Style applied to the header content. + */ + headerContentStyle?: any } diff --git a/src/stories/surfaces/Card/Card.stories.tsx b/src/stories/surfaces/Card/Card.stories.tsx index 1c76fc29..5ec2be0e 100644 --- a/src/stories/surfaces/Card/Card.stories.tsx +++ b/src/stories/surfaces/Card/Card.stories.tsx @@ -34,19 +34,20 @@ const subheader = 'Subheader' const children = 'Cards are surfaces that display content and actions on a single topic. They should be easy to scan for relevant and actionable information. Elements, like text and images, should be placed on them in a way that clearly indicates hierarchy. Although cards can support multiple actions, UI controls, and an overflow menu, use restraint and remember that cards are entry points to more complex and detailed information.' const footer = - +const avatarProps = { left: '-10px', top: '-10px' } const actions = ( ) +const headerContentStyle = { paddingLeft: '30px' } /** * Although cards can support multiple actions, UI controls, and an overflow menu, * use restraint and remember that cards are entry points to more complex and detailed information. */ export const Card: Story = { - args: { title, subheader, children, icon: People, footer, actions }, + args: { title, subheader, children, icon: People, footer, actions, avatarProps, headerContentStyle }, parameters: { docs: { @@ -58,7 +59,7 @@ export const Card: Story = { children={--Text content here--} icon={People} footer={} - action={ + actions={ @@ -113,8 +114,8 @@ export const Filled: Story = { /** * Examples of cards using images, video or audio files to reinforce the content. - * - * By default, we use the combination of a `
` element and a background image to display the media. + * + * By default, we use the combination of a `
` element and a background image to display the media. * It can be problematic in some situations, for example, you might want to display a video or a responsive image. Use the component prop for these use cases: */ export const Media: Story = { From 83a809961cdce9dd3e5875d4793ea85c05385fce Mon Sep 17 00:00:00 2001 From: Costi Date: Mon, 26 Aug 2024 15:37:29 +0300 Subject: [PATCH 2/5] rename --- src/components/surfaces/Card/Card.tsx | 6 +++--- .../surfaces/Card/CardHeader/CardHeaderStyles.ts | 8 ++++---- src/components/surfaces/Card/types.ts | 4 ++-- src/stories/surfaces/Card/Card.stories.tsx | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/surfaces/Card/Card.tsx b/src/components/surfaces/Card/Card.tsx index a0259f12..06452679 100644 --- a/src/components/surfaces/Card/Card.tsx +++ b/src/components/surfaces/Card/Card.tsx @@ -45,7 +45,7 @@ const Card: React.FC = ({ icon: Icon, iconColor = 'secondary', mediaProps, - avatarProps, + avatarStyle, headerContentStyle, ...props }) => { @@ -69,7 +69,7 @@ const Card: React.FC = ({ @@ -161,7 +161,7 @@ Card.propTypes = { * @default {} * Props applied to the avatar. */ - avatarProps: PropTypes.object, + avatarStyle: PropTypes.object, /** * @default {} * Props applied to the CardHeader component. diff --git a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts index ce3ae5bd..268a3254 100644 --- a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts +++ b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts @@ -9,20 +9,20 @@ type StyledProps = { filled: boolean hasIcon: boolean iconColor: CardColor - avatarProps: any + avatarStyle: any headerContentStyle: any } const CardHeader = styled(MuiCardHeader, { shouldForwardProp: prop => - !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled', 'avatarProps', 'headerContentStyle']) + !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled', 'avatarStyle', 'headerContentStyle']) })( ({ theme, filled, hasIcon, iconColor = 'secondary' as CardColor & keyof Palette, - avatarProps, + avatarStyle, headerContentStyle }: Partial) => ({ ['&.MuiCardHeader-root']: { @@ -36,7 +36,7 @@ const CardHeader = styled(MuiCardHeader, { background: `linear-gradient(195deg, ${theme?.palette[iconColor].light}, ${theme?.palette[iconColor].main})`, position: 'absolute', top: '-20px', - ...avatarProps + ...avatarStyle }) }, ['& .MuiCardHeader-content']: { diff --git a/src/components/surfaces/Card/types.ts b/src/components/surfaces/Card/types.ts index a804dccf..84a967dd 100644 --- a/src/components/surfaces/Card/types.ts +++ b/src/components/surfaces/Card/types.ts @@ -65,7 +65,7 @@ export interface CardHeaderProps extends Omit { /** * Props applied to the avatar. */ - avatarProps?: any + avatarStyle?: any /** * Style applied to the header content. */ @@ -145,7 +145,7 @@ export interface CardProps extends Omit { /** * Props applied to the avatar. */ - avatarProps?: any + avatarStyle?: any /** * Style applied to the header content. */ diff --git a/src/stories/surfaces/Card/Card.stories.tsx b/src/stories/surfaces/Card/Card.stories.tsx index 5ec2be0e..9e0b61f1 100644 --- a/src/stories/surfaces/Card/Card.stories.tsx +++ b/src/stories/surfaces/Card/Card.stories.tsx @@ -34,7 +34,7 @@ const subheader = 'Subheader' const children = 'Cards are surfaces that display content and actions on a single topic. They should be easy to scan for relevant and actionable information. Elements, like text and images, should be placed on them in a way that clearly indicates hierarchy. Although cards can support multiple actions, UI controls, and an overflow menu, use restraint and remember that cards are entry points to more complex and detailed information.' const footer = -const avatarProps = { left: '-10px', top: '-10px' } +const avatarStyle = { left: '-10px', top: '-10px' } const actions = ( @@ -47,7 +47,7 @@ const headerContentStyle = { paddingLeft: '30px' } * use restraint and remember that cards are entry points to more complex and detailed information. */ export const Card: Story = { - args: { title, subheader, children, icon: People, footer, actions, avatarProps, headerContentStyle }, + args: { title, subheader, children, icon: People, footer, actions, avatarStyle, headerContentStyle }, parameters: { docs: { From 4899584486aef830ea02d1a6581fba732f531f86 Mon Sep 17 00:00:00 2001 From: Costi Date: Tue, 27 Aug 2024 10:46:17 +0300 Subject: [PATCH 3/5] resolve comments + add string as option for typography color --- .../dataDisplay/Typography/Typography.tsx | 5 ++++- src/components/dataDisplay/Typography/types.ts | 10 +++++++++- src/components/surfaces/Card/Card.tsx | 12 ++++++------ .../surfaces/Card/CardActions/CardActionsStyles.ts | 2 +- .../surfaces/Card/CardHeader/CardHeaderStyles.ts | 14 +++++++------- src/components/surfaces/Card/types.ts | 10 +++++----- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/components/dataDisplay/Typography/Typography.tsx b/src/components/dataDisplay/Typography/Typography.tsx index d210ca41..1cb999ca 100644 --- a/src/components/dataDisplay/Typography/Typography.tsx +++ b/src/components/dataDisplay/Typography/Typography.tsx @@ -69,7 +69,10 @@ Typography.propTypes = { /** * The color of the text. */ - color: PropTypes.oneOf(['initial', 'inherit', 'primary', 'secondary', 'textPrimary', 'textSecondary', 'error']), + color: PropTypes.oneOfType([ + PropTypes.oneOf(['initial', 'inherit', 'primary', 'secondary', 'textPrimary', 'textSecondary', 'error']), + PropTypes.string + ]), /** * Controls the text emphasis. Different font styles can be used individually or in combination. */ diff --git a/src/components/dataDisplay/Typography/types.ts b/src/components/dataDisplay/Typography/types.ts index 9da82080..356f61ad 100644 --- a/src/components/dataDisplay/Typography/types.ts +++ b/src/components/dataDisplay/Typography/types.ts @@ -5,7 +5,15 @@ import { TypographyProps as MuiTypographyProps } from '@mui/material' /** * The color of the text. */ -export type TypographyColor = 'initial' | 'inherit' | 'primary' | 'secondary' | 'textPrimary' | 'textSecondary' | 'error' +export type TypographyColor = + | 'initial' + | 'inherit' + | 'primary' + | 'secondary' + | 'textPrimary' + | 'textSecondary' + | 'error' + | string /** * Controls the text emphasis. Different font styles can be used individually or in combination. diff --git a/src/components/surfaces/Card/Card.tsx b/src/components/surfaces/Card/Card.tsx index 06452679..462ccdce 100644 --- a/src/components/surfaces/Card/Card.tsx +++ b/src/components/surfaces/Card/Card.tsx @@ -45,8 +45,8 @@ const Card: React.FC = ({ icon: Icon, iconColor = 'secondary', mediaProps, - avatarStyle, - headerContentStyle, + avatarProps, + headerContentProps, ...props }) => { const hasIcon = !!Icon @@ -69,8 +69,8 @@ const Card: React.FC = ({ )} @@ -161,12 +161,12 @@ Card.propTypes = { * @default {} * Props applied to the avatar. */ - avatarStyle: PropTypes.object, + avatarProps: PropTypes.object, /** * @default {} * Props applied to the CardHeader component. */ - headerContentStyle: PropTypes.object + headerContentProps: PropTypes.object } export default Card diff --git a/src/components/surfaces/Card/CardActions/CardActionsStyles.ts b/src/components/surfaces/Card/CardActions/CardActionsStyles.ts index 7ca3cddc..58be2e46 100644 --- a/src/components/surfaces/Card/CardActions/CardActionsStyles.ts +++ b/src/components/surfaces/Card/CardActions/CardActionsStyles.ts @@ -10,7 +10,7 @@ const contentAlignment = cond([ [equals('left'), always('flex-start')], [equals('right'), always('flex-end')], [equals('center'), always('center')], - [T, always('flex-start')] + [T, always('unset')] ]) const CardActions = styled(MuiCardActions, { diff --git a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts index 268a3254..4f1b44e0 100644 --- a/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts +++ b/src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts @@ -9,21 +9,21 @@ type StyledProps = { filled: boolean hasIcon: boolean iconColor: CardColor - avatarStyle: any - headerContentStyle: any + avatarProps: any + headerContentProps: any } const CardHeader = styled(MuiCardHeader, { shouldForwardProp: prop => - !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled', 'avatarStyle', 'headerContentStyle']) + !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled', 'avatarProps', 'headerContentProps']) })( ({ theme, filled, hasIcon, iconColor = 'secondary' as CardColor & keyof Palette, - avatarStyle, - headerContentStyle + avatarProps, + headerContentProps }: Partial) => ({ ['&.MuiCardHeader-root']: { ...(filled && { backgroundColor: theme?.palette.grey[200], minHeight: '48px' }) @@ -36,14 +36,14 @@ const CardHeader = styled(MuiCardHeader, { background: `linear-gradient(195deg, ${theme?.palette[iconColor].light}, ${theme?.palette[iconColor].main})`, position: 'absolute', top: '-20px', - ...avatarStyle + ...avatarProps }) }, ['& .MuiCardHeader-content']: { ...(hasIcon && { paddingLeft: '80px' }), - ...headerContentStyle + ...headerContentProps }, ['& .MuiCardHeader-action']: { display: 'flex', diff --git a/src/components/surfaces/Card/types.ts b/src/components/surfaces/Card/types.ts index 84a967dd..da03082f 100644 --- a/src/components/surfaces/Card/types.ts +++ b/src/components/surfaces/Card/types.ts @@ -5,7 +5,7 @@ import { CardProps as MuiCardProps, CardContentProps as MuiCardContentProps } from '@mui/material' -import { ElementType } from 'react' +import { ElementType, HTMLAttributes } from 'react' import { SvgIconComponent } from '@mui/icons-material' import { Color } from '../../types' @@ -65,11 +65,11 @@ export interface CardHeaderProps extends Omit { /** * Props applied to the avatar. */ - avatarStyle?: any + avatarProps?: HTMLAttributes /** * Style applied to the header content. */ - headerContentStyle?: any + headerContentProps?: HTMLAttributes } export interface CardProps extends Omit { @@ -145,9 +145,9 @@ export interface CardProps extends Omit { /** * Props applied to the avatar. */ - avatarStyle?: any + avatarProps?: HTMLAttributes /** * Style applied to the header content. */ - headerContentStyle?: any + headerContentProps?: HTMLAttributes } From 64a6e8261af681166c6ac5b5344277050d1ba0a6 Mon Sep 17 00:00:00 2001 From: Costi Date: Tue, 27 Aug 2024 10:47:59 +0300 Subject: [PATCH 4/5] undo story example changes --- src/stories/surfaces/Card/Card.stories.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/stories/surfaces/Card/Card.stories.tsx b/src/stories/surfaces/Card/Card.stories.tsx index 9e0b61f1..5ee0a698 100644 --- a/src/stories/surfaces/Card/Card.stories.tsx +++ b/src/stories/surfaces/Card/Card.stories.tsx @@ -34,20 +34,18 @@ const subheader = 'Subheader' const children = 'Cards are surfaces that display content and actions on a single topic. They should be easy to scan for relevant and actionable information. Elements, like text and images, should be placed on them in a way that clearly indicates hierarchy. Although cards can support multiple actions, UI controls, and an overflow menu, use restraint and remember that cards are entry points to more complex and detailed information.' const footer = -const avatarStyle = { left: '-10px', top: '-10px' } const actions = ( ) -const headerContentStyle = { paddingLeft: '30px' } /** * Although cards can support multiple actions, UI controls, and an overflow menu, * use restraint and remember that cards are entry points to more complex and detailed information. */ export const Card: Story = { - args: { title, subheader, children, icon: People, footer, actions, avatarStyle, headerContentStyle }, + args: { title, subheader, children, icon: People, footer, actions }, parameters: { docs: { From 3fbf9202682852a3c835a0568801538c30b23572 Mon Sep 17 00:00:00 2001 From: Costi Date: Tue, 27 Aug 2024 10:53:34 +0300 Subject: [PATCH 5/5] fix test --- src/components/surfaces/Card/CardActions/CardActions.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/surfaces/Card/CardActions/CardActions.test.tsx b/src/components/surfaces/Card/CardActions/CardActions.test.tsx index bf147eb9..b2e41972 100644 --- a/src/components/surfaces/Card/CardActions/CardActions.test.tsx +++ b/src/components/surfaces/Card/CardActions/CardActions.test.tsx @@ -31,7 +31,7 @@ describe('CardActions', () => { ) - expect(screen.getByRole('button').parentElement).toHaveStyle('justify-content: flex-start') + expect(screen.getByRole('button').parentElement).toHaveStyle('justify-content: unset') }) it('displays actions on the right when `align` is set to `right`', () => {