Files
webapp/app/components/ui/Text.vue
2026-01-07 09:10:35 +07:00

80 lines
1.7 KiB
Vue

<template>
<component :is="tag" :class="textClass">
<slot />
</component>
</template>
<script setup lang="ts">
const props = defineProps({
tag: {
type: String,
default: 'p',
},
size: {
type: String,
default: 'body', // body | base
},
tone: {
type: String,
default: 'default', // default | muted | inverse
},
weight: {
type: String,
default: 'normal', // normal | semibold
},
align: {
type: String,
default: 'start', // start | center | end
},
transform: {
type: String,
default: 'none', // none | uppercase
},
mono: {
type: Boolean,
default: false,
},
})
const sizeMap: Record<string, string> = {
body: 'text-base',
base: 'text-base',
sm: 'text-sm',
caption: 'text-sm',
}
const toneMap: Record<string, string> = {
default: 'text-base-content',
muted: 'text-base-content/70',
inverse: 'text-primary-content/90',
}
const weightMap: Record<string, string> = {
normal: 'font-normal',
semibold: 'font-semibold',
}
const alignMap: Record<string, string> = {
start: 'text-left',
center: 'text-center',
end: 'text-right',
}
const transformMap: Record<string, string> = {
none: '',
uppercase: 'uppercase tracking-[0.08em]',
}
const textClass = computed(() => {
const sizeClass = sizeMap[props.size] || sizeMap.body
const toneClass = toneMap[props.tone] || toneMap.default
const weightClass = weightMap[props.weight] || weightMap.normal
const alignClass = alignMap[props.align] || alignMap.start
const transformClass = transformMap[props.transform] || ''
const familyClass = props.mono ? 'font-mono' : ''
return [sizeClass, toneClass, weightClass, alignClass, transformClass, familyClass]
.filter(Boolean)
.join(' ')
})
</script>