Component improvement & adjustments

This commit is contained in:
cristij 2018-10-07 22:32:30 +03:00
parent a6421f4a51
commit 69f7d9a8e8
17 changed files with 334 additions and 105 deletions

View File

@ -19,7 +19,7 @@
import { FadeTransition } from 'vue2-transitions'; import { FadeTransition } from 'vue2-transitions';
export default { export default {
name: 'alert', name: 'base-alert',
components: { components: {
FadeTransition FadeTransition
}, },

View File

@ -1,18 +1,20 @@
<template> <template>
<component <component
:is="tag" :is="tag"
:type="nativeType" :type="tag === 'button' ? nativeType : ''"
:disabled="disabled || loading" :disabled="disabled || loading"
@click="handleClick" @click="handleClick"
class="btn" class="btn"
:class="[ :class="[
{'btn-round': round}, {'btn-round': round},
{'btn-block': block}, {'btn-block': block},
{'btn-icon': icon}, {'btn-icon btn-fab': icon},
{[`btn-${type}`]: type && !outline}, {[`btn-${type}`]: type && !outline},
{[`btn-outline-${type}`]: type && outline}, {[`btn-outline-${type}`]: type && outline},
{[`btn-${size}`]: size}, {[`btn-${size}`]: size},
{'btn-link': simple} {'btn-simple': simple},
{'btn-link': link},
{'disabled': disabled && tag !== 'button'}
]"> ]">
<slot name="loading"> <slot name="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i> <i v-if="loading" class="fa fa-spinner fa-spin"></i>
@ -46,7 +48,8 @@ export default {
type: String, type: String,
default: "" default: ""
}, },
simple: Boolean simple: Boolean,
link: Boolean,
}, },
methods: { methods: {
handleClick(evt) { handleClick(evt) {

View File

@ -16,9 +16,9 @@
</template> </template>
<script> <script>
export default { export default {
name: 'base-checkbox', name: "base-checkbox",
model: { model: {
prop: 'checked' prop: "checked"
}, },
props: { props: {
checked: [Array, Boolean], checked: [Array, Boolean],

View File

@ -4,17 +4,19 @@
:class="{show:isOpen}" :class="{show:isOpen}"
@click="toggleDropDown" @click="toggleDropDown"
v-click-outside="closeDropDown"> v-click-outside="closeDropDown">
<a class="dropdown-toggle btn-rotate" <slot name="title-container" :is-open="isOpen">
:class="titleClasses" <component
:aria-expanded="isOpen" :is="titleTag"
data-toggle="dropdown"> class="dropdown-toggle btn-rotate"
<slot name="title"> :class="titleClasses"
<i :class="icon"></i> :aria-expanded="isOpen"
<span class="notification">{{title}} data-toggle="dropdown">
<b class="caret"></b> <slot name="title" :is-open="isOpen">
</span> <i :class="icon"></i>
</slot> {{title}}
</a> </slot>
</component>
</slot>
<ul class="dropdown-menu" :class="[{show:isOpen}, {'dropdown-menu-right': menuOnRight}, menuClasses]"> <ul class="dropdown-menu" :class="[{show:isOpen}, {'dropdown-menu-right': menuOnRight}, menuClasses]">
<slot></slot> <slot></slot>
</ul> </ul>
@ -22,11 +24,15 @@
</template> </template>
<script> <script>
export default { export default {
name: 'base-dropdown', name: "base-dropdown",
props: { props: {
tag: { tag: {
type: String, type: String,
default: "li" default: "div"
},
titleTag: {
type: String,
default: "button"
}, },
title: String, title: String,
icon: String, icon: String,

97
src/components/BaseNav.vue Executable file
View File

@ -0,0 +1,97 @@
<template>
<nav class="navbar"
:class="[
{'navbar-expand-lg': expand},
{[`navbar-${effect}`]: effect},
{'navbar-transparent': transparent},
{[`bg-${type}`]: type},
{'rounded': round}
]">
<div class="container">
<slot name="container-pre"></slot>
<slot name="brand">
<a class="navbar-brand" href="#" @click.prevent="onTitleClick">
{{title}}
</a>
</slot>
<navbar-toggle-button :toggled="toggled"
:target="contentId"
@click.native.stop="toggled = !toggled">
</navbar-toggle-button>
<slot name="container-after"></slot>
<div class="collapse navbar-collapse" :class="{show: toggled}" :id="contentId" v-click-outside="closeMenu">
<div class="navbar-collapse-header">
<slot name="content-header" :close-menu="closeMenu"></slot>
</div>
<slot :close-menu="closeMenu"></slot>
</div>
</div>
</nav>
</template>
<script>
import { FadeTransition } from "vue2-transitions";
import NavbarToggleButton from "./NavbarToggleButton";
export default {
name: "base-nav",
components: {
FadeTransition,
NavbarToggleButton
},
props: {
type: {
type: String,
default: "primary",
description: "Navbar type (e.g default, primary etc)"
},
title: {
type: String,
default: "",
description: "Title of navbar"
},
contentId: {
type: [String, Number],
default: Math.random().toString(),
description:
"Explicit id for the menu. By default it's a generated random number"
},
effect: {
type: String,
default: "dark",
description: "Effect of the navbar (light|dark)"
},
round: {
type: Boolean,
default: false,
description: "Whether nav has rounded corners"
},
transparent: {
type: Boolean,
default: false,
description: "Whether navbar is transparent"
},
expand: {
type: Boolean,
default: false,
description: "Whether navbar should contain `navbar-expand-lg` class"
}
},
data() {
return {
toggled: false
};
},
methods: {
onTitleClick(evt) {
this.$emit("title-click", evt);
},
closeMenu() {
this.toggled = false;
}
}
};
</script>
<style>
</style>

63
src/components/BaseRadio.vue Executable file
View File

@ -0,0 +1,63 @@
<template>
<div class="form-check form-check-radio" :class="[inlineClass, {disabled: disabled}]">
<label :for="cbId" class="form-check-label">
<input :id="cbId"
class="form-check-input"
type="radio"
:disabled="disabled"
:value="name"
v-model="model" />
<slot></slot>
<span class="form-check-sign"></span>
</label>
</div>
</template>
<script>
export default {
name: "base-radio",
props: {
name: {
type: [String, Number],
description: "Radio label"
},
disabled: {
type: Boolean,
description: "Whether radio is disabled"
},
value: {
type: [String, Boolean],
description: "Radio value"
},
inline: {
type: Boolean,
description: "Whether radio is inline"
}
},
data() {
return {
cbId: ""
};
},
computed: {
model: {
get() {
return this.value;
},
set(value) {
this.$emit("input", value);
}
},
inlineClass() {
if (this.inline) {
return `form-check-inline`;
}
return "";
}
},
created() {
this.cbId = Math.random()
.toString(16)
.slice(2);
}
};
</script>

View File

@ -1,11 +1,11 @@
<template> <template>
<table class="table tablesorter" :class="tableClass"> <table class="table tablesorter" :class="tableClass">
<thead :class="theadClasses"> <thead :class="theadClasses">
<slot name="columns"> <tr>
<tr> <slot name="columns">
<th v-for="column in columns" :key="column">{{column}}</th> <th v-for="column in columns" :key="column">{{column}}</th>
</tr> </slot>
</slot> </tr>
</thead> </thead>
<tbody :class="tbodyClasses"> <tbody :class="tbodyClasses">
<tr v-for="(item, index) in data" :key="index"> <tr v-for="(item, index) in data" :key="index">

View File

@ -12,6 +12,9 @@
<div class="card-body" v-if="$slots.default"> <div class="card-body" v-if="$slots.default">
<slot></slot> <slot></slot>
</div> </div>
<div class="card-image" v-if="$slots['image-bottom']">
<slot name="image-bottom"></slot>
</div>
<slot name="raw-content"></slot> <slot name="raw-content"></slot>
<div class="card-footer" v-if="$slots.footer"> <div class="card-footer" v-if="$slots.footer">
<slot name="footer"></slot> <slot name="footer"></slot>

34
src/components/CloseButton.vue Executable file
View File

@ -0,0 +1,34 @@
<template>
<button type="button" class="navbar-toggler"
data-toggle="collapse"
@click="handleClick"
:data-target="`#${target}`"
:aria-controls="target"
:aria-expanded="expanded"
aria-label="Toggle navigation">
<span></span>
<span></span>
</button>
</template>
<script>
export default {
name: "close-button",
props: {
target: {
type: [String, Number],
description: "Close button target element"
},
expanded: {
type: Boolean,
description: "Whether button is expanded (aria-expanded attribute)"
}
},
methods: {
handleClick(evt) {
this.$emit("click", evt);
}
}
};
</script>
<style>
</style>

View File

@ -1,5 +1,9 @@
<template> <template>
<div class="form-group" :class="{'input-group': hasIcon}"> <div class="form-group"
:class="{
'input-group': hasIcon,
'input-group-focus': focused
}">
<slot name="label"> <slot name="label">
<label v-if="label" class="control-label"> <label v-if="label" class="control-label">
{{label}} {{label}}
@ -7,38 +11,71 @@
</slot> </slot>
<slot name="addonLeft"> <slot name="addonLeft">
<span v-if="addonLeftIcon" class="input-group-prepend"> <span v-if="addonLeftIcon" class="input-group-prepend">
<i :class="addonLeftIcon" class="input-group-text"></i> <div class="input-group-text">
<i :class="addonLeftIcon"></i>
</div>
</span> </span>
</slot> </slot>
<slot> <slot>
<input <input
:value="value" :value="value"
@input="$emit('input',$event.target.value)"
v-bind="$attrs" v-bind="$attrs"
v-on="listeners"
class="form-control" class="form-control"
aria-describedby="addon-right addon-left"> aria-describedby="addon-right addon-left">
</slot> </slot>
<slot name="addonRight"> <slot name="addonRight">
<span v-if="addonRightIcon" class="input-group-append"> <span v-if="addonRightIcon" class="input-group-append">
<i :class="addonRightIcon" class="input-group-text"></i> <div class="input-group-text">
<i :class="addonRightIcon"></i>
</div>
</span> </span>
</slot> </slot>
<slot name="helperText"></slot>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
inheritAttrs: false, inheritAttrs: false,
name: "fg-input", name: "base-input",
props: { props: {
label: String, label: String,
value: [String, Number], value: [String, Number],
addonRightIcon: String, addonRightIcon: String,
addonLeftIcon: String addonLeftIcon: String
}, },
model: {
prop: 'value',
event: 'input'
},
data() {
return {
focused: false
}
},
computed: { computed: {
hasIcon() { hasIcon() {
const { addonRight, addonLeft } = this.$slots; const { addonRight, addonLeft } = this.$slots;
return addonRight !== undefined || addonLeft !== undefined || this.addonRightIcon !== undefined || this.addonLeftIcon !== undefined; return addonRight !== undefined || addonLeft !== undefined || this.addonRightIcon !== undefined || this.addonLeftIcon !== undefined;
},
listeners() {
return {
...this.$listeners,
input: this.onInput,
blur: this.onBlur,
focus: this.onFocus
}
}
},
methods: {
onInput(evt) {
this.$emit('input', evt.target.value)
},
onFocus() {
this.focused = true;
},
onBlur() {
this.focused = false;
} }
} }
} }

View File

@ -0,0 +1,27 @@
<template>
<button class="navbar-toggler" type="button"
data-toggle="collapse"
:data-target="target"
:aria-controls="target"
:aria-expanded="toggled"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</template>
<script>
export default {
props: {
target: {
type: [String, Number],
description: "Button target element"
},
toggled: {
type: Boolean,
default: false,
description: "Whether button is toggled"
}
}
};
</script>
<style>
</style>

View File

@ -1,44 +0,0 @@
<template>
<div class="moving-arrow" :style="arrowStyle">
</div>
</template>
<script>
export default {
props: {
moveY: {
type: Number,
default: 0
}
},
computed: {
/**
* Styles to animate the arrow
* @returns {{transform: string}}
*/
arrowStyle() {
return {
transform: `translate3d(0px, ${this.moveY}px, 0px)`
};
}
}
};
</script>
<style lang="scss">
$bg-nude: #f4f3ef !default;
.moving-arrow {
border-right: 17px solid $bg-nude;
border-top: 17px solid transparent;
border-bottom: 17px solid transparent;
display: inline-block;
position: absolute;
left: 243px;
top: 95px;
transition: all 0.5s cubic-bezier(0.29, 1.42, 0.79, 1);
}
@media (max-width: 992px) {
.moving-arrow {
display: none;
}
}
</style>

View File

@ -33,14 +33,10 @@
</sidebar-link> </sidebar-link>
</slot> </slot>
</ul> </ul>
<moving-arrow :move-y="arrowMovePx">
</moving-arrow>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import MovingArrow from "./MovingArrow.vue";
import SidebarLink from "./SidebarLink"; import SidebarLink from "./SidebarLink";
export default { export default {
@ -88,7 +84,6 @@
}; };
}, },
components: { components: {
MovingArrow,
SidebarLink SidebarLink
}, },
computed: { computed: {

View File

@ -1,10 +1,14 @@
import FormGroupInput from "./Inputs/formGroupInput.vue"; import BaseInput from "./Inputs/BaseInput.vue";
import BaseCheckbox from "./BaseCheckbox.vue"; import BaseCheckbox from "./BaseCheckbox.vue";
import BaseRadio from "./BaseRadio.vue";
import BaseDropdown from "./BaseDropdown.vue"; import BaseDropdown from "./BaseDropdown.vue";
import BaseTable from "./BaseTable.vue"; import BaseTable from "./BaseTable.vue";
import BaseButton from "./BaseButton"; import BaseButton from "./BaseButton";
import BaseAlert from "./BaseAlert"; import BaseAlert from "./BaseAlert";
import BaseNav from "./BaseNav";
import Modal from "./Modal";
import CloseButton from "./CloseButton";
import Card from "./Cards/Card.vue"; import Card from "./Cards/Card.vue";
import StatsCard from "./Cards/StatsCard.vue"; import StatsCard from "./Cards/StatsCard.vue";
@ -12,13 +16,17 @@ import StatsCard from "./Cards/StatsCard.vue";
import SidebarPlugin from "./SidebarPlugin/index"; import SidebarPlugin from "./SidebarPlugin/index";
export { export {
FormGroupInput, BaseInput,
Card, Card,
Modal,
CloseButton,
StatsCard, StatsCard,
BaseTable, BaseTable,
BaseCheckbox, BaseCheckbox,
BaseRadio,
BaseDropdown, BaseDropdown,
BaseButton, BaseButton,
BaseAlert, BaseAlert,
SidebarPlugin SidebarPlugin,
BaseNav
}; };

View File

@ -41,7 +41,7 @@
:show-close="true"> :show-close="true">
<input slot="header" type="text" class="form-control" id="inlineFormInputGroup" placeholder="SEARCH"> <input slot="header" type="text" class="form-control" id="inlineFormInputGroup" placeholder="SEARCH">
</modal> </modal>
<base-dropdown class="nav-item" menu-on-right> <base-dropdown tag="li" title-tag="a" class="nav-item" menu-on-right>
<a slot="title" href="#" class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="true"> <a slot="title" href="#" class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="true">
<div class="notification d-none d-lg-block d-xl-block"></div> <div class="notification d-none d-lg-block d-xl-block"></div>
<i class="tim-icons icon-sound-wave"></i> <i class="tim-icons icon-sound-wave"></i>
@ -65,7 +65,7 @@
<a href="#" class="nav-item dropdown-item">Another one</a> <a href="#" class="nav-item dropdown-item">Another one</a>
</li> </li>
</base-dropdown> </base-dropdown>
<base-dropdown class="nav-item" menu-classes="dropdown-navbar"> <base-dropdown tag="li" title-tag="a" class="nav-item" menu-classes="dropdown-navbar">
<a slot="title" href="#" class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="true"> <a slot="title" href="#" class="dropdown-toggle nav-link" data-toggle="dropdown" aria-expanded="true">
<div class="photo"> <div class="photo">
<img src="/img/anime3.png"> <img src="/img/anime3.png">

View File

@ -3,69 +3,69 @@
<h5 slot="header" class="title">Edit Profile</h5> <h5 slot="header" class="title">Edit Profile</h5>
<div class="row"> <div class="row">
<div class="col-md-5 pr-md-1"> <div class="col-md-5 pr-md-1">
<fg-input label="Company (disabled)" <base-input label="Company (disabled)"
placeholder="Company" placeholder="Company"
v-model="model.company" v-model="model.company"
disabled> disabled>
</fg-input> </base-input>
</div> </div>
<div class="col-md-3 px-md-1"> <div class="col-md-3 px-md-1">
<fg-input label="Username" <base-input label="Username"
placeholder="Username" placeholder="Username"
v-model="model.username"> v-model="model.username">
</fg-input> </base-input>
</div> </div>
<div class="col-md-4 pl-md-1"> <div class="col-md-4 pl-md-1">
<fg-input label="Email address" <base-input label="Email address"
type="email" type="email"
placeholder="mike@email.com"> placeholder="mike@email.com">
</fg-input> </base-input>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6 pr-md-1"> <div class="col-md-6 pr-md-1">
<fg-input label="First Name" <base-input label="First Name"
v-model="model.firstName" v-model="model.firstName"
placeholder="First Name"> placeholder="First Name">
</fg-input> </base-input>
</div> </div>
<div class="col-md-6 pl-md-1"> <div class="col-md-6 pl-md-1">
<fg-input label="Last Name" <base-input label="Last Name"
v-model="model.lastName" v-model="model.lastName"
placeholder="Last Name"> placeholder="Last Name">
</fg-input> </base-input>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<fg-input label="Address" <base-input label="Address"
v-model="model.address" v-model="model.address"
placeholder="Home Address"> placeholder="Home Address">
</fg-input> </base-input>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-4 pr-md-1"> <div class="col-md-4 pr-md-1">
<fg-input label="City" <base-input label="City"
v-model="model.city" v-model="model.city"
placeholder="City"> placeholder="City">
</fg-input> </base-input>
</div> </div>
<div class="col-md-4 px-md-1"> <div class="col-md-4 px-md-1">
<fg-input label="Country" <base-input label="Country"
v-model="model.country" v-model="model.country"
placeholder="Country"> placeholder="Country">
</fg-input> </base-input>
</div> </div>
<div class="col-md-4 pl-md-1"> <div class="col-md-4 pl-md-1">
<fg-input label="Postal Code" <base-input label="Postal Code"
placeholder="ZIP Code"> placeholder="ZIP Code">
</fg-input> </base-input>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<fg-input> <base-input>
<label>About Me</label> <label>About Me</label>
<textarea rows="4" cols="80" <textarea rows="4" cols="80"
class="form-control" class="form-control"
@ -73,7 +73,7 @@
v-model="model.about"> v-model="model.about">
</textarea> </textarea>
</fg-input> </base-input>
</div> </div>
</div> </div>
<base-button slot="footer" type="primary" fill>Save</base-button> <base-button slot="footer" type="primary" fill>Save</base-button>

View File

@ -1,11 +1,11 @@
import { FormGroupInput, Card, BaseDropdown, BaseButton, BaseCheckbox } from "../components/index"; import { BaseInput, Card, BaseDropdown, BaseButton, BaseCheckbox } from "../components/index";
/** /**
* You can register global components here and use them as a plugin in your main Vue instance * You can register global components here and use them as a plugin in your main Vue instance
*/ */
const GlobalComponents = { const GlobalComponents = {
install(Vue) { install(Vue) {
Vue.component(FormGroupInput.name, FormGroupInput); Vue.component(BaseInput.name, BaseInput);
Vue.component(Card.name, Card); Vue.component(Card.name, Card);
Vue.component(BaseDropdown.name, BaseDropdown); Vue.component(BaseDropdown.name, BaseDropdown);
Vue.component(BaseButton.name, BaseButton); Vue.component(BaseButton.name, BaseButton);