diff --git a/.changeset/stupid-pianos-brake.md b/.changeset/stupid-pianos-brake.md new file mode 100644 index 0000000000..b87f25a8f6 --- /dev/null +++ b/.changeset/stupid-pianos-brake.md @@ -0,0 +1,6 @@ +--- +"@twilio-paste/card": minor +"@twilio-paste/core": minor +--- + +[Card]: add `fillHeight` prop to make card height stretch to the container height diff --git a/packages/paste-core/components/card/src/Card.tsx b/packages/paste-core/components/card/src/Card.tsx index 6f8cd5b189..1e658c1181 100644 --- a/packages/paste-core/components/card/src/Card.tsx +++ b/packages/paste-core/components/card/src/Card.tsx @@ -14,6 +14,15 @@ export interface CardProps extends HTMLPasteProps<"article">, PaddingProps { * @memberof CardProps */ element?: BoxProps["element"]; + + /** + * Overrides the default element name to apply unique styles with the Customization Provider + * + * @default false + * @type {boolean} + * @memberof CardProps + */ + fillHeight?: boolean; } const Card = React.forwardRef( @@ -26,6 +35,7 @@ const Card = React.forwardRef( paddingLeft, paddingRight, paddingTop, + fillHeight, ...props }, ref, @@ -46,6 +56,7 @@ const Card = React.forwardRef( paddingRight={paddingRight} paddingTop={paddingTop} backgroundColor="colorBackgroundWeakest" + height={fillHeight ? "100%" : undefined} > {children} diff --git a/packages/paste-core/components/card/stories/index.stories.tsx b/packages/paste-core/components/card/stories/index.stories.tsx index ce2e01266e..d52ece925d 100644 --- a/packages/paste-core/components/card/stories/index.stories.tsx +++ b/packages/paste-core/components/card/stories/index.stories.tsx @@ -1,5 +1,7 @@ import type { StoryFn } from "@storybook/react"; +import { Box } from "@twilio-paste/box"; import { CustomizationProvider } from "@twilio-paste/customization"; +import { Column, Grid } from "@twilio-paste/grid"; import { Heading } from "@twilio-paste/heading"; import { Paragraph } from "@twilio-paste/paragraph"; import { Stack } from "@twilio-paste/stack"; @@ -62,6 +64,49 @@ export const PropPassthrough = (): React.ReactNode => ( ); +export const FillHeight = (): React.ReactNode => ( + + + + + Without fillHeight, the card will only be as tall as its content. + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa + + + + + + + + + + With fillHeight, the card will stretch to fill the height of the container. This can be useful when you need + to align multiple cards in a row. + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat + nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa + + + + + +); + export const CustomCard: StoryFn = (_args, { parameters: { isTestEnvironment } }) => { const currentTheme = useTheme(); return ( diff --git a/packages/paste-core/components/card/type-docs.json b/packages/paste-core/components/card/type-docs.json index b7906eff1f..e937b150f0 100644 --- a/packages/paste-core/components/card/type-docs.json +++ b/packages/paste-core/components/card/type-docs.json @@ -473,6 +473,13 @@ "required": false, "externalProp": true }, + "fillHeight": { + "type": "boolean", + "defaultValue": false, + "required": false, + "externalProp": false, + "description": "Overrides the default element name to apply unique styles with the Customization Provider" + }, "hidden": { "type": "boolean", "defaultValue": null, diff --git a/packages/paste-website/src/component-examples/CardExamples.ts b/packages/paste-website/src/component-examples/CardExamples.ts index c46a857d59..7e1f7da128 100644 --- a/packages/paste-website/src/component-examples/CardExamples.ts +++ b/packages/paste-website/src/component-examples/CardExamples.ts @@ -99,6 +99,30 @@ export const TitleBodyButtonExample = `const CardExample = () => { render();`.trim(); +export const FillHeightExample = `const CardExample = () => { + return ( + + + + + With fillHeight, the card will stretch to fill the height of the container. + + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et + dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex. + + + + + ); +}; + +render();`.trim(); + export const MarketingOneExample = `const CardExample = () => { return ( diff --git a/packages/paste-website/src/pages/components/card/index.mdx b/packages/paste-website/src/pages/components/card/index.mdx index 056087667b..f994687f2e 100644 --- a/packages/paste-website/src/pages/components/card/index.mdx +++ b/packages/paste-website/src/pages/components/card/index.mdx @@ -27,7 +27,7 @@ import MultipleDont from '../../../assets/images/dont2-multiple-primary.png'; import packageJson from '@twilio-paste/card/package.json'; import ComponentPageLayout from '../../../layouts/ComponentPageLayout'; import {getFeature, getNavigationData} from '../../../utils/api'; -import {AdjustingPaddingExample, DefaultExample, TitleBodyButtonExample, MarketingOneExample, MarketingTwoExample, MarketingThreeExample, MarketingFourExample} from '../../../component-examples/CardExamples' +import {AdjustingPaddingExample, DefaultExample, TitleBodyButtonExample, MarketingOneExample, MarketingTwoExample, MarketingThreeExample, MarketingFourExample, FillHeightExample} from '../../../component-examples/CardExamples' export default ComponentPageLayout; @@ -77,9 +77,9 @@ If you find yourself limited by the default styling and constraints of a Card, y but first consider bringing the problem you are trying to solve to Design System Office Hours to see if another component or pattern could fit your needs. -### Examples +## Examples -#### Default Card +### Default Card By default, a Card has `space100` padding, which can be adjusted with [padding props](/components/card/api#card) and [spacing tokens](/tokens/list#spacings). @@ -90,7 +90,7 @@ By default, a Card has `space100` padding, which can be adjusted with [padding p code={DefaultExample} /> -#### Adjusting padding +### Adjusting padding You can set non-default padding on all sides of a Card. @@ -101,7 +101,7 @@ You can set non-default padding on all sides of a Card. code={AdjustingPaddingExample} /> -#### Card with Title, Body and Button +### Card with Title, Body and Button One of the most common use cases for a Card is to relate a title ([Heading](/components/heading)), supporting body copy ([Paragraph](/components/paragraph)), and primary action ([Button](/components/button)) together. Relating these three elements together with a Card makes it easy for a user to @@ -113,7 +113,18 @@ digest and provides a clear call to action. code={TitleBodyButtonExample} /> -#### Marketing Card +### Fill height + +In scenarios where there is a requirement for the card to fill the height of the parent container, you can use the `fillHeight` prop. + + + +### Marketing Card Use these layouts when you need to draw customers’ attention to upsell and cross-sell opportunities. Use them sparingly, mainly when they’ll help customers solve immediate problems. diff --git a/packages/paste-website/stories/Card.stories.tsx b/packages/paste-website/stories/Card.stories.tsx index be40d27c25..cf40e1345d 100644 --- a/packages/paste-website/stories/Card.stories.tsx +++ b/packages/paste-website/stories/Card.stories.tsx @@ -5,6 +5,7 @@ import { Box } from "@twilio-paste/box"; import { Button } from "@twilio-paste/button"; import { ButtonGroup } from "@twilio-paste/button-group"; import { Card } from "@twilio-paste/card"; +import { Column, Grid } from "@twilio-paste/grid"; import { Heading } from "@twilio-paste/heading"; import { AcceptIcon } from "@twilio-paste/icons/esm/AcceptIcon"; import { ArrowForwardIcon } from "@twilio-paste/icons/esm/ArrowForwardIcon"; @@ -135,6 +136,28 @@ TitleBodyButtonExample.parameters = { padding: false, }; +export const FillHeightExample = (): JSX.Element => ( + + + + With fillHeight, the card will stretch to fill the height of the container. + + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex. + + + + +); + +FillHeightExample.parameters = { + padding: false, +}; + export const MarketingOneExample = (): JSX.Element => { return (