Skip to content

Commit

Permalink
feat(card): add Card component for react-native (razorpay#52)
Browse files Browse the repository at this point in the history
* feat(card): create Card component

* test: update tests

* chore: update story

* chore: remove unnecessary props

* chore: add outline card

* test: update tests

* chore: remove padding from styles and put it inline

* Update src/atoms/Card/Card.web.js

Co-Authored-By: Kamlesh Chandnani <[email protected]>

* fix: fix card on web

* chore: expose background and border color as props

* chore: change variants to 'shadowed' and 'outlined'

* test: update snapshot

Co-authored-by: Kamlesh Chandnani <[email protected]>
  • Loading branch information
chaitanyadeorukhkar and kamleshchandnani authored Mar 13, 2020
1 parent 3f21eb5 commit 1b0f164
Show file tree
Hide file tree
Showing 8 changed files with 593 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .stylelintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
module.exports = {
processors: ['stylelint-processor-styled-components'],
extends: ['stylelint-config-recommended', 'stylelint-config-styled-components'],
rules: {
'property-no-unknown': [
true,
{
ignoreProperties: ['shadow-color', 'shadow-offset', 'shadow-radius', 'shadow-opacity'], // stylelint does not understand these react-native properties
},
],
},
};
94 changes: 94 additions & 0 deletions src/atoms/Card/Card.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components/native';
import automation from '../../_helpers/automation-attributes';
import View from '../View';
import Space from '../Space/Space.native';
import { getColor, getColorKeys } from '../../_helpers/theme';

const styles = {
backgroundColor({ theme, backgroundColor }) {
return getColor(theme, backgroundColor);
},
shadowColor({ theme }) {
return theme.colors.primary[920];
},
shadowOffset({ variant }) {
if (variant === 'shadowed') {
return '0px 4px';
} else {
return '0px 0px';
}
},
shadowOpacity({ variant }) {
if (variant === 'shadowed') {
return 1;
} else {
return 0;
}
},
shadowRadius({ variant }) {
if (variant === 'shadowed') {
return '20px';
} else {
return 0;
}
},
elevation({ variant }) {
if (variant === 'shadowed') {
return 2;
} else {
return 0;
}
},
border({ variant, theme, borderColor }) {
if (variant === 'shadowed') {
return 'none';
} else {
return `1px solid ${getColor(theme, borderColor)}`;
}
},
};

const StyledCard = styled(View)`
shadow-color: ${styles.shadowColor};
shadow-offset: ${styles.shadowOffset};
shadow-opacity: ${styles.shadowOpacity};
shadow-radius: ${styles.shadowRadius};
elevation: ${styles.elevation};
background-color: ${styles.backgroundColor};
border: ${styles.border};
`;

const Card = ({ children, variant, backgroundColor, borderColor, testID }) => {
return (
<Space padding={[1.5, 1.5, 1.5, 1.5]}>
<StyledCard
variant={variant}
backgroundColor={backgroundColor}
borderColor={borderColor}
{...automation(testID)}
>
{children}
</StyledCard>
</Space>
);
};

Card.propTypes = {
children: PropTypes.node,
variant: PropTypes.oneOf(['shadowed', 'outlined']),
testID: PropTypes.string,
backgroundColor: PropTypes.oneOf(getColorKeys()),
borderColor: PropTypes.oneOf(getColorKeys()),
};

Card.defaultProps = {
children: undefined,
variant: 'shadowed',
testID: 'ds-card',
backgroundColor: 'background.200',
borderColor: 'primary.930',
};

export default Card;
55 changes: 55 additions & 0 deletions src/atoms/Card/Card.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import Card from './Card';
import Text from '../Text';
import View from '../View';
import Flex from '../Flex';
import { text, select } from '@storybook/addon-knobs';
import { getColorKeys } from '../../_helpers/theme';

const variantOptions = {
shadowed: 'shadowed',
outlined: 'outlined',
};

storiesOf('Card', module)
.addParameters({
component: Card,
})
.add('default', () => (
<Flex justifyContent="space-evenly" flex={1}>
<View>
<Card
variant={select('Variant', variantOptions, 'shadowed')}
backgroundColor={select('Background color', getColorKeys(), undefined)}
borderColor={select('Border color', getColorKeys(), undefined)}
>
<Text align="center">
{text('Display Text', 'The quick brown fox jumps over the lazy dog')}
</Text>
</Card>
<Card
variant={select('Variant', variantOptions, 'shadowed')}
backgroundColor={select('Background color', getColorKeys(), undefined)}
borderColor={select('Border color', getColorKeys(), undefined)}
>
<Text align="center">
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi tristique, est sed mollis molestie, ligula ipsum molestie nisl, sit amet consectetur eros mauris non nisi.'
}
</Text>
</Card>
<Flex alignSelf="flex-start">
<View>
<Card
variant={select('Variant', variantOptions, 'shadowed')}
backgroundColor={select('Background color', getColorKeys(), undefined)}
borderColor={select('Border color', getColorKeys(), undefined)}
>
<Text align="left">Hello World</Text>
</Card>
</View>
</Flex>
</View>
</Flex>
));
5 changes: 5 additions & 0 deletions src/atoms/Card/Card.web.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

const Card = () => <div>WIP</div>;

export default Card;
63 changes: 63 additions & 0 deletions src/atoms/Card/__tests__/Card.native.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { renderWithTheme } from '../../../_helpers/testing';
import Text from '../../Text';
import Card from '../index';

describe('<Card />', () => {
describe('shadowed', () => {
it('renders a shadowed Card', () => {
const { container } = renderWithTheme(<Card variant="shadowed" />);
expect(container).toMatchSnapshot();
});

it('renders a shadowed Card with custom background color', () => {
const { container } = renderWithTheme(
<Card variant="shadowed" backgroundColor="primary.920" />,
);
expect(container).toMatchSnapshot();
});

it('renders a shadowed Card with text content', () => {
const displayText = 'Hello';
const { container, getByText } = renderWithTheme(
<Card variant="shadowed">
<Text>{displayText}</Text>
</Card>,
);
const textComponent = getByText(displayText);
expect(textComponent.props.children).toEqual(displayText);
expect(container).toMatchSnapshot();
});
});

describe('outlined', () => {
it('renders an outlined Card', () => {
const { container } = renderWithTheme(<Card variant="outlined" />);
expect(container).toMatchSnapshot();
});

it('renders an outlined Card with custom background color', () => {
const { container } = renderWithTheme(
<Card variant="outlined" backgroundColor="primary.920" />,
);
expect(container).toMatchSnapshot();
});

it('renders an outlined Card with custom border color', () => {
const { container } = renderWithTheme(<Card variant="outlined" borderColor="primary.920" />);
expect(container).toMatchSnapshot();
});

it('renders an outlined Card with text content', () => {
const displayText = 'Hello';
const { container, getByText } = renderWithTheme(
<Card variant="outlined">
<Text>{displayText}</Text>
</Card>,
);
const textComponent = getByText(displayText);
expect(textComponent.props.children).toEqual(displayText);
expect(container).toMatchSnapshot();
});
});
});
Loading

0 comments on commit 1b0f164

Please sign in to comment.