Skip to content

fix(ServiceCard): Add horizontal layout to the ServiceCard #260

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

Merged
merged 3 commits into from
Aug 12, 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
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@ The **service card** component displays a card representing a service with an ic

## Examples

### Service Card
### Basic service card

This shows a basic service card with an `icon`, `title`, `description`, and optional footer passed in.
This shows a basic service card with an `icon`, `title`, `description`, and optional footer passed in. You can also pass all props of the [card component](/components/card).

```js file="./ServiceCardExample.tsx"

```

### Service Card with Gallery example
### Stacked service card

This shows how cards can look side by side in a [gallery layout](/layouts/gallery).
If you set `isStacked` property to `true`, the header layout changes to stacked.

```js file="./ServiceCardStackedExample.tsx"

```

### Service card in a gallery

This shows how cards can look side by side in a [gallery layout](/layouts/gallery). If you set `isFullHeight` property to `true`, the card height will fill the available space.

```js file="./ServiceCardGalleryExample.tsx"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export const BasicExample: React.FunctionComponent = () => (
helperText='Here is helper text'
footer={<>
<Button
variant={ButtonVariant.secondary}
variant={ButtonVariant.primary}
isInline
className='pf-v5-u-pr-md'
className='pf-v5-u-mr-md'
component="a"
href='www.google.com'>
Launch
Expand All @@ -26,7 +26,7 @@ export const BasicExample: React.FunctionComponent = () => (
isInline
href='www.google.com'
>
Learn More
Learn more
</Button></>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import contentHeaderIcon from '../../assets/icons/content-header-icon.svg';
export const ServiceCardGalleryExample: React.FunctionComponent = () => (
<Gallery hasGutter minWidths={{ default: '330px' }}>
<GalleryItem>
<ServiceCard
<ServiceCard
isStacked
isFullHeight
title='Example1'
subtitle='A basic example'
description='This is a basic ServiceCard Example'
Expand All @@ -18,16 +20,19 @@ export const ServiceCardGalleryExample: React.FunctionComponent = () => (
/>
</GalleryItem>
<GalleryItem>
<ServiceCard
<ServiceCard
isStacked
isFullHeight
title='Example2'
subtitle='A second example'
description='This is another basic ServiceCard Example'
icon={<img src={contentHeaderIcon} alt="content-header-icon" />}
helperText=''
footer={<>
<Button
variant={ButtonVariant.secondary}
variant={ButtonVariant.primary}
isInline
className='pf-v5-u-mr-md'
component="a"
href='www.google.com'>
Launch
Expand All @@ -38,7 +43,7 @@ export const ServiceCardGalleryExample: React.FunctionComponent = () => (
isInline
href='www.google.com'
>
Learn More
Learn more
</Button></>
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import ServiceCard from "@patternfly/react-component-groups/dist/dynamic/ServiceCard";
import contentHeaderIcon from '../../assets/icons/content-header-icon.svg';
import { Button, ButtonVariant } from '@patternfly/react-core';


export const BasicExample: React.FunctionComponent = () => (
<ServiceCard
isStacked
title='Example'
subtitle='A basic example'
description='This is a basic ServiceCard Example'
icon={<img src={contentHeaderIcon} alt="content-header-icon" />}
helperText='Here is helper text'
footer={<>
<Button
variant={ButtonVariant.primary}
isInline
className='pf-v5-u-mr-md'
component="a"
href='www.google.com'>
Launch
</Button>
<Button
variant={ButtonVariant.link}
component="a"
isInline
href='www.google.com'
>
Learn more
</Button></>
}
/>
);
4 changes: 2 additions & 2 deletions packages/module/src/ServiceCard/ServiceCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { render } from '@testing-library/react';
import ServiceCard from './ServiceCard';

describe('LogSnippet component', () => {
it('should render LogSnippet component', () => {
describe('ServiceCard component', () => {
it('should render ServiceCard component', () => {
expect(render(<ServiceCard
title='Example'
subtitle='A basic example'
Expand Down
59 changes: 36 additions & 23 deletions packages/module/src/ServiceCard/ServiceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from 'react';
import { Card, CardBody, CardFooter, CardHeader, Text, TextContent, TextVariants } from '@patternfly/react-core';
import { Card, CardBody, CardFooter, CardHeader, Text, TextContent, TextVariants, Flex, FlexItem, CardProps } from '@patternfly/react-core';
import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText';
import { createUseStyles } from 'react-jss';
import clsx from 'clsx';

export interface ServiceCardProps {
export interface ServiceCardProps extends CardProps {
/** Service card title */
title: string;
/** Service card subtitle */
Expand All @@ -19,11 +20,15 @@ export interface ServiceCardProps {
footer?: React.ReactElement | null;
/** Optional custom OUIA ID */
ouiaId?: string | number;
/** Optional flag modifying the card header layout */
isStacked?: boolean;
/** Optional flag indicating if the card height fills the available space */
isFullHeight?: boolean;
}

const useStyles = createUseStyles({
card: {
height: 'var(--pf-v5-u-h-100)'
fullHeightCard: {
height: '100%'
},
image: {
marginRight: 'var(--pf-v5-global--spacer--md)',
Expand All @@ -38,32 +43,40 @@ const ServiceCard: React.FunctionComponent<ServiceCardProps> = ({
icon,
helperText,
footer = null,
ouiaId='ServiceCard'
ouiaId='ServiceCard',
isStacked = false,
isFullHeight = false,
...props
}: ServiceCardProps) => {
const classes = useStyles();

return (
<Card className={classes.card} ouiaId={`${ouiaId}-card`}>
<Card className={clsx({ [classes.fullHeightCard]: isFullHeight })} ouiaId={`${ouiaId}-card`} {...props}>
<CardHeader>
<div className={classes.image}>
{icon}
</div>
<TextContent>
<Text component={TextVariants.h2} ouiaId={`${ouiaId}-title`}>{title}</Text>
{subtitle}
</TextContent>
<Flex direction={{ default: isStacked ? 'column' : 'row' }} alignItems={{ default: isStacked ? 'alignItemsFlexStart' : 'alignItemsCenter' }}>
<FlexItem className={classes.image}>
{icon}
</FlexItem>
<FlexItem>
<TextContent>
<Text component={TextVariants.h2} ouiaId={`${ouiaId}-title`}>{title}</Text>
{subtitle}
</TextContent>
</FlexItem>
</Flex>
</CardHeader>
<CardBody data-ouia-component-id={`${ouiaId}-description`}>{description}</CardBody>
<CardFooter data-ouia-component-id={`${ouiaId}-footer`}>
{ helperText ?
( <HelperText data-ouia-component-id={`${ouiaId}-helper-text`}>
<HelperTextItem variant="indeterminate" className="pf-v5-u-mb-lg">
{helperText}
</HelperTextItem>
</HelperText>) : null
}
{ footer }
</CardFooter>
{ footer || helperText ? (
<CardFooter data-ouia-component-id={`${ouiaId}-footer`}>
{ helperText ?
( <HelperText data-ouia-component-id={`${ouiaId}-helper-text`}>
<HelperTextItem variant="indeterminate" className="pf-v5-u-mb-lg">
{helperText}
</HelperTextItem>
</HelperText>) : null
}
{ footer }
</CardFooter>) : null}
</Card>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`LogSnippet component should render LogSnippet component 1`] = `
exports[`ServiceCard component should render ServiceCard component 1`] = `
{
"asFragment": [Function],
"baseElement": <body>
<div>
<div
class="pf-v5-c-card card-0-2-1"
class="pf-v5-c-card"
data-ouia-component-id="ServiceCard-card"
data-ouia-component-type="PF5/Card"
data-ouia-safe="true"
Expand All @@ -19,23 +19,31 @@ exports[`LogSnippet component should render LogSnippet component 1`] = `
class="pf-v5-c-card__header-main"
>
<div
class="image-0-2-2"
>
/
</div>
<div
class="pf-v5-c-content"
class="pf-v5-l-flex pf-m-row pf-m-align-items-center"
>
<h2
<div
class="image-0-2-2"
>
/
</div>
<div
class=""
data-ouia-component-id="ServiceCard-title"
data-ouia-component-type="PF5/Text"
data-ouia-safe="true"
data-pf-content="true"
>
Example
</h2>
A basic example
<div
class="pf-v5-c-content"
>
<h2
class=""
data-ouia-component-id="ServiceCard-title"
data-ouia-component-type="PF5/Text"
data-ouia-safe="true"
data-pf-content="true"
>
Example
</h2>
A basic example
</div>
</div>
</div>
</div>
</div>
Expand All @@ -45,16 +53,12 @@ exports[`LogSnippet component should render LogSnippet component 1`] = `
>
This is a basic ServiceCard Example
</div>
<div
class="pf-v5-c-card__footer"
data-ouia-component-id="ServiceCard-footer"
/>
</div>
</div>
</body>,
"container": <div>
<div
class="pf-v5-c-card card-0-2-1"
class="pf-v5-c-card"
data-ouia-component-id="ServiceCard-card"
data-ouia-component-type="PF5/Card"
data-ouia-safe="true"
Expand All @@ -67,23 +71,31 @@ exports[`LogSnippet component should render LogSnippet component 1`] = `
class="pf-v5-c-card__header-main"
>
<div
class="image-0-2-2"
>
/
</div>
<div
class="pf-v5-c-content"
class="pf-v5-l-flex pf-m-row pf-m-align-items-center"
>
<h2
<div
class="image-0-2-2"
>
/
</div>
<div
class=""
data-ouia-component-id="ServiceCard-title"
data-ouia-component-type="PF5/Text"
data-ouia-safe="true"
data-pf-content="true"
>
Example
</h2>
A basic example
<div
class="pf-v5-c-content"
>
<h2
class=""
data-ouia-component-id="ServiceCard-title"
data-ouia-component-type="PF5/Text"
data-ouia-safe="true"
data-pf-content="true"
>
Example
</h2>
A basic example
</div>
</div>
</div>
</div>
</div>
Expand All @@ -93,10 +105,6 @@ exports[`LogSnippet component should render LogSnippet component 1`] = `
>
This is a basic ServiceCard Example
</div>
<div
class="pf-v5-c-card__footer"
data-ouia-component-id="ServiceCard-footer"
/>
</div>
</div>,
"debug": [Function],
Expand Down
Loading