mirror of
https://github.com/zhigang1992/react.git
synced 2026-04-24 04:15:54 +08:00
feat(card): append types to card
This commit is contained in:
@@ -1,14 +1,18 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import withDefaults from '../utils/with-defaults'
|
||||
import useTheme from '../styles/use-theme'
|
||||
import { CardTypes } from '../utils/prop-types'
|
||||
import { getStyles } from './styles'
|
||||
|
||||
interface Props {
|
||||
hoverable?: boolean
|
||||
shadow?: boolean
|
||||
className?: string
|
||||
type?: CardTypes
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
type: 'default' as CardTypes,
|
||||
hoverable: false,
|
||||
shadow: false,
|
||||
className: '',
|
||||
@@ -18,13 +22,17 @@ type NativeAttrs = Omit<React.HTMLAttributes<any>, keyof Props>
|
||||
export type CardProps = Props & typeof defaultProps & NativeAttrs
|
||||
|
||||
const Card: React.FC<React.PropsWithChildren<CardProps>> = React.memo(({
|
||||
children, hoverable, className, shadow, ...props
|
||||
children, hoverable, className, shadow, type, ...props
|
||||
}) => {
|
||||
const theme = useTheme()
|
||||
const hoverShadow = useMemo(() => {
|
||||
if (shadow) return theme.expressiveness.shadowMedium
|
||||
return hoverable ? theme.expressiveness.shadowSmall : 'none'
|
||||
}, [hoverable, shadow, theme.expressiveness])
|
||||
const { color, bgColor, borderColor } = useMemo(
|
||||
() => getStyles(type, theme.palette, shadow),
|
||||
[type, theme.palette, shadow],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={`card ${className}`} {...props}>
|
||||
@@ -37,19 +45,23 @@ const Card: React.FC<React.PropsWithChildren<CardProps>> = React.memo(({
|
||||
transition: all .2s ease;
|
||||
padding: ${theme.layout.gap} ${theme.layout.gap};
|
||||
border-radius: ${theme.layout.radius};
|
||||
border: 1px solid ${shadow ? 'transparent' : theme.palette.border};
|
||||
box-shadow: ${shadow ? theme.expressiveness.shadowSmall : 'none'};
|
||||
box-sizing: border-box;
|
||||
color: ${color};
|
||||
background-color: ${bgColor};
|
||||
border: 1px solid ${borderColor};
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: ${hoverShadow};
|
||||
}
|
||||
|
||||
.card :global(p), .card :global(h1), .card :global(h2),
|
||||
.card :global(h3), .card :global(h4), .card :global(h5),
|
||||
.card :global(h6) {
|
||||
margin: 0;
|
||||
.card :global(*:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.card :global(*:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
|
||||
66
components/card/styles.ts
Normal file
66
components/card/styles.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { CardTypes } from '../utils/prop-types'
|
||||
import { ZeitUIThemesPalette } from '../styles/themes'
|
||||
|
||||
export type CardStyles = {
|
||||
color: string
|
||||
bgColor: string
|
||||
borderColor: string
|
||||
}
|
||||
|
||||
export const getStyles = (
|
||||
type: CardTypes,
|
||||
palette: ZeitUIThemesPalette,
|
||||
isShadow?: boolean,
|
||||
): CardStyles => {
|
||||
const colors: { [key in CardTypes]: Omit<CardStyles, 'borderColor'> } = {
|
||||
default: {
|
||||
color: palette.foreground,
|
||||
bgColor: palette.background,
|
||||
},
|
||||
dark: {
|
||||
color: palette.background,
|
||||
bgColor: palette.foreground,
|
||||
},
|
||||
secondary: {
|
||||
color: palette.background,
|
||||
bgColor: palette.secondary,
|
||||
},
|
||||
success: {
|
||||
color: palette.background,
|
||||
bgColor: palette.success,
|
||||
},
|
||||
warning: {
|
||||
color: palette.background,
|
||||
bgColor: palette.warning,
|
||||
},
|
||||
error: {
|
||||
color: palette.background,
|
||||
bgColor: palette.error,
|
||||
},
|
||||
lite: {
|
||||
color: palette.foreground,
|
||||
bgColor: palette.background,
|
||||
},
|
||||
alert: {
|
||||
color: 'white',
|
||||
bgColor: palette.alert,
|
||||
},
|
||||
purple: {
|
||||
color: 'white',
|
||||
bgColor: palette.purple,
|
||||
},
|
||||
violet: {
|
||||
color: 'white',
|
||||
bgColor: palette.violet,
|
||||
},
|
||||
cyan: {
|
||||
color: 'black',
|
||||
bgColor: palette.cyan,
|
||||
},
|
||||
}
|
||||
const showBorder = type === 'default' && !isShadow
|
||||
return {
|
||||
...colors[type],
|
||||
borderColor: showBorder ? palette.border : 'transparent',
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,20 @@ const snippetTypes = tuple(
|
||||
'lite',
|
||||
)
|
||||
|
||||
const cardTypes = tuple(
|
||||
'default',
|
||||
'secondary',
|
||||
'success',
|
||||
'warning',
|
||||
'error',
|
||||
'dark',
|
||||
'lite',
|
||||
'alert',
|
||||
'purple',
|
||||
'violet',
|
||||
'cyan',
|
||||
)
|
||||
|
||||
const copyTypes = tuple(
|
||||
'default',
|
||||
'slient',
|
||||
@@ -76,6 +90,8 @@ export type ThemeTypes = typeof themeTypes[number]
|
||||
|
||||
export type SnippetTypes = typeof snippetTypes[number]
|
||||
|
||||
export type CardTypes = typeof cardTypes[number]
|
||||
|
||||
export type CopyTypes = typeof copyTypes[number]
|
||||
|
||||
export type TriggerTypes = typeof triggerTypes[number]
|
||||
|
||||
Reference in New Issue
Block a user