Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V10 card #1861

Draft
wants to merge 17 commits into
base: master
Choose a base branch
from
Draft
72 changes: 72 additions & 0 deletions packages/zent/__tests__/card.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,76 @@ describe('Card', () => {
const cardBody = card.find('.zent-card-body');
expect(cardBody.prop('style').background).toBe('blue');
});
it('should render borderless card', () => {
const card = shallow(
<Card bordered={false}>
<p>card items</p>
</Card>
);
expect(card.find('.zent-card--borderless').length).toBe(1);
});
it('card loading', () => {
const card = shallow(
<Card loading>
<p>card items</p>
</Card>
);
expect(card.find('TextBlock').length).toBe(1);
});
});

describe('Small Card', () => {
it('should render children in card-body', () => {
const card = shallow(
<Card size="small">
<p>card items</p>
</Card>
);
expect(card.find('.zent-card-body').children().length).toBe(1);
});
it('should only render title in header', () => {
const card = shallow(
<Card size="small" title="card title">
card items
</Card>
);
expect(card.find('.zent-card-header__action').length).toBe(0);
expect(card.find('.zent-card-header').text()).toBe('card title');
expect(card.find('.zent-card-body').text()).toBe('card items');
});
it('should render left extra', () => {
const card = shallow(
<Card size="small" leftExtra="left extra">
<p>card items</p>
</Card>
);
expect(card.find('.zent-card__left-extra').length).toBe(1);
expect(card.find('.zent-card__left-extra').text()).toBe('left extra');
});
it('should render right extra', () => {
const card = shallow(
<Card size="small" rightExtra="right extra">
<p>card items</p>
</Card>
);
expect(card.find('.zent-card__right-extra').length).toBe(1);
expect(card.find('.zent-card__right-extra').text()).toBe('right extra');
});
it('should render bottom extra', () => {
const card = shallow(
<Card size="small" bottomExtra="bottom extra">
<p>card items</p>
</Card>
);
expect(card.find('.zent-card__bottom-extra').length).toBe(1);
expect(card.find('.zent-card__bottom-extra').text()).toBe('bottom extra');
});
it('small card loading', () => {
const card = shallow(
<Card size="small" loading>
<p>card items</p>
</Card>
);
expect(card.find('TextBlock').length).toBe(1);
});
});
21 changes: 21 additions & 0 deletions packages/zent/assets/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,13 @@ $btn-warning-active: 1;
&.zent-btn-text {
@include theme-color(background-color, primary, 4, 0.03);
}

&.zent-btn-icon {
background: transparent;
}
&.zent-btn-text {
@include theme-color(background-color, primary, 4, 0.03);
}
}

&[type='button'],
Expand Down Expand Up @@ -489,6 +496,20 @@ $btn-warning-active: 1;
@include theme-color(border-top-color, stroke, 1);
@include theme-color(border-right-color, stroke, 1);
}

&.zent-btn-small::after,
&.zent-btn-text::after {
width: 12px;
height: 12px;
margin-left: -6px;
margin-top: -6px;
border-radius: 6px;
}

&.zent-btn-icon::after {
border-top-color: $text-300;
border-right-color: $text-300;
}
}

&#{&}-border-transparent {
Expand Down
66 changes: 56 additions & 10 deletions packages/zent/assets/card.scss
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
@import './theme/default';
@import './theme/font';
@import './theme/timing-functions';

