wip bsky client for the web & android
bbell.vt3e.cat
1<script setup lang="ts">
2import { useId } from 'vue'
3import { IconCheckRounded } from '@iconify-prerendered/vue-material-symbols'
4
5defineProps<{
6 label?: string
7 disabled?: boolean
8}>()
9
10const model = defineModel<boolean>()
11const id = useId()
12</script>
13
14<template>
15 <div class="checkbox-wrapper" :class="{ disabled }" @click.stop="!disabled && (model = !model)">
16 <div
17 class="checkbox-box"
18 :class="{ 'is-checked': model }"
19 role="checkbox"
20 :aria-checked="model"
21 :tabindex="disabled ? -1 : 0"
22 @keydown.space.prevent="!disabled && (model = !model)"
23 >
24 <IconCheckRounded class="check-icon" />
25 </div>
26 <label v-if="label" :for="id" class="label">{{ label }}</label>
27 </div>
28</template>
29
30<style scoped>
31.checkbox-wrapper {
32 display: inline-flex;
33 align-items: center;
34 gap: 0.75rem;
35 cursor: pointer;
36 user-select: none;
37}
38
39.checkbox-wrapper.disabled {
40 opacity: 0.5;
41 cursor: not-allowed;
42}
43
44.checkbox-box {
45 width: 1.5rem;
46 height: 1.5rem;
47 border-radius: 0.5rem;
48 border: 2px solid hsla(var(--subtext0) / 0.75);
49 background-color: hsla(var(--surface0) / 0.5);
50 display: flex;
51 align-items: center;
52 justify-content: center;
53 color: hsl(var(--base));
54
55 &:hover {
56 background-color: hsla(var(--surface0) / 1);
57 border-color: hsla(var(--subtext0) / 0.75);
58 }
59}
60
61.checkbox-box.is-checked {
62 background-color: hsl(var(--accent));
63 border-color: hsl(var(--accent));
64}
65
66.check-icon {
67 width: 100%;
68 height: 100%;
69 opacity: 0;
70 transform: scale(0.5);
71 transition: all 0.2s;
72}
73
74.checkbox-box.is-checked .check-icon {
75 opacity: 1;
76 transform: scale(1);
77}
78
79.label {
80 color: hsl(var(--text));
81 font-size: 1rem;
82 cursor: inherit;
83}
84</style>