Skip to content

Commit

Permalink
feat(react-core/card): added Card Components
Browse files Browse the repository at this point in the history
affects: @patternfly/react-core, @patternfly/react-docs

Added Card, CardHeader, CardBody, and CardFooter components

ISSUES CLOSED: patternfly#386
  • Loading branch information
dmiller9911 committed Jul 4, 2018
1 parent a6224ff commit c43e41b
Show file tree
Hide file tree
Showing 43 changed files with 633 additions and 143 deletions.
2 changes: 1 addition & 1 deletion packages/react-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ npm install @patternfly/react-core --save
It's strongly advised to use the Patternfly Base CSS in your whole project, or some components may diverge in appearance:

```javascript
import '@patternfly/react-core/styles/patternfly.css';
import '@patternfly/react-core/dist/styles/base.css';
```

#### Example Component Usage
Expand Down
45 changes: 38 additions & 7 deletions packages/react-core/build/copyStyles.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
/* eslint-disable no-case-declarations */
const { copySync, readFileSync, writeFileSync } = require('fs-extra');
const { resolve, dirname, join } = require('path');
const { parse: parseCSS, stringify: stringifyCSS } = require('css');

const baseCSSFilename = 'patternfly-base.css';
const stylesDir = resolve(__dirname, '../dist/styles');
const pfDir = dirname(
require.resolve('@patternfly/patternfly-next/patternfly.css')
require.resolve(`@patternfly/patternfly-next/${baseCSSFilename}`)
);

copySync(join(pfDir, 'assets/'), stylesDir);
const css = readFileSync(join(pfDir, 'patternfly.css'), 'utf8').replace(
/\/assets\//gi,
'./'
);
writeFileSync(join(stylesDir, 'patternfly.css'), css);
const css = readFileSync(join(pfDir, baseCSSFilename), 'utf8');
const ast = parseCSS(css);

const unusedSelectorRegEx = /(\.fas?|\.sr-only)/;
const unusedKeyFramesRegEx = /fa-/;
const unusedFontFamilyRegEx = /Font Awesome 5 Free/;
const ununsedFontFilesRegExt = /(fa-|\.html$|\.css$)/;

// Core provides font awesome fonts and utlities. React does not use these
ast.stylesheet.rules = ast.stylesheet.rules.filter(rule => {
switch (rule.type) {
case 'rule':
return !rule.selectors.some(sel => unusedSelectorRegEx.test(sel));
case 'keyframes':
return !unusedKeyFramesRegEx.test(rule.name);
case 'charset':
case 'comment':
return false;
case 'font-face':
const fontFamilyDecl = rule.declarations.find(
decl => decl.property === 'font-family'
);
return !unusedFontFamilyRegEx.test(fontFamilyDecl.value);
default:
return true;
}
});

