Skip to content

Commit a49c28f

Browse files
authored
feat(Tile): add tile component (#4610)
* feat(Tile): add tile component * docs(Tile): add extra content example * feat(Tile): fix example * feat(Tile): add missing reference * feat(Tile): pr feedback, demo update * feat(Tile): add usage demos * feat(Tile): fix docs error * feat(Tile): add link to demo section in md
1 parent 1840aac commit a49c28f

File tree

11 files changed

+605
-0
lines changed

11 files changed

+605
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import * as React from 'react';
2+
import styles from '@patternfly/react-styles/css/components/Tile/tile';
3+
import { css } from '@patternfly/react-styles';
4+
5+
export interface TileProps extends React.HTMLProps<HTMLDivElement> {
6+
/** Content rendered inside the banner */
7+
children?: React.ReactNode;
8+
/** Additional classes added to the banner */
9+
className?: string;
10+
/** Title of the tile */
11+
title: string;
12+
/** Icon in the tile title */
13+
icon?: React.ReactNode;
14+
/** Flag indicating if the tile is selected */
15+
isSelected?: boolean;
16+
/** Flag indicating if the tile is disabled */
17+
isDisabled?: boolean;
18+
/** Flag indicating if the tile header is stacked */
19+
isStacked?: boolean;
20+
/** Flag indicating if the stacked tile icon is large */
21+
isDisplayLarge?: boolean;
22+
}
23+
24+
export const Tile: React.FunctionComponent<TileProps> = ({
25+
children,
26+
title,
27+
icon,
28+
isStacked,
29+
isSelected,
30+
isDisabled,
31+
isDisplayLarge,
32+
className,
33+
...props
34+
}: TileProps) => (
35+
<div
36+
className={css(
37+
styles.tile,
38+
isSelected && styles.modifiers.selected,
39+
isDisabled && styles.modifiers.disabled,
40+
isDisplayLarge && styles.modifiers.displayLg,
41+
className
42+
)}
43+
tabIndex={0}
44+
{...props}
45+
>
46+
<div className={css(styles.tileHeader, isStacked && styles.modifiers.stacked)}>
47+
{icon && <div className={css(styles.tileIcon)}>{icon}</div>}
48+
<div className={css(styles.tileTitle)}>{title}</div>
49+
</div>
50+
{children && <div className={css(styles.tileBody)}>{children}</div>}
51+
</div>
52+
);
53+
Tile.displayName = 'Tile';
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import { Tile } from '../Tile';
4+
import PlusIcon from '@patternfly/react-icons/dist/js/icons/plus-icon';
5+
6+
describe('Tile', () => {
7+
test('basic', () => {
8+
const view = shallow(<Tile title="test" />);
9+
expect(view).toMatchSnapshot();
10+
});
11+
12+
test('renders selected', () => {
13+
const view = shallow(<Tile title="test" isSelected />);
14+
expect(view).toMatchSnapshot();
15+
});
16+
17+
test('renders disabled', () => {
18+
const view = shallow(<Tile title="test" isDisabled />);
19+
expect(view).toMatchSnapshot();
20+
});
21+
22+
test('renders with subtext', () => {
23+
const view = shallow(<Tile title="test">test subtext</Tile>);
24+
expect(view).toMatchSnapshot();
25+
});
26+
27+
test('renders with icon', () => {
28+
const view = shallow(<Tile title="test" icon={<PlusIcon />} />);
29+
expect(view).toMatchSnapshot();
30+
});
31+
32+
test('renders with stacked icon', () => {
33+
const view = shallow(<Tile title="test" icon={<PlusIcon />} isStacked />);
34+
expect(view).toMatchSnapshot();
35+
});
36+
37+
test('renders with stacked large icon', () => {
38+
const view = shallow(<Tile title="test" icon={<PlusIcon />} isStacked isDisplayLarge />);
39+
expect(view).toMatchSnapshot();
40+
});
41+
});
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Tile basic 1`] = `
4+
<div
5+
className="pf-c-tile"
6+
tabIndex={0}
7+
>
8+
<div
9+
className="pf-c-tile__header"
10+
>
11+
<div
12+
className="pf-c-tile__title"
13+
>
14+
test
15+
</div>
16+
</div>
17+
</div>
18+
`;
19+
20+
exports[`Tile renders disabled 1`] = `
21+
<div
22+
className="pf-c-tile pf-m-disabled"
23+
tabIndex={0}
24+
>
25+
<div
26+
className="pf-c-tile__header"
27+
>
28+
<div
29+
className="pf-c-tile__title"
30+
>
31+
test
32+
</div>
33+
</div>
34+
</div>
35+
`;
36+
37+
exports[`Tile renders selected 1`] = `
38+
<div
39+
className="pf-c-tile pf-m-selected"
40+
tabIndex={0}
41+
>
42+
<div
43+
className="pf-c-tile__header"
44+
>
45+
<div
46+
className="pf-c-tile__title"
47+
>
48+
test
49+
</div>
50+
</div>
51+
</div>
52+
`;
53+
54+
exports[`Tile renders with icon 1`] = `
55+
<div
56+
className="pf-c-tile"
57+
tabIndex={0}
58+
>
59+
<div
60+
className="pf-c-tile__header"
61+
>
62+
<div
63+
className="pf-c-tile__icon"
64+
>
65+
<PlusIcon
66+
color="currentColor"
67+
noVerticalAlign={false}
68+
size="sm"
69+
/>
70+
</div>
71+
<div
72+
className="pf-c-tile__title"
73+
>
74+
test
75+
</div>
76+
</div>
77+
</div>
78+
`;
79+
80+
exports[`Tile renders with stacked icon 1`] = `
81+
<div
82+
className="pf-c-tile"
83+
tabIndex={0}
84+
>
85+
<div
86+
className="pf-c-tile__header pf-m-stacked"
87+
>
88+
<div
89+
className="pf-c-tile__icon"
90+
>
91+
<PlusIcon
92+
color="currentColor"
93+
noVerticalAlign={false}
94+
size="sm"
95+
/>
96+
</div>
97+
<div
98+
className="pf-c-tile__title"
99+
>
100+
test
101+
</div>
102+
</div>
103+
</div>
104+
`;
105+
106+
exports[`Tile renders with stacked large icon 1`] = `
107+
<div
108+
className="pf-c-tile pf-m-display-lg"
109+
tabIndex={0}
110+
>
111+
<div
112+
className="pf-c-tile__header pf-m-stacked"
113+
>
114+
<div
115+
className="pf-c-tile__icon"
116+
>
117+
<PlusIcon
118+
color="currentColor"
119+
noVerticalAlign={false}
120+
size="sm"
121+
/>
122+
</div>
123+
<div
124+
className="pf-c-tile__title"
125+
>
126+
test
127+
</div>
128+
</div>
129+
</div>
130+
`;
131+
132+
exports[`Tile renders with subtext 1`] = `
133+
<div
134+
className="pf-c-tile"
135+
tabIndex={0}
136+
>
137+
<div
138+
className="pf-c-tile__header"
139+
>
140+
<div
141+
className="pf-c-tile__title"
142+
>
143+
test
144+
</div>
145+
</div>
146+
<div
147+
className="pf-c-tile__body"
148+
>
149+
test subtext
150+
</div>
151+
</div>
152+
`;
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
---
2+
id: Tile
3+
section: components
4+
cssPrefix: pf-c-tile
5+
propComponents: ['Tile']
6+
beta: true
7+
---
8+
9+
import { Tile, Flex } from '@patternfly/react-core';
10+
import { PlusIcon, BellIcon } from '@patternfly/react-icons';
11+
12+
## Examples
13+
14+
Keyboard interaction patterns and a11y is implemented in the Tile demos, located in the [Demo section](/documentation/react/demos/tiledemo).
15+
16+
### Tile
17+
18+
```js
19+
import React from 'react';
20+
import { Tile } from '@patternfly/react-core';
21+
22+
BasicTile = () => (
23+
<React.Fragment>
24+
<Tile title="Default" /> <Tile title="Selected" isSelected /> <Tile title="Disabled" isDisabled />
25+
</React.Fragment>
26+
);
27+
```
28+
29+
### Tile with subtext
30+
31+
```js
32+
import React from 'react';
33+
import { Tile } from '@patternfly/react-core';
34+
35+
SubtextTile = () => (
36+
<React.Fragment>
37+
<Tile title="Default">Subtext goes here</Tile>{' '}
38+
<Tile title="Selected" isSelected>
39+
Subtext goes here
40+
</Tile>{' '}
41+
<Tile title="Disabled" isDisabled>
42+
Subtext goes here
43+
</Tile>
44+
</React.Fragment>
45+
);
46+
```
47+
48+
### Tile with icon
49+
50+
```js
51+
import React from 'react';
52+
import { Tile } from '@patternfly/react-core';
53+
import { PlusIcon } from '@patternfly/react-icons';
54+
55+
IconTile = () => (
56+
<React.Fragment>
57+
<Tile title="Default" icon={<PlusIcon />}>
58+
Subtext goes here
59+
</Tile>{' '}
60+
<Tile title="Selected" icon={<PlusIcon />} isSelected>
61+
Subtext goes here
62+
</Tile>{' '}
63+
<Tile title="Disabled" icon={<PlusIcon />} isDisabled>
64+
Subtext goes here
65+
</Tile>
66+
</React.Fragment>
67+
);
68+
```
69+
70+
### Stacked tile
71+
72+
```js
73+
import React from 'react';
74+
import { Tile } from '@patternfly/react-core';
75+
import { BellIcon } from '@patternfly/react-icons';
76+
77+
StackedTile = () => (
78+
<React.Fragment>
79+
<Tile title="Default" icon={<BellIcon />} isStacked>
80+
Subtext goes here
81+
</Tile>{' '}
82+
<Tile title="Selected" icon={<BellIcon />} isStacked isSelected>
83+
Subtext goes here
84+
</Tile>{' '}
85+
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisabled>
86+
Subtext goes here
87+
</Tile>
88+
</React.Fragment>
89+
);
90+
```
91+
92+
### Stacked tile with large icons
93+
94+
```js
95+
import React from 'react';
96+
import { Tile } from '@patternfly/react-core';
97+
import { BellIcon } from '@patternfly/react-icons';
98+
99+
LargeStackedTile = () => (
100+
<React.Fragment>
101+
<Tile title="Default" icon={<BellIcon />} isStacked isDisplayLarge>
102+
Subtext goes here
103+
</Tile>{' '}
104+
<Tile title="Selected" icon={<BellIcon />} isStacked isDisplayLarge isSelected>
105+
Subtext goes here
106+
</Tile>{' '}
107+
<Tile title="Disabled" icon={<BellIcon />} isStacked isDisplayLarge isDisabled>
108+
Subtext goes here
109+
</Tile>
110+
</React.Fragment>
111+
);
112+
```
113+
114+
### Tile with extra content
115+
116+
```js
117+
import React from 'react';
118+
import { Tile, Flex } from '@patternfly/react-core';
119+
import { BellIcon } from '@patternfly/react-icons';
120+
121+
ExtraContentTile = () => (
122+
<Flex>
123+
<Flex flex={{ default: 'flex_1' }}>
124+
<Tile title="Default" icon={<BellIcon />} isStacked>
125+
This is really really long subtext that goes on for so long that it has to wrap to the next line. This is really
126+
really long subtext that goes on for so long that it has to wrap to the next line.
127+
</Tile>
128+
</Flex>
129+
<Flex flex={{ default: 'flex_1' }}>
130+
<Tile title="Selected" icon={<BellIcon />} isStacked>
131+
This is really really long subtext that goes on for so long that it has to wrap to the next line.
132+
</Tile>
133+
</Flex>
134+
<Flex flex={{ default: 'flex_1' }}>
135+
<Tile title="Disabled" icon={<BellIcon />} isStacked>
136+
Subtext goes here
137+
</Tile>
138+
</Flex>
139+
</Flex>
140+
);
141+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Tile';

0 commit comments

Comments
 (0)