Closed6
chakra-ui themingで複数部品からなるカスタムコンポーネントを作成
カスタムコンポーネントは二種類
- Single part
- Multipart components(composite component)
2のMultiPart componentsとして、Card コンポーネントをつくる。
完成イメージ
function Usage() {
return (
<Card>
<CardTitle>タイトル</CardTitle>
<CardDescription>詳細な説明</CardDescription>
</Card>
)
}
Themingによるスタイル定義
export const Card: ComponentMultiStyleConfig = {
parts: ['card', 'cardTitle', 'cardDescription'],
baseStyle: {
card: {
shadow: 'md',
borderWidth: '1px',
borderRadius: 'md',
},
cardTitle: {
textAlign: 'center',
fontWeight: 'bold',
fontSize: '2xl',
},
cardDescription: {
color: 'gray.600',
},
},
sizes: {
sm: {
card: {
padding: 2,
},
cardTitle: {
marginBottom: 2,
},
},
md: {
card: {
padding: 6,
},
cardTitle: {
marginBottom: 6,
},
},
},
// 今回は使用しない
variants: {},
defaultProps: {
size: 'md',
},
};
Card
interface CardProps extends BoxProps {
size?: 'sm' | 'md';
}
export const Card: React.FC<CardProps> = (props) => {
const {children, size, ...boxProps} = props;
const styles = useMultiStyleConfig('Card', {size});
return (
<Box __css={styles.card} {...boxProps}>
<StylesProvider value={styles}>{children}</StylesProvider>
</Box>
);
};
CardTitle
interface CardTitleProps extends BoxProps {}
export const CardTitle: React.FC<CardTitleProps> = (props) => {
const styles = useStyles();
return <Box as="h2" __css={styles.cardTitle} {...props} />;
};
CardDescription
export interface CardDescriptionProps extends BoxProps {}
export const CardDescription: React.FC<CardDescriptionProps> = (props) => {
const styles = useStyles();
return <Box __css={styles.cardDescription} {...props} />;
};
function Usage() {
return (
<Card size='sm'>
<CardTitle>カードのタイトル</CardTitle>
<CardDescription>カードの詳細な説明_...</CardDescription>
</Card>
)
}
size: md
size: sm
今回の定義では、sizeを変更することにより一部paddingやmarginが変更される。
例えば、画面サイズによってmobile表示時にspaceを詰めたいときなどに使用できるようになるなど。
// 例
const size = isMobile ? 'sm' : 'md'
CardTitleについて
例えば、Headingをラップして作成することについてはどうだろうか?
// 既存コンポーネントである、Heading
// @see https://chakra-ui.com/docs/components/typography/heading
import {Heading} from 'chakra-ui';
export const CardTitle: React.FC<CardTitleProps> = (props) => {
const styles = useStyles();
return <Heading __css={styles.cardTitle} {...props} />;
};
こちらの実装では、 __css は動作しない。
Headingに関しては、カスタムコンポーネントではなく既存コンポーネントであるため。
あくまで全体のHeadingの定義をThemingによって上書きする、ということは可能。
どうしてもHeadingを使用したい場合は、下記のようにpropsで上書きすることになる。
ただ下記だとsize違いの定義なども不便になるので、基本的には上述のやり方がおすすめ。
export const CardTitle: React.FC<CardTitleProps> = (props) => {
return <Heading fontSize="2xl" textAlign="center" {...props} />;
};
Issueでも同様の質問が上がっていた
このスクラップは2023/01/23にクローズされました