Modrinth/components/ui/Chips.vue
Sasha Sorokin 34fd9d29c8
Update Nuxt to v3.12.1 (#1720)
* Update Nuxt dependencies

* Fix ref access in ChartDisplay

* Fix feature flags cookie options type error

* Specify type-only imports

* Fix shorthands access to tags outside of reactive scope

* Replace most useRoute calls with useRoute from vue-router

Nuxt's version of this composable is horrendously broken (nuxt/nuxt#21340)

* Import all svgs with ?component parameter

Fixes weird hydration issues + gives correct type
2024-06-14 13:23:02 -07:00

102 lines
1.8 KiB
Vue

<template>
<div class="chips">
<button
v-for="item in items"
:key="item"
class="iconified-button"
:class="{ selected: selected === item, capitalize: capitalize }"
@click="toggleItem(item)"
>
<CheckIcon v-if="selected === item" />
<span>{{ formatLabel(item) }}</span>
</button>
</div>
</template>
<script>
import CheckIcon from '~/assets/images/utils/check.svg?component'
export default {
components: {
CheckIcon,
},
props: {
modelValue: {
required: true,
type: String,
},
items: {
required: true,
type: Array,
},
neverEmpty: {
default: true,
type: Boolean,
},
formatLabel: {
default: (x) => x,
type: Function,
},
capitalize: {
type: Boolean,
default: true,
},
},
emits: ['update:modelValue'],
computed: {
selected: {
get() {
return this.modelValue
},
set(value) {
this.$emit('update:modelValue', value)
},
},
},
created() {
if (this.items.length > 0 && this.neverEmpty) {
this.selected = this.items[0]
}
},
methods: {
toggleItem(item) {
if (this.selected === item && !this.neverEmpty) {
this.selected = null
} else {
this.selected = item
}
},
},
}
</script>
<style lang="scss" scoped>
.chips {
display: flex;
grid-gap: 0.5rem;
flex-wrap: wrap;
.iconified-button {
&.capitalize {
text-transform: capitalize;
}
svg {
width: 1em;
height: 1em;
}
&:focus-visible {
outline: 0.25rem solid #ea80ff;
border-radius: 0.25rem;
}
}
.selected {
color: var(--color-button-text-active);
background-color: var(--color-brand-highlight);
box-shadow: inset 0 0 0 transparent, 0 0 0 2px var(--color-brand);
}
}
</style>