Add to prop support on v-button (#111)

This commit is contained in:
Rijk van Zanten
2020-02-19 12:24:19 -05:00
committed by GitHub
parent 61311c13bb
commit a16569f45d
4 changed files with 55 additions and 24 deletions

View File

@@ -46,37 +46,33 @@ The button has a loading state that can be enabled with the `loading` prop. By d
The loading slot is rendered _on top_ of the content that was there before. Make sure that your loading content doesn't exceed the size of the default state content. This restriction is put in place to prevent jumps when going from and to the loading state.
## Props
| Prop | Description | Default |
|--------------------------|---------------------------------------------------------------------------|-------------------------------------------|
| `block` | Enable ull width (display block) | `false` |
| `icon` | Remove padding / min-width. Meant to be used with just an icon as content | `false` |
| `outlined` | No background | `false` |
| `rounded` | Enable rounded corners | `false` |
| `type` | HTML `type` attribute | `button` |
| `disabled` | Disabled state | `false` |
| `loading` | Loading state | `false` |
| `size` | Size of the text in the button in px | -- |
| `x-small` | Render extra small | `false` |
| `small` | Render small | `false` |
| `large` | Render large | `false` |
| `x-large` | Render extra large | `false` |
| Prop | Description | Default |
|------------|---------------------------------------------------------------------------|----------|
| `block` | Enable ull width (display block) | `false` |
| `icon` | Remove padding / min-width. Meant to be used with just an icon as content | `false` |
| `outlined` | No background | `false` |
| `rounded` | Enable rounded corners | `false` |
| `type` | HTML `type` attribute | `button` |
| `disabled` | Disabled state | `false` |
| `loading` | Loading state | `false` |
| `x-small` | Render extra small | `false` |
| `small` | Render small | `false` |
| `large` | Render large | `false` |
| `x-large` | Render extra large | `false` |
| `to` | Render as vue router-link | `false` |
## Slots
| Slot | Description |
|-----------|----------------------------------------------|
| _default_ | Button content |
| _default_ | Button content |
| `loading` | Content that's rendered during loading state |
## Events
| Event | Description | Value |
|---------|-----------------------|--------------|
| `click` | User clicks on button | `MouseEvent` |
## CSS Variables
| Variable | Default |
|-------------------------------------|------------------------------------------------|
| `--v-button-width` | `auto` |

View File

@@ -12,9 +12,13 @@ import VButton from './v-button.vue';
import VIcon from '../v-icon/';
import markdown from './v-button.readme.md';
import withPadding from '../../../.storybook/decorators/with-padding';
import VueRouter from 'vue-router';
Vue.component('v-button', VButton);
Vue.component('v-icon', VIcon);
Vue.use(VueRouter);
const router = new VueRouter();
export default {
title: 'Components / Button',
@@ -302,3 +306,10 @@ export const customLoading = () => ({
</template>
</v-button>`
});
export const asLink = () => ({
router: router,
template: `
<v-button to="/login">I'm a link</v-button>
`
});

View File

@@ -106,4 +106,15 @@ describe('Button', () => {
component.find('button').trigger('click');
expect(component.emitted()).toEqual({});
});
it('Renders as a router-link if the to prop is set', () => {
const component = mount(VButton, {
localVue,
propsData: {
to: '/login'
}
});
expect((component.vm as any).component).toBe('router-link');
});
});

View File

@@ -1,9 +1,11 @@
<template>
<button
<component
:is="component"
class="v-button"
:class="[sizeClass, { block, rounded, icon, outlined, loading }]"
:type="type"
:disabled="disabled"
:to="to"
@click="onClick"
>
<span class="content" :class="{ invisible: loading }"><slot /></span>
@@ -12,11 +14,12 @@
<v-progress-circular :x-small="xSmall" :small="small" indeterminate />
</slot>
</div>
</button>
</component>
</template>
<script lang="ts">
import { createComponent, reactive, computed, Ref } from '@vue/composition-api';
import { createComponent, reactive, computed, Ref, PropType } from '@vue/composition-api';
import { Location } from 'vue-router';
import parseCSSVar from '@/utils/parse-css-var';
import useSizeClass, { sizeProps } from '@/compositions/size-class';
@@ -50,12 +53,18 @@ export default createComponent({
type: Boolean,
default: false
},
to: {
type: [String, Object] as PropType<string | Location>,
default: null
},
...sizeProps
},
setup(props, { emit }) {
const sizeClass = useSizeClass(props);
return { sizeClass, onClick };
const component = computed<string>(() => (props.to ? 'router-link' : 'button'));
return { sizeClass, onClick, component };
function onClick(event: MouseEvent) {
if (props.loading === true) return;
@@ -76,6 +85,9 @@ export default createComponent({
--v-button-font-size: 16px;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: var(--v-button-width);
min-width: 78px;
height: var(--v-button-height);
@@ -83,6 +95,7 @@ export default createComponent({
color: var(--v-button-color);
font-weight: 500;
font-size: var(--v-button-font-size);
text-decoration: none;
background-color: var(--v-button-background-color);
border: var(--button-border-width) solid var(--v-button-background-color);
border-radius: var(--button-border-radius);
@@ -179,7 +192,7 @@ export default createComponent({
.content {
position: relative;
top: -1;
top: -1px;
&.invisible {
opacity: 0;