Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add props to override avatar and header content style #126

Merged
merged 5 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/components/dataDisplay/Typography/Typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
10 changes: 9 additions & 1 deletion src/components/dataDisplay/Typography/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
22 changes: 20 additions & 2 deletions src/components/surfaces/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const Card: React.FC<CardProps> = ({
icon: Icon,
iconColor = 'secondary',
mediaProps,
avatarProps,
headerContentProps,
...props
}) => {
const hasIcon = !!Icon
Expand All @@ -64,7 +66,13 @@ const Card: React.FC<CardProps> = ({
return (
<MuiCard color={color} hasIcon={hasIcon} variant={variant} {...props}>
{hasHeader && (
<CardHeader hasIcon={hasIcon} iconColor={hasIcon ? (iconColor as CardColor) : undefined} {...cardHeaderProps} />
<CardHeader
hasIcon={hasIcon}
iconColor={hasIcon ? (iconColor as CardColor) : undefined}
avatarProps={avatarProps}
headerContentProps={headerContentProps}
{...cardHeaderProps}
/>
)}
{mediaProps && <CardMedia {...sizes[size || 's']} {...standardMediaProps} />}
{disablePadding ? children : <CardContent hasHeader={hasHeader} children={children} {...contentProps} />}
Expand Down Expand Up @@ -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.
*/
headerContentProps: PropTypes.object
}

export default Card
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('CardActions', () => {
<Button>ok</Button>
</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`', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand Down
71 changes: 45 additions & 26 deletions src/components/surfaces/Card/CardHeader/CardHeaderStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
headerContentProps: any
}

const CardHeader = styled(MuiCardHeader, {
shouldForwardProp: prop => !includes(prop, ['variant', 'hasIcon', 'iconColor', 'filled'])
})(({ theme, filled, hasIcon, iconColor = 'secondary' as CardColor & keyof Palette }: Partial<StyledProps>) => ({
['&.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', 'headerContentProps'])
})(
({
theme,
filled,
hasIcon,
iconColor = 'secondary' as CardColor & keyof Palette,
avatarProps,
headerContentProps
}: Partial<StyledProps>) => ({
['&.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'
}),
...headerContentProps
},
['& .MuiCardHeader-action']: {
display: 'flex',
alignItems: 'center'
}
})
)

export default CardHeader
18 changes: 17 additions & 1 deletion src/components/surfaces/Card/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -62,6 +62,14 @@ export interface CardHeaderProps extends Omit<MuiCardHeaderProps, 'action'> {
* Icon color.
*/
iconColor?: CardColor
/**
* Props applied to the avatar.
*/
avatarProps?: HTMLAttributes<HTMLDivElement>
/**
* Style applied to the header content.
*/
headerContentProps?: HTMLAttributes<HTMLDivElement>
}

export interface CardProps extends Omit<MuiCardProps, 'title'> {
Expand Down Expand Up @@ -134,4 +142,12 @@ export interface CardProps extends Omit<MuiCardProps, 'title'> {
* Props applied to the CardContent component
*/
contentProps?: MuiCardContentProps
/**
* Props applied to the avatar.
*/
avatarProps?: HTMLAttributes<HTMLDivElement>
/**
* Style applied to the header content.
*/
headerContentProps?: HTMLAttributes<HTMLDivElement>
}
7 changes: 3 additions & 4 deletions src/stories/surfaces/Card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ 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 = <Button variant="text">SUBMIT</Button>

const actions = (
<IconButton color="info" variant="text" size="small">
<QuestionMark fontSize="small" />
Expand All @@ -58,7 +57,7 @@ export const Card: Story = {
children={--Text content here--}
icon={People}
footer={<Button variant="text">SUBMIT</Button>}
action={
actions={
<IconButton color="info" variant="text" size="small">
<QuestionMark fontSize="small" />
</IconButton>
Expand Down Expand Up @@ -113,8 +112,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 `<div>` element and a background image to display the media.
*
* By default, we use the combination of a `<div>` 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 = {
Expand Down
Loading