rmwc
Version:
A thin React wrapper for Material Design (Web) Components
173 lines (157 loc) • 4.75 kB
JavaScript
// @flow
import * as React from 'react';
import classNames from 'classnames';
import { Button } from '../Button';
import { Ripple } from '../Ripple';
import { Icon } from '../Icon';
import { IconToggle } from '../IconToggle';
import { simpleTag, withRipple } from '../Base';
import type { SimpleTagPropsT } from '../Base';
/****************************************************************
* Public
****************************************************************/
export type CardPropsT = {
/** Removes the shadow and displays a hairline outline instead */
outlined: boolean
} & SimpleTagPropsT;
/** A Card Component */
export class Card extends simpleTag({
displayName: 'Card',
classNames: (props: CardPropsT) => [
'mdc-card',
{
'mdc-card--outlined': props.outlined
}
],
consumeProps: ['outlined']
})<CardPropsT> {
render() {
return super.render();
}
}
export type CardMediaPropsT = {
/** Automatically scales the media area’s height to equal its width */
square: boolean,
/** Automatically scales the media area’s height according to its width, maintaining a 16:9 aspect ratio */
sixteenByNine: boolean
};
/** Media area that displays a custom background-image with background-size: cover */
export class CardMedia extends simpleTag({
displayName: 'CardMedia',
tag: 'section',
classNames: (props: CardMediaPropsT) => [
'mdc-card__media',
{
'mdc-card__media--square': props.square,
'mdc-card__media--16-9': props.sixteenByNine
}
],
consumeProps: ['square', 'sixteenByNine']
})<CardMediaPropsT> {
render() {
return super.render();
}
}
/** An absolutely-positioned box the same size as the media area, for displaying a title or icon on top of the background-image */
export const CardMediaContent = simpleTag({
displayName: 'CardMediaContent',
classNames: 'mdc-card__media-content'
});
/** The main clickable area for the primary content of the card */
export const CardPrimaryAction = withRipple({ surface: false })(
simpleTag({
displayName: 'CardPrimaryAction',
classNames: 'mdc-card__primary-action'
})
);
export type CardActionsT = {
/** Removes the action area’s padding and causes its only child (an mdc-card__action element) to consume 100% of the action area’s width */
fullBleed: boolean
} & SimpleTagPropsT;
/** Row containing action buttons and/or icons */
export class CardActions extends simpleTag({
displayName: 'CardActions',
tag: 'section',
classNames: (props: CardActionsT) => [
'mdc-card__actions',
{ 'mdc-card__actions--full-bleed': props.fullBleed }
],
consumeProps: ['fullBleed']
})<CardActionsT> {
render() {
return super.render();
}
}
/** A group of action buttons, displayed on the left side of the card (in LTR), adjacent to CardActionIcons */
export const CardActionButtons = simpleTag({
displayName: 'CardActionButtons',
classNames: 'mdc-card__action-buttons'
});
/** A group of supplemental action icons, displayed on the right side of the card (in LTR), adjacent to CardActionButtons */
export const CardActionIcons = simpleTag({
displayName: 'CardActionIcons',
classNames: 'mdc-card__action-icons'
});
export type CardActionPropsT = {
/** An action icon with no text. This is an instance of the Icon component. */
icon?: boolean,
/** The use prop when using an icon. */
use?: React.Node,
/** An toggleable action icon with no text. This is an instance of the IconToggle component. */
iconToggle?: boolean,
/** The on prop when using an iconToggle. */
on?: Object,
/** The off prop when using an iconToggle. */
off?: Object
} & SimpleTagPropsT;
/** A Card action Button. Will return a Button component by default. */
export const CardAction: React.ComponentType<CardActionPropsT> = ({
icon,
iconToggle,
className,
...rest
}: CardActionPropsT) => {
if (icon) {
return (
<Ripple unbounded>
<Icon
{...rest}
use={rest.use}
className={classNames(
className,
'mdc-card__action',
'mdc-card__action--icon'
)}
/>
</Ripple>
);
}
if (iconToggle) {
if (!rest.on || !rest.off) {
throw Error('You must specify `on` and `off` when using the IconToggle');
}
return (
<IconToggle
{...rest}
on={rest.on}
off={rest.off}
className={classNames(
className,
'mdc-card__action',
'mdc-card__action--icon'
)}
/>
);
}
return (
<Button
{...rest}
className={classNames(
className,
'mdc-card__action',
'mdc-card__action--button'
)}
/>
);
};
CardAction.displayName = 'CardAction';