joyent-portal/packages/ui-toolkit/src/card/header.js

205 lines
4.9 KiB
JavaScript

import React from 'react';
import { Broadcast, Subscriber } from 'joy-react-broadcast';
import PropTypes from 'prop-types';
import is, { isNot, isOr } from 'styled-is';
import isBoolean from 'lodash.isboolean';
import remcalc from 'remcalc';
import Baseline from '../baseline';
import Card, { BaseCard } from './card';
const BaseHeader = BaseCard.extend`
flex-direction: row;
z-index: 1;
line-height: ${remcalc(24)};
height: auto;
margin: ${remcalc(-1)} ${remcalc(-1)} 0 ${remcalc(-1)};
${is('parentCollapsed')`
margin: ${remcalc(-1)};
box-shadow: none;
`};
${isNot('secondary', 'tertiary')`
${is('transparent')`
color: ${props => props.theme.text};
-webkit-text-fill-color: currentcolor;
`};
`};
${is('disabled')`
color: ${props => props.theme.text};
-webkit-text-fill-color: currentcolor;
border-color: ${props => props.theme.grey};
box-shadow: none;
`};
button {
margin-bottom: 0;
margin-top: 0;
}
`;
const BaseBox = BaseCard.extend`
width: ${remcalc(49)};
min-width: ${remcalc(49)};
min-height: ${remcalc(46)};
display: inline-flex;
flex: 0 0 auto;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: transparent;
border-width: 0;
border-radius: 0;
box-shadow: none;
${is('border')`
border-right-width: ${props => (props.border === 'right' ? remcalc(1) : 0)};
border-left-width: ${props => (props.border === 'left' ? remcalc(1) : 0)};
`};
${is('actionable', 'secondary')`
&:hover {
background-color: ${props => props.theme.primaryHover};
}
`};
${is('disabled')`
color: ${props => props.theme.text};
-webkit-text-fill-color: currentcolor;
border-color: ${props => props.theme.grey};
box-shadow: none;
&:hover {
background-color: transparent;
}
`};
`;
const BaseMeta = BaseCard.extend`
box-sizing: border-box;
min-height: ${remcalc(47)};
width: auto;
height: auto;
padding: ${remcalc(12)};
display: inline-flex;
flex: 1 1 auto;
flex-direction: column;
justify-content: center;
align-items: stretch;
align-content: stretch;
overflow: hidden;
background-color: transparent;
border-width: 0;
box-shadow: none;
color: inherit;
`;
export const Box = ({ children, border, actionable, ...rest }) => {
const render = ({ secondary, transparent, parentCollapsed, ...value }) => {
// if parent is collapsed, show border
// if parent is not collapsed, only if this is secondary and not transparent
const showBorder = parentCollapsed || (secondary && !transparent);
const newBorder = showBorder && border;
return (
<BaseBox
{...value}
{...rest}
name="card-header-box"
border={newBorder}
secondary={secondary}
transparent={transparent}
parentCollapsed={parentCollapsed}
actionable={actionable}
collapsed
>
{children}
</BaseBox>
);
};
return <Subscriber channel="card">{render}</Subscriber>;
};
Box.propTypes = {
...Card.propTypes,
children: PropTypes.node,
border: PropTypes.oneOf(['left', 'right'])
};
Box.defaultProps = {
...Card.defaultProps,
children: null,
border: null
};
export const Meta = ({ children, ...rest }) => (
<Subscriber channel="card">
{value => (
<BaseMeta {...rest} {...value} name="card-header-meta" collapsed>
{children}
</BaseMeta>
)}
</Subscriber>
);
const Header = ({ children, transparent, shadow, ...rest }) => {
const render = ({ secondary, tertiary, collapsed, actionable, ...value }) => {
const parentPrimary = !secondary && !tertiary;
// if secondary is hardcoded, use that
// if transparent and parent is secondary, keep seconday
// if parent is secondary, keep being secondary or
// if parent is primary, become secondary
const isSecondary = isBoolean(rest.secondary)
? rest.secondary
: transparent ? secondary : secondary || parentPrimary;
// if parent is primary, don't become transparent
const isTransparent = transparent || secondary || tertiary;
const newValue = {
...value,
parentCollapsed: collapsed,
secondary: isSecondary,
tertiary: isBoolean(rest.tertiary) ? rest.tertiary : tertiary,
actionable: isBoolean(rest.actionable) ? rest.actionable : actionable,
transparent: isTransparent,
collapsed: true,
shadow: Boolean(shadow)
};
return (
<Broadcast channel="card" value={newValue}>
<BaseHeader
{...rest}
{...newValue}
name="card-header"
parentCollapsed={collapsed}
shadow={shadow}
>
{children}
</BaseHeader>
</Broadcast>
);
};
return <Subscriber channel="card">{render}</Subscriber>;
};
Header.propTypes = {
children: PropTypes.node
};
Header.defaultProps = {
children: null
};
export default Baseline(Header);