1
0

feat: abstract BaseCheckbox

This commit is contained in:
Dominik Pschenitschni
2023-03-07 17:59:12 +01:00
parent 7d3b97d422
commit 8fc254d2db
12 changed files with 193 additions and 112 deletions

View File

@ -0,0 +1,71 @@
<script lang="ts" setup>
import {ref} from 'vue'
import {logEvent} from 'histoire/client'
import FancyCheckbox from './fancycheckbox.vue'
const isDisabled = ref<boolean | undefined>()
const isChecked = ref(false)
const isCheckedInitiallyEnabled = ref(true)
const isCheckedDisabled = ref(false)
const withoutInitialState = ref<boolean | undefined>()
</script>
<template>
<Story :layout="{ type: 'grid', width: '200px' }">
<Variant title="Default">
<FancyCheckbox
v-model="isChecked"
:disabled="isDisabled"
>
This is probably not important
</FancyCheckbox>
Visualisation
<input type="checkbox" v-model="isChecked">
{{ isChecked }}
</Variant>
<Variant title="Enabled Initially">
<FancyCheckbox
:disabled="isDisabled"
v-model="isCheckedInitiallyEnabled"
>
We want you to use this option
</FancyCheckbox>
Visualisation
<input type="checkbox" v-model="isCheckedInitiallyEnabled">
{{ isCheckedInitiallyEnabled }}
</Variant>
<Variant title="Disabled">
<FancyCheckbox
disabled
:modelValue="isCheckedDisabled"
@update:model-value="logEvent('Setting disabled: This should never happen', $event)"
>
You can't change this
</FancyCheckbox>
Visualisation
<input type="checkbox" v-model="isCheckedDisabled" disabled>
{{ isCheckedDisabled }}
</Variant>
<Variant title="Undefined initial State">
<FancyCheckbox
v-model="withoutInitialState"
:disabled="isDisabled"
>
Not sure what the value should be
</FancyCheckbox>
Visualisation
<input type="checkbox" v-model="withoutInitialState" disabled>
{{ withoutInitialState }}
</Variant>
</Story>
</template>

View File

@ -1,66 +1,42 @@
<template>
<div :class="{'is-disabled': disabled}" class="fancycheckbox">
<input
:checked="checked"
:disabled="disabled || undefined"
:id="checkBoxId"
@change="(event: Event) => updateData((event.target as HTMLInputElement).checked)"
type="checkbox"
/>
<label :for="checkBoxId" class="check" @click.prevent="check">
<svg height="18px" viewBox="0 0 18 18" width="18px">
<path
d="M1,9 L1,3.5 C1,2 2,1 3.5,1 L14.5,1 C16,1 17,2 17,3.5 L17,14.5 C17,16 16,17 14.5,17 L3.5,17 C2,17 1,16 1,14.5 L1,9 Z"></path>
<polyline points="1 9 7 14 15 4"></polyline>
</svg>
<span>
<slot></slot>
</span>
</label>
</div>
<BaseCheckbox
class="fancycheckbox"
:class="{
'is-disabled': disabled,
'is-block': isBlock,
}"
:disabled="disabled"
:model-value="modelValue"
@update:model-value="value => emit('update:modelValue', value)"
>
<CheckboxIcon class="fancycheckbox__icon" />
<span class="fancycheckbox__content">
<slot/>
</span>
</BaseCheckbox>
</template>
<script setup lang="ts">
import {ref, toRef, watch} from 'vue'
import CheckboxIcon from '@/assets/checkbox.svg?component'
import {createRandomID} from '@/helpers/randomId'
import BaseCheckbox from '@/components/base/BaseCheckbox.vue'
const checked = ref(false)
const checkBoxId = `fancycheckbox_${createRandomID()}`
const props = defineProps({
defineProps({
modelValue: {
type: Boolean,
required: false,
},
disabled: {
type: Boolean,
required: false,
},
isBlock: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue', 'change'])
const modelValue = toRef(props, 'modelValue')
watch(
modelValue,
newValue => {
checked.value = newValue
},
{immediate: true},
)
function updateData(newChecked: boolean) {
checked.value = newChecked
emit('update:modelValue', newChecked)
emit('change', newChecked)
}
function check() {
checked.value = !checked.value
updateData(checked.value)
}
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void
}>()
</script>
@ -70,75 +46,51 @@ function check() {
padding-right: 5px;
padding-top: 3px;
// FIXME: should be a prop
&.is-block {
display: block;
margin: .5rem .2rem;
}
}
input[type=checkbox] {
display: none;
}
.check {
cursor: pointer;
position: relative;
margin: auto;
width: 18px;
height: 18px;
-webkit-tap-highlight-color: transparent;
transform: translate3d(0, 0, 0);
}
span {
.fancycheckbox__content {
font-size: 0.8rem;
vertical-align: top;
padding-left: .5rem;
}
svg {
.fancycheckbox__icon {
--stroke-color: #c8ccd4;
position: relative;
z-index: 1;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
stroke: #c8ccd4;
stroke-width: 1.5;
stroke: var(--stroke-color);
transform: translate3d(0, 0, 0);
transition: all 0.2s ease;
}
.check:hover svg {
stroke: var(--primary);
}
.is-disabled .check:hover svg {
stroke: #c8ccd4;
}
path {
stroke-dasharray: 60;
stroke-dashoffset: 0;
}
polyline {
stroke-dasharray: 22;
stroke-dashoffset: 66;
}
input[type=checkbox]:checked + .check {
svg {
stroke: var(--primary);
:deep(path) {
// stroke-dasharray: 60;
transition: all 0.2s linear, color 0.2s ease;
}
:deep(polyline) {
// stroke-dasharray: 22;
// stroke-dashoffset: 66;
transition: all 0.2s linear, color 0.2s ease;
}
}
.fancycheckbox:not(:has(input:disabled)):hover .fancycheckbox__icon {
--stroke-color: var(--primary);
}
.fancycheckbox:has(input:checked) .fancycheckbox__icon:deep() {
--stroke-color: var(--primary);
path {
stroke-dashoffset: 60;
transition: all 0.3s linear;
}
polyline {
stroke-dashoffset: 42;
transition: all 0.2s linear;
transition-delay: 0.15s;
}
}