.zent-card {
@include theme-color(background-color, stroke, 9);
@include theme-color(border-color, stroke, 6);
border-radius: 2px;
border-radius: 4px;
position: relative;
border-width: 1px;
border-style: solid;
overflow: hidden;

&:not(.zent-card--borderless) {
border-width: 1px;
border-style: solid;
}

&-header {
@include theme-color(border-bottom-color, stroke, 6);
height: 48px;
padding: 0 20px;
border-bottom-width: 1px;
border-bottom-style: solid;
padding: 24px 24px 0;
box-sizing: border-box;
display: flex;
justify-content: flex-end;
align-items: center;
font-weight: 500;
font-weight: 600;

&__title {
@include theme-color(color, stroke, 1);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: 100%;
line-height: 26px;
}

&__action {
Expand All @@ -36,12 +38,12 @@
}

&-body {
padding: 20px;
margin: 24px;
}

&--normal {
.zent-card-header {
font-size: $font-size-large;
font-size: $font-size-h4;
}

.zent-card-body {
Expand All @@ -53,6 +55,50 @@
.zent-card-header {
@include theme-color(background-color, stroke, 8);
font-size: $font-size-normal;
padding-top: 12px;
padding-bottom: 12px;
}
}

&--small {
padding: 8px;
border-radius: 4px;
display: flex;
width: fit-content;
box-sizing: border-box;
cursor: pointer;
border: 1px solid transparent;
transition: border-color 100ms $timing-fn-linear;

&:hover {
@include theme-color(border-color, primary, 4);
}

.zent-card__left-extra {
margin-right: 8px;
}

.zent-card__right-extra {
flex-grow: 1;
display: flex;
flex-direction: row-reverse;
align-items: center;
}

.zent-card__content {
.zent-card-header {
display: block;
padding: 0;
font-size: $font-size-normal;
font-weight: 400;
}

.zent-card-body {
@include theme-color(color, stroke, 3);
padding: 0;
margin: 0;
font-size: $font-size-small;
}
}
}
}
42 changes: 42 additions & 0 deletions packages/zent/src/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import cx from 'classnames';
import Placeholder from '../placeholder';
import isNil from '../utils/isNil';

export type CardSize = 'large' | 'small';

export interface ICardProps {
type?: 'normal' | 'nested';
title?: React.ReactNode;
Expand All @@ -11,6 +13,11 @@ export interface ICardProps {
bodyStyle?: React.CSSProperties;
loading?: boolean;
className?: string;
size?: CardSize;
bordered?: boolean;
leftExtra?: React.ReactNode;
rightExtra?: React.ReactNode;
bottomExtra?: React.ReactNode;
}

export class Card extends Component<ICardProps> {
Expand All @@ -20,6 +27,8 @@ export class Card extends Component<ICardProps> {
bodyStyle: {},
loading: false,
className: '',
size: 'large',
bordered: true,
};

render() {
Expand All @@ -32,16 +41,49 @@ export class Card extends Component<ICardProps> {
children,
className,
bodyStyle,
bordered,
size,
leftExtra,
rightExtra,
bottomExtra,
} = this.props;

const isValidTitle = !isNil(title);
const isValidAction = !isNil(action);

if (size === 'small') {
return (
<div
className={cx('zent-card', 'zent-card--small', className, {
'zent-card--borderless': !bordered,
})}
style={style}
>
{leftExtra && (
<div className="zent-card__left-extra">{leftExtra}</div>
)}
<div className="zent-card__content">
{isValidTitle && <div className="zent-card-header">{title}</div>}
<div className="zent-card-body" style={bodyStyle}>
{loading ? <Placeholder.TextBlock rows={1} /> : children}
</div>
{bottomExtra && (
<div className="zent-card__bottom-extra">{bottomExtra}</div>
)}
</div>
{rightExtra && (
<div className="zent-card__right-extra">{rightExtra}</div>
)}
</div>
);
}

return (
<div
className={cx('zent-card', className, {
'zent-card--normal': type === 'normal',
'zent-card--nested': type === 'nested',
'zent-card--borderless': !bordered,
})}
style={style}
>
Expand Down
41 changes: 29 additions & 12 deletions packages/zent/src/card/README_en-US.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
---
title: Card
path: component/card
group: Data Display
group: Container
scatter: true
---

## Card

Card is used for information displayed on the card container.
The most basic information container, a rounded rectangle, is visually defined as a single unit of information.

### Guides

- Control whether to display title by `title`
- Provide interactive operation through `action`
- Customize content style through `bodyStyle`
- Customize content style through `bodyStyle`

### Demos

<!-- demo-slot-2 -->
<!-- demo-slot-3 -->
<!-- demo-slot-4 -->
<!-- demo-slot-6 -->

### API

| Props | Description | Type | Default | Alternative |
| --------- | ------- | ------ | ---- |-----|
| title | Card's title | `node` | | |
| action | Card's operation | `node` | | |
| loading | Loading state | `bool` | `false` | `true` |
| type | Card type | string | `'normal'` | `'nested'` |
| style | Custom style of the card container | `object` | `{}` | |
| bodyStyle | Custom style of the content area | `object` | `{}` | |
| className | Custom calssname | `string` | `''` | |
| Props | Description | Type | Default | Alternative |
| ----------- | ------------------------------------------------------------------------- | -------- | ---------- | ----------- |
| title | Card's title | `node` | | |
| action | Card's operation | `node` | | |
| loading | Loading state | `bool` | `false` | `true` |
| type | Card type | string | `'normal'` | `'nested'` |
| style | Custom style of the card container | `object` | `{}` | |
| bodyStyle | Custom style of the content area | `object` | `{}` | |
| className | Custom calssname | `string` | `''` | |
| size | Card Size | `string` | `'large'` | `'small'` |
| leftExtra | Custom content on the left side of the card (only for small size cards) | `node` | | |
| rightExtra | Custom content on the right side of the card (only for small size cards) | `node` | | |
| bottomExtra | Custom content on the bottom side of the card (only for small size cards) | `node` | | |

#### The following functions is obsolete in the new design system and is only used as a reference for the old version

<!-- demo-slot-1 -->
<!-- demo-slot-5 -->
Loading