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

75 lines
1.7 KiB
Vue

<template>
<component
:is="tag"
:class="['flex', directionClass, gapClass, alignClass, justifyClass, wrapClass, fullHeightClass]"
>
<slot />
</component>
</template>
<script setup lang="ts">
const props = defineProps({
tag: {
type: String,
default: 'div',
},
gap: {
type: [String, Number],
default: 6,
},
direction: {
type: String,
default: 'col', // col | row
},
align: {
type: String,
default: 'stretch', // start | center | end | stretch
},
justify: {
type: String,
default: 'start', // start | center | end | between
},
wrap: {
type: Boolean,
default: false,
},
fullHeight: {
type: Boolean,
default: false,
},
})
const gapMap: Record<string, string> = {
'1': 'gap-1',
'2': 'gap-2',
'3': 'gap-3',
'4': 'gap-4',
'5': 'gap-5',
'6': 'gap-6',
'8': 'gap-8',
'10': 'gap-10',
'12': 'gap-12',
}
const alignMap: Record<string, string> = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
stretch: 'items-stretch',
}
const justifyMap: Record<string, string> = {
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
between: 'justify-between',
}
const gapClass = computed(() => gapMap[String(props.gap)] || gapMap['6'])
const alignClass = computed(() => alignMap[props.align] || alignMap.start)
const justifyClass = computed(() => justifyMap[props.justify] || justifyMap.start)
const directionClass = computed(() => (props.direction === 'row' ? 'flex-row' : 'flex-col'))
const wrapClass = computed(() => (props.wrap ? 'flex-wrap' : ''))
const fullHeightClass = computed(() => (props.fullHeight ? 'min-h-screen' : ''))
</script>