feat: refactor buttons
This commit is contained in:
@@ -11,30 +11,15 @@
|
||||
<!-- text-pink-400 -->
|
||||
<!-- text-red-400 -->
|
||||
<!-- text-yellow-400 -->
|
||||
<span
|
||||
<ButtonSecondary
|
||||
v-for="(color, index) of accentColors"
|
||||
:key="`color-${index}`"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
title="capitalized(color)"
|
||||
class="
|
||||
inline-flex
|
||||
items-center
|
||||
justify-center
|
||||
p-3
|
||||
m-2
|
||||
transition
|
||||
duration-150
|
||||
ease-in-out
|
||||
bg-transparent
|
||||
rounded-full
|
||||
cursor-pointer
|
||||
hover:shadow-none
|
||||
"
|
||||
:title="capitalized(color)"
|
||||
:class="[`text-${color}-400`, { 'bg-primary': color === active }]"
|
||||
@click="setActiveColor(color)"
|
||||
>
|
||||
<i class="material-icons">lens</i>
|
||||
</span>
|
||||
icon="lens"
|
||||
@click.native="setActiveColor(color)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="show-if-initialized" :class="{ initialized }">
|
||||
<div v-if="lang == 'json'" class="outline">
|
||||
<div v-for="(p, index) in currPath" :key="index" class="block">
|
||||
<div class="label" @click="onBlockClick(index)">
|
||||
<div class="label" @click.native="onBlockClick(index)">
|
||||
{{ p }}
|
||||
</div>
|
||||
<i v-if="index + 1 !== currPath.length" class="material-icons"
|
||||
@@ -18,7 +18,7 @@
|
||||
v-for="(sib, i) in currSib"
|
||||
:key="i"
|
||||
class="sib"
|
||||
@click="goToSib(sib)"
|
||||
@click.native="goToSib(sib)"
|
||||
>
|
||||
{{ sib.key ? sib.key.value : i }}
|
||||
</div>
|
||||
@@ -277,7 +277,7 @@ export default {
|
||||
|
||||
.label {
|
||||
@apply p-2;
|
||||
@apply transition;
|
||||
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
class="inline-flex items-center justify-center focus:outline-none"
|
||||
:class="[
|
||||
color
|
||||
? `text-${color}-500 transition hover:text-${color}-600 focus:text-${color}-600`
|
||||
: 'transition hover:text-secondaryDark focus:text-secondaryDark',
|
||||
? `text-${color}-500 hover:text-${color}-600 focus:text-${color}-600`
|
||||
: 'hover:text-secondaryDark focus:text-secondaryDark',
|
||||
{ 'opacity-50 cursor-not-allowed': disabled },
|
||||
{ 'flex-row-reverse': reverse },
|
||||
]"
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
:class="styles"
|
||||
@input="updateSuggestions"
|
||||
@keyup="updateSuggestions"
|
||||
@click="updateSuggestions"
|
||||
@click.native="updateSuggestions"
|
||||
@keydown="handleKeystroke"
|
||||
/>
|
||||
<ul
|
||||
@@ -24,7 +24,7 @@
|
||||
v-for="(suggestion, index) in suggestions"
|
||||
:key="index"
|
||||
:class="{ active: currentSuggestionIndex === index }"
|
||||
@click.prevent="forceSuggestion(suggestion)"
|
||||
@click.native.prevent="forceSuggestion(suggestion)"
|
||||
>
|
||||
{{ suggestion }}
|
||||
</li>
|
||||
@@ -200,7 +200,7 @@ export default {
|
||||
@apply mx-2;
|
||||
@apply left-0;
|
||||
@apply z-50;
|
||||
@apply transition;
|
||||
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
@apply shadow-lg;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<span>
|
||||
<tippy
|
||||
ref="language"
|
||||
tabindex="-1"
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
arrow
|
||||
@@ -9,15 +10,15 @@
|
||||
:animate-fill="false"
|
||||
>
|
||||
<template #trigger>
|
||||
<button v-tippy="{ theme: 'tooltip' }" :title="$t('choose_language')">
|
||||
<span class="mr-2 text-lg">
|
||||
{{
|
||||
$i18n.locales.find(({ code }) => code == $i18n.locale).country
|
||||
| formatCountry
|
||||
}}
|
||||
</span>
|
||||
{{ $i18n.locales.find(({ code }) => code == $i18n.locale).name }}
|
||||
</button>
|
||||
<ButtonSecondary
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="$t('choose_language')"
|
||||
:label="$i18n.locales.find(({ code }) => code == $i18n.locale).name"
|
||||
/>
|
||||
{{
|
||||
$i18n.locales.find(({ code }) => code == $i18n.locale).country
|
||||
| formatCountry
|
||||
}}
|
||||
</template>
|
||||
<NuxtLink
|
||||
v-for="locale in $i18n.locales.filter(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<label>
|
||||
<!-- <ColorScheme placeholder="..." tag="span">
|
||||
<ColorScheme placeholder="..." tag="span">
|
||||
{{ $t("background") }}:
|
||||
{{
|
||||
$colorMode.preference.charAt(0).toUpperCase() +
|
||||
@@ -10,37 +10,21 @@
|
||||
<span v-if="$colorMode.preference === 'system'">
|
||||
({{ $colorMode.value }} mode detected)
|
||||
</span>
|
||||
</ColorScheme> -->
|
||||
</ColorScheme>
|
||||
</label>
|
||||
<div>
|
||||
<span
|
||||
<ButtonSecondary
|
||||
v-for="(color, index) of colors"
|
||||
:key="`color-${index}`"
|
||||
v-tippy="{ theme: 'tooltip' }"
|
||||
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
|
||||
class="
|
||||
inline-flex
|
||||
items-center
|
||||
justify-center
|
||||
p-3
|
||||
m-2
|
||||
transition
|
||||
duration-150
|
||||
ease-in-out
|
||||
bg-transparent
|
||||
rounded-full
|
||||
cursor-pointer
|
||||
text-secondaryLight
|
||||
hover:text-secondary
|
||||
"
|
||||
:class="[
|
||||
{ 'bg-primary': color === $colorMode.preference },
|
||||
{ 'text-accent hover:text-accent': color === $colorMode.value },
|
||||
]"
|
||||
@click="$colorMode.preference = color"
|
||||
>
|
||||
<i class="material-icons">{{ getIcon(color) }}</i>
|
||||
</span>
|
||||
:icon="getIcon(color)"
|
||||
@click.native="$colorMode.preference = color"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
<template #header>
|
||||
<h3 class="heading">{{ $t("confirm") }}</h3>
|
||||
<div>
|
||||
<button class="icon button" @click="hideModal">
|
||||
<i class="material-icons">close</i>
|
||||
</button>
|
||||
<ButtonSecondary icon="close" @click.native="hideModal" />
|
||||
</div>
|
||||
</template>
|
||||
<template #body>
|
||||
@@ -14,12 +12,8 @@
|
||||
<template #footer>
|
||||
<span></span>
|
||||
<span>
|
||||
<button class="icon button" @click="hideModal">
|
||||
{{ no }}
|
||||
</button>
|
||||
<button class="icon button primary" @click="resolve">
|
||||
{{ yes }}
|
||||
</button>
|
||||
<ButtonSecondary :label="no" @click.native="hideModal" />
|
||||
<ButtonPrimary :label="yes" @click.native="resolve" />
|
||||
</span>
|
||||
</template>
|
||||
</SmartModal>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<template>
|
||||
<span class="chip">
|
||||
<span><slot></slot></span>
|
||||
<button class="p-2 icon" @click="$emit('chip-delete')">
|
||||
<i class="material-icons close-button"> close </i>
|
||||
</button>
|
||||
<ButtonSecondary
|
||||
class="p-2 close-button icon"
|
||||
icon="close"
|
||||
@click.native="$emit('chip-delete')"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -18,7 +20,7 @@
|
||||
@apply bg-primaryDark;
|
||||
@apply text-secondary;
|
||||
@apply font-mono;
|
||||
@apply transition;
|
||||
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
@apply border border-divider;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
right-0
|
||||
cursor-pointer
|
||||
"
|
||||
@click="$emit('toggle')"
|
||||
@click.native="$emit('toggle')"
|
||||
>
|
||||
<i
|
||||
class="
|
||||
|
||||
19
components/smart/Icon.vue
Normal file
19
components/smart/Icon.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<component :is="src" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
src() {
|
||||
return require(`~/assets/icons/${this.name}.svg?inline`)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
93
components/smart/Item.vue
Normal file
93
components/smart/Item.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<SmartLink
|
||||
:to="`${/^\/(?!\/).*$/.test(to) ? localePath(to) : to}`"
|
||||
:exact="exact"
|
||||
:blank="blank"
|
||||
class="
|
||||
inline-flex
|
||||
px-4
|
||||
py-2
|
||||
text-sm
|
||||
transition
|
||||
rounded-lg
|
||||
focus:bg-primaryDark focus:text-secondaryDark
|
||||
hover:bg-primaryDark hover:text-secondaryDark
|
||||
focus:outline-none
|
||||
"
|
||||
:class="[
|
||||
{ 'opacity-50 cursor-not-allowed': disabled },
|
||||
{ 'flex-1': label },
|
||||
{ 'flex-row-reverse justify-end': reverse },
|
||||
]"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<i
|
||||
v-if="icon"
|
||||
:class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''"
|
||||
class="material-icons"
|
||||
>
|
||||
{{ icon }}
|
||||
</i>
|
||||
<SmartIcon
|
||||
v-if="svg"
|
||||
:name="svg"
|
||||
:class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''"
|
||||
class="svg-icons"
|
||||
/>
|
||||
<div class="inline-flex items-start" :class="{ 'flex-col': description }">
|
||||
<div class="font-semibold">
|
||||
{{ label }}
|
||||
</div>
|
||||
<p v-if="description" class="my-2 text-xs text-left text-secondaryLight">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
</SmartLink>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
to: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
exact: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
blank: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
svg: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
infoIcon: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
reverse: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -8,24 +8,20 @@
|
||||
@mouseup="onBackdropMouseUp"
|
||||
@mousedown="onBackdropMouseDown"
|
||||
>
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="row-wrapper">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<div class="modal-container">
|
||||
<div class="modal-header">
|
||||
<div class="row-wrapper">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="flex flex-col">
|
||||
<slot name="body"></slot>
|
||||
<!-- <div class="top fade"></div>
|
||||
<div class="bottom fade"></div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="flex flex-col">
|
||||
<slot name="body"></slot>
|
||||
</div>
|
||||
<div v-if="hasFooterSlot" class="modal-footer">
|
||||
<div class="row-wrapper">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hasFooterSlot" class="modal-footer">
|
||||
<div class="row-wrapper">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,7 +46,7 @@ export default {
|
||||
return {
|
||||
stackId: Math.random(),
|
||||
shouldCloseOnBackdropClick: true,
|
||||
// when transition doesn't fire on unmount, we should manually remove the modal from DOM
|
||||
// when doesn't fire on unmount, we should manually remove the modal from DOM
|
||||
// (for example, when the parent component of this modal gets destroyed)
|
||||
shouldCleanupDomOnUnmount: true,
|
||||
}
|
||||
@@ -127,33 +123,23 @@ export default {
|
||||
@apply flex;
|
||||
@apply items-center;
|
||||
@apply justify-center;
|
||||
@apply transition;
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.64);
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
@apply flex flex-1;
|
||||
@apply items-center;
|
||||
@apply justify-center;
|
||||
@apply bg-primaryLight;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
@apply relative;
|
||||
@apply flex flex-1 flex-col;
|
||||
@apply m-2;
|
||||
@apply transition;
|
||||
@apply p-4;
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
@apply bg-primary;
|
||||
@apply rounded-lg;
|
||||
@apply shadow-2xl;
|
||||
@apply border-4 border-tooltip;
|
||||
|
||||
max-height: calc(100vh - 128px);
|
||||
max-width: 640px;
|
||||
@apply shadow-xl;
|
||||
@apply max-w-md;
|
||||
@apply max-h-xl;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
@@ -161,6 +147,7 @@ export default {
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
@apply my-4;
|
||||
@apply overflow-auto;
|
||||
}
|
||||
|
||||
@@ -168,15 +155,6 @@ export default {
|
||||
@apply p-2;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following styles are auto-applied to elements with
|
||||
* transition="modal" when their visibility is toggled
|
||||
* by Vue.js.
|
||||
*
|
||||
* You can easily play with the modal transition by editing
|
||||
* these styles.
|
||||
*/
|
||||
|
||||
.modal-enter,
|
||||
.modal-leave-active {
|
||||
@apply opacity-0;
|
||||
@@ -186,30 +164,7 @@ export default {
|
||||
.modal-leave-active .modal-container {
|
||||
@apply transform;
|
||||
@apply scale-90;
|
||||
@apply transition;
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
}
|
||||
|
||||
// .fade {
|
||||
// @apply absolute;
|
||||
// @apply block;
|
||||
// @apply transition;
|
||||
// @apply ease-in-out;
|
||||
// @apply duration-150;
|
||||
|
||||
// left: 16px;
|
||||
// right: 20px;
|
||||
// height: 32px;
|
||||
|
||||
// &.top {
|
||||
// top: 56px;
|
||||
// background: linear-gradient(to bottom, var(--primary-color), transparent);
|
||||
// }
|
||||
|
||||
// &.bottom {
|
||||
// bottom: 16px;
|
||||
// background: linear-gradient(to top, var(--primary-color), transparent);
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
|
||||
34
components/smart/Spinner.vue
Normal file
34
components/smart/Spinner.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<svg
|
||||
class="animate-spin"
|
||||
:class="`w-${size} h-${size}`"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
class="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
stroke-width="4"
|
||||
/>
|
||||
<path
|
||||
class="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
size: {
|
||||
type: Number,
|
||||
default: 6,
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,27 +1,29 @@
|
||||
<template>
|
||||
<section class="tabs-wrapper">
|
||||
<div class="tabs-wrapper">
|
||||
<div class="tabs" :class="styles">
|
||||
<ul>
|
||||
<li
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="{ 'is-active': tab.isActive }"
|
||||
:tabindex="0"
|
||||
@keyup.enter="selectTab(tab)"
|
||||
>
|
||||
<a :href="tab.href" @click="selectTab(tab)">
|
||||
<div class="flex w-0">
|
||||
<div class="inline-flex">
|
||||
<button
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
class="tab"
|
||||
:class="{ 'is-active': tab.isActive }"
|
||||
:tabindex="0"
|
||||
@keyup.enter="selectTab(tab)"
|
||||
@click="selectTab(tab)"
|
||||
>
|
||||
<i v-if="tab.icon" class="material-icons">
|
||||
{{ tab.icon }}
|
||||
</i>
|
||||
<span v-if="tab.label">{{ tab.label }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs-details">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -56,7 +58,10 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tabs-wrapper {
|
||||
@apply flex flex-col flex-nowrap flex-1;
|
||||
@apply flex;
|
||||
@apply flex-col;
|
||||
@apply flex-nowrap;
|
||||
@apply flex-1;
|
||||
|
||||
.tabs {
|
||||
@apply flex;
|
||||
@@ -64,53 +69,35 @@ export default {
|
||||
@apply overflow-auto;
|
||||
@apply mt-4;
|
||||
|
||||
ul {
|
||||
.tab {
|
||||
@apply flex;
|
||||
@apply w-0;
|
||||
}
|
||||
@apply items-center;
|
||||
@apply justify-center;
|
||||
@apply p-3;
|
||||
@apply text-secondaryLight;
|
||||
@apply font-semibold;
|
||||
@apply cursor-pointer;
|
||||
@apply transition;
|
||||
@apply border-b-2;
|
||||
@apply border-transparent;
|
||||
@apply rounded-t-lg;
|
||||
|
||||
li {
|
||||
@apply inline-flex;
|
||||
@apply outline-none;
|
||||
@apply border-none;
|
||||
|
||||
a {
|
||||
@apply flex;
|
||||
@apply items-center;
|
||||
@apply justify-center;
|
||||
@apply py-2 px-4;
|
||||
@apply text-secondaryLight text-sm;
|
||||
@apply rounded-lg;
|
||||
@apply cursor-pointer;
|
||||
@apply transition-colors;
|
||||
@apply ease-in-out;
|
||||
@apply duration-150;
|
||||
|
||||
.material-icons {
|
||||
@apply m-4;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@apply text-secondary;
|
||||
}
|
||||
.material-icons {
|
||||
@apply mr-4;
|
||||
}
|
||||
|
||||
&:focus a {
|
||||
@apply text-secondary;
|
||||
&:hover {
|
||||
@apply text-secondaryDark;
|
||||
}
|
||||
|
||||
&.is-active a {
|
||||
@apply bg-divider;
|
||||
@apply text-secondary;
|
||||
&:focus {
|
||||
@apply text-secondaryDark;
|
||||
@apply outline-none;
|
||||
}
|
||||
&.is-active {
|
||||
@apply text-accent;
|
||||
@apply border-accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
ul,
|
||||
ol {
|
||||
@apply flex-row flex-nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user