[new feature] GoodsAction: update style (#3967)

This commit is contained in:
neverland 2019-07-25 20:13:21 +08:00 committed by GitHub
parent d3178c85d7
commit c72ac6edcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 156 additions and 178 deletions

View File

@ -0,0 +1,59 @@
import { createNamespace } from '../utils';
import { route, routeProps } from '../utils/router';
import { ChildrenMixin } from '../mixins/relation';
import Button from '../button';
const [createComponent, bem] = createNamespace('goods-action-button');
export default createComponent({
mixins: [ChildrenMixin('vanGoodsAction')],
props: {
...routeProps,
type: String,
text: String,
loading: Boolean,
disabled: Boolean
},
computed: {
isFirst() {
const prev = this.parent && this.parent.children[this.index - 1];
return !prev || prev.$options.name !== this.$options.name;
},
isLast() {
const next = this.parent && this.parent.children[this.index + 1];
return !next || next.$options.name !== this.$options.name;
}
},
methods: {
onClick(event) {
this.$emit('click', event);
route(this.$router, this);
}
},
render(h) {
return (
<Button
class={bem([
{
first: this.isFirst,
last: this.isLast
},
this.type
])}
square
size="large"
type={this.type}
loading={this.loading}
disabled={this.disabled}
onClick={this.onClick}
>
{this.slots() || this.text}
</Button>
);
}
});

View File

@ -2,8 +2,33 @@
.van-goods-action-button {
flex: 1;
height: 36px;
font-weight: 500;
font-size: @font-size-md;
line-height: 34px;
border: none;
&--first {
margin-left: 5px;
border-top-left-radius: 18px;
border-bottom-left-radius: 18px;
}
&--last {
margin-right: 5px;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
}
&--warning {
background: linear-gradient(to right, #ffd01e, #ff8917);
}
&--danger {
background: linear-gradient(to right, #ff6034, #ee0a24);
}
@media (max-width: 321px) {
font-size: 15px;
font-size: 13px;
}
}

View File

@ -1,55 +0,0 @@
import { createNamespace } from '../utils';
import Button, { ButtonType, ButtonEvents } from '../button';
import { emit, inherit } from '../utils/functional';
import { functionalRoute, routeProps, RouteProps } from '../utils/router';
// Types
import { CreateElement, RenderContext } from 'vue/types';
import { DefaultSlots } from '../utils/types';
export type GoodsActionButtonProps = RouteProps & {
text?: string;
type?: ButtonType;
primary?: boolean;
loading?: boolean;
disabled?: boolean;
};
const [createComponent, bem] = createNamespace('goods-action-button');
function GoodsActionButton(
h: CreateElement,
props: GoodsActionButtonProps,
slots: DefaultSlots,
ctx: RenderContext<GoodsActionButtonProps>
) {
function onClick(event: Event) {
emit(ctx, 'click', event);
functionalRoute(ctx);
}
return (
<Button
square
class={bem()}
size="large"
type={props.type}
loading={props.loading}
disabled={props.disabled}
onClick={onClick}
{...inherit(ctx)}
>
{slots.default ? slots.default() : props.text}
</Button>
);
}
GoodsActionButton.props = {
...routeProps,
type: String,
text: String,
loading: Boolean,
disabled: Boolean
};
export default createComponent<GoodsActionButtonProps, ButtonEvents>(GoodsActionButton);

View File

@ -0,0 +1,43 @@
import { createNamespace } from '../utils';
import { route, routeProps } from '../utils/router';
import { ChildrenMixin } from '../mixins/relation';
import Icon from '../icon';
const [createComponent, bem] = createNamespace('goods-action-icon');
export default createComponent({
mixins: [ChildrenMixin('vanGoodsAction')],
props: {
...routeProps,
text: String,
icon: String,
info: [Number, String],
iconClass: null
},
methods: {
onClick(event) {
this.$emit('click', event);
route(this.$router, this);
}
},
render(h) {
return (
<div role="button" tabindex="0" class={bem()} onClick={this.onClick}>
{this.slots('icon') ? (
<div class={bem('icon')}>{this.slots('icon')}</div>
) : (
<Icon
class={[bem('icon'), this.iconClass]}
tag="div"
info={this.info}
name={this.icon}
/>
)}
{this.slots() || this.text}
</div>
);
}
});

View File

@ -1,65 +0,0 @@
import { createNamespace } from '../utils';
import Icon, { IconEvents } from '../icon';
import { emit, inherit } from '../utils/functional';
import { functionalRoute, routeProps, RouteProps } from '../utils/router';
// Types
import { CreateElement, RenderContext } from 'vue/types';
import { DefaultSlots, ScopedSlot } from '../utils/types';
export type GoodsActionIconProps = RouteProps & {
icon: string;
text?: string;
info?: string | number;
iconClass?: any;
};
export type GoodsActionIconSlots = DefaultSlots & {
icon?: ScopedSlot;
};
const [createComponent, bem] = createNamespace('goods-action-icon');
function GoodsActionIcon(
h: CreateElement,
props: GoodsActionIconProps,
slots: GoodsActionIconSlots,
ctx: RenderContext<GoodsActionIconProps>
) {
function onClick(event: Event) {
emit(ctx, 'click', event);
functionalRoute(ctx);
}
return (
<div
role="button"
tabindex="0"
class={bem()}
onClick={onClick}
{...inherit(ctx)}
>
{slots.icon ? (
<div class={bem('icon')}>{slots.icon()}</div>
) : (
<Icon
class={[bem('icon'), props.iconClass]}
tag="div"
info={props.info}
name={props.icon}
/>
)}
{slots.default ? slots.default() : props.text}
</div>
);
}
GoodsActionIcon.props = {
...routeProps,
text: String,
icon: String,
info: [Number, String],
iconClass: null as any
};
export default createComponent<GoodsActionIconProps, IconEvents>(GoodsActionIcon);

20
src/goods-action/index.js Normal file
View File

@ -0,0 +1,20 @@
import { createNamespace } from '../utils';
import { ParentMixin } from '../mixins/relation';
const [createComponent, bem] = createNamespace('goods-action');
export default createComponent({
mixins: [ParentMixin('vanGoodsAction')],
props: {
safeAreaInsetBottom: Boolean
},
render(h) {
return (
<div class={bem({ 'safe-area-inset-bottom': this.safeAreaInsetBottom })}>
{this.slots()}
</div>
);
}
});

View File

@ -6,6 +6,7 @@
bottom: 0;
left: 0;
display: flex;
align-items: center;
background-color: @goods-action-background-color;
&--safe-area-inset-bottom {

View File

@ -1,34 +0,0 @@
import { createNamespace } from '../utils';
import { inherit } from '../utils/functional';
// Types
import { CreateElement, RenderContext } from 'vue/types';
import { DefaultSlots } from '../utils/types';
export type GoodsActionProps = {
safeAreaInsetBottom?: boolean;
};
const [createComponent, bem] = createNamespace('goods-action');
function GoodsAction(
h: CreateElement,
props: GoodsActionProps,
slots: DefaultSlots,
ctx: RenderContext
) {
return (
<div
class={bem({ 'safe-area-inset-bottom': props.safeAreaInsetBottom })}
{...inherit(ctx, true)}
>
{slots.default && slots.default()}
</div>
);
}
GoodsAction.props = {
safeAreaInsetBottom: Boolean
};
export default createComponent<GoodsActionProps>(GoodsAction);

View File

@ -13,7 +13,7 @@ exports[`renders demo correctly 1`] = `
<div class="van-icon van-icon-cart-o van-goods-action-icon__icon">
<!---->
</div>购物车
</div> <button class="van-button van-button--warning van-button--large van-button--square van-goods-action-button"><span class="van-button__text">加入购物车</span></button> <button class="van-button van-button--danger van-button--large van-button--square van-goods-action-button"><span class="van-button__text">立即购买</span></button>
</div> <button class="van-button van-button--warning van-button--large van-button--square van-goods-action-button van-goods-action-button--first van-goods-action-button--warning"><span class="van-button__text">加入购物车</span></button> <button class="van-button van-button--danger van-button--large van-button--square van-goods-action-button van-goods-action-button--last van-goods-action-button--danger"><span class="van-button__text">立即购买</span></button>
</div>
</div>
<div>
@ -32,7 +32,7 @@ exports[`renders demo correctly 1`] = `
<div class="van-icon van-icon-shop-o van-goods-action-icon__icon">
<!---->
</div>店铺
</div> <button class="van-button van-button--warning van-button--large van-button--square van-goods-action-button"><span class="van-button__text">加入购物车</span></button> <button class="van-button van-button--danger van-button--large van-button--square van-goods-action-button"><span class="van-button__text">立即购买</span></button>
</div> <button class="van-button van-button--warning van-button--large van-button--square van-goods-action-button van-goods-action-button--first van-goods-action-button--warning"><span class="van-button__text">加入购物车</span></button> <button class="van-button van-button--danger van-button--large van-button--square van-goods-action-button van-goods-action-button--last van-goods-action-button--danger"><span class="van-button__text">立即购买</span></button>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Button render default slot 1`] = `<button class="van-button van-button--default van-button--large van-button--square van-goods-action-button"><span class="van-button__text">Default Content</span></button>`;
exports[`Button render default slot 1`] = `<button class="van-button van-button--default van-button--large van-button--square van-goods-action-button van-goods-action-button--first van-goods-action-button--last"><span class="van-button__text">Default Content</span></button>`;
exports[`Icon render default slot 1`] = `
<div role="button" tabindex="0" class="van-goods-action-icon">

View File

@ -3,31 +3,15 @@ import Icon from '../../goods-action-icon';
import { mount } from '../../../test/utils';
test('Button click event', () => {
const click = jest.fn();
const wrapper = mount(Button, {
context: {
on: {
click
}
}
});
const wrapper = mount(Button);
wrapper.trigger('click');
expect(click).toHaveBeenCalledTimes(1);
expect(wrapper.emitted('click').length).toEqual(1);
});
test('Icon click event', () => {
const click = jest.fn();
const wrapper = mount(Icon, {
context: {
on: {
click
}
}
});
const wrapper = mount(Icon);
wrapper.trigger('click');
expect(click).toHaveBeenCalledTimes(1);
expect(wrapper.emitted('click').length).toEqual(1);
});
test('Button render default slot', () => {