copySync(join(pfDir, 'assets/fonts'), join(stylesDir, 'assets/fonts'), {
filter(src) {
return !ununsedFontFilesRegExt.test(src);
}
});
writeFileSync(join(stylesDir, 'base.css'), stringifyCSS(ast));
3 changes: 2 additions & 1 deletion packages/react-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"postbuild": "node ./build/copyStyles.js"
},
"devDependencies": {
"@patternfly/patternfly-next": "^1.0.4",
"@patternfly/patternfly-next": "1.0.8",
"css": "^2.2.3",
"fs-extra": "^6.0.1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
exports[`action button 1`] = `
.pf-c-button.pf-m-action {
display: inline-block;
position: relative;
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1;
color: #292e34;
text-align: center;
white-space: nowrap;
background-color: transparent;
border: 0px;
border-radius: 30em;
box-shadow: none;
color: #292e34;
}
<button
Expand All @@ -30,17 +30,17 @@ exports[`action button 1`] = `
exports[`danger button 1`] = `
.pf-c-button.pf-m-danger {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #ffffff;
text-align: center;
white-space: nowrap;
background-color: #a30000;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #a30000;
color: #ffffff;
}
<button
Expand All @@ -57,17 +57,17 @@ exports[`danger button 1`] = `
exports[`isBlock 1`] = `
.pf-c-button.pf-m-primary.pf-m-block {
display: block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #ffffff;
text-align: center;
white-space: nowrap;
background-color: #00659c;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #00659c;
color: #ffffff;
width: 100%;
}
Expand All @@ -84,17 +84,17 @@ exports[`isBlock 1`] = `
exports[`isDisabled 1`] = `
.pf-c-button.pf-m-primary.pf-m-disabled {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #72767b;
text-align: center;
white-space: nowrap;
background-color: #00659c;
background-color: #d1d1d1;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 1px undefined;
color: #ffffff;
pointer-events: none;
}
Expand All @@ -111,17 +111,17 @@ exports[`isDisabled 1`] = `
exports[`isFocus 1`] = `
.pf-c-button.pf-m-primary.pf-m-focus {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #ffffff;
text-align: center;
white-space: nowrap;
background-color: #00659c;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #00659c;
color: #ffffff;
}
<button
Expand All @@ -137,17 +137,17 @@ exports[`isFocus 1`] = `
exports[`isHover 1`] = `
.pf-c-button.pf-m-primary.pf-m-hover {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #ffffff;
text-align: center;
white-space: nowrap;
background-color: #00659c;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #00659c;
color: #ffffff;
}
<button
Expand All @@ -163,17 +163,17 @@ exports[`isHover 1`] = `
exports[`link button 1`] = `
.pf-c-button.pf-m-link {
display: inline-block;
position: relative;
padding: 0.25rem 0.25rem 0.25rem 0.25rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #00486e;
text-align: center;
white-space: nowrap;
background-color: transparent;
border: 0px;
border-radius: 30em;
box-shadow: none;
color: #00486e;
}
<button
Expand All @@ -190,17 +190,17 @@ exports[`link button 1`] = `
exports[`primary button 1`] = `
.pf-c-button.pf-m-primary {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #ffffff;
text-align: center;
white-space: nowrap;
background-color: #00659c;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #00659c;
color: #ffffff;
}
<button
Expand All @@ -217,17 +217,17 @@ exports[`primary button 1`] = `
exports[`secondary button 1`] = `
.pf-c-button.pf-m-secondary {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #00659c;
text-align: center;
white-space: nowrap;
background-color: transparent;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #00659c;
color: #00659c;
}
<button
Expand All @@ -244,17 +244,17 @@ exports[`secondary button 1`] = `
exports[`tertiary button 1`] = `
.pf-c-button.pf-m-tertiary {
display: inline-block;
position: relative;
padding: 0.25rem 1.5rem 0.25rem 1.5rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #292e34;
text-align: center;
white-space: nowrap;
background-color: transparent;
border: 0px;
border-radius: 30em;
box-shadow: inset 0 0 0 2px #72767b;
color: #00659c;
}
<button
Expand Down
9 changes: 9 additions & 0 deletions packages/react-core/src/components/Card/Card.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SFC, HTMLProps, ReactType } from 'react';

export interface CardProps extends HTMLProps<HTMLDivElement> {
component?: ReactType<CardProps>;
}

declare const Card: SFC<CardProps>;

export default Card;
28 changes: 28 additions & 0 deletions packages/react-core/src/components/Card/Card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/patternfly-next/components/Card/styles.css';
import { componentShape } from '../../internal/componentShape';

const propTypes = {
children: PropTypes.any,
className: PropTypes.string,
component: componentShape
};

const defaultProps = {
children: null,
className: '',
component: 'article'
};

const Card = ({ children, className, component: Component, ...props }) => (
<Component className={css(styles.card, className)} {...props}>
{children}
</Component>
);

Card.propTypes = propTypes;
Card.defaultProps = defaultProps;

export default Card;
31 changes: 31 additions & 0 deletions packages/react-core/src/components/Card/Card.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import Card from './Card';
import { shallow } from 'enzyme';

test('renders with PatternFly Core styles', () => {
const view = shallow(<Card />);
expect(view).toMatchSnapshot();
});

test('className is added to the root element', () => {
const view = shallow(<Card className="extra-class" />);
expect(view.prop('className')).toMatchSnapshot();
});

test('extra props are spread to the root element', () => {
const testId = 'card';
const view = shallow(<Card data-testid={testId} />);
expect(view.prop('data-testid')).toBe(testId);
});

test('allows passing in a string as the component', () => {
const component = 'section';
const view = shallow(<Card component={component} />);
expect(view.type()).toBe(component);
});

test('allows passing in a React Component as the component', () => {
const Component = () => null;
const view = shallow(<Card component={Component} />);
expect(view.type()).toBe(Component);
});
9 changes: 9 additions & 0 deletions packages/react-core/src/components/Card/CardBody.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SFC, HTMLProps, ReactType } from 'react';

export interface CardBodyProps extends HTMLProps<HTMLDivElement> {
component?: ReactType<CardBodyProps>;
}

declare const CardBody: SFC<CardBodyProps>;

export default CardBody;
28 changes: 28 additions & 0 deletions packages/react-core/src/components/Card/CardBody.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/patternfly-next/components/Card/styles.css';
import { componentShape } from '../../internal/componentShape';

const propTypes = {
children: PropTypes.any,
className: PropTypes.string,
component: componentShape
};

const defaultProps = {
children: null,
className: '',
component: 'div'
};

const CardBody = ({ children, className, component: Component, ...props }) => (
<Component className={css(styles.cardBody, className)} {...props}>
{children}
</Component>
);

CardBody.propTypes = propTypes;
CardBody.defaultProps = defaultProps;

export default CardBody;
Loading

0 comments on commit c43e41b

Please sign in to comment.