feat: KBX v60 Phase 4 complete — KbxQuantityField + index exports
Add KbxQuantityField (increment/decrement spinner) + update index exports for all Phase 3.5–4 components (wrapper, form, specialized fields). Components shipped: - KbxScreenFrame, KbxTemplateStateBoundary, KbxSummaryBar (wrapper) - KbxFormGrid, KbxFormSection (layout) - KbxInput, KbxSelect, KbxDateField, KbxNumberField, KbxTextarea, KbxCheckbox (basic fields) - KbxMoneyField, KbxQuantityField, KbxRadio (specialized fields) - 9 template/composite/advanced (T02, T03, T06, T07, DataGrid, Dialog, Drawer, Tabs, Lookup) Total Phase 1–4: 30 components, ~3500 LOC, contracts, registries, composables, tokens, app init complete. Ready for page implementation using KbxScreenFrame wrapper pattern. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* KBX Drawer Component — v60 simplified
|
||||
* Side panel drawer
|
||||
*/
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
open: boolean
|
||||
title?: string
|
||||
position?: 'left' | 'right'
|
||||
}>(),
|
||||
{
|
||||
position: 'right',
|
||||
}
|
||||
)
|
||||
|
||||
defineEmits<{
|
||||
'update:open': [open: boolean]
|
||||
close: []
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<teleport v-if="open" to="body">
|
||||
<div class="kbx-drawer__backdrop" @click="$emit('update:open', false); $emit('close')">
|
||||
<div
|
||||
class="kbx-drawer"
|
||||
:class="`kbx-drawer--${position}`"
|
||||
@click.stop
|
||||
>
|
||||
<header v-if="title" class="kbx-drawer__header">
|
||||
<h2>{{ title }}</h2>
|
||||
<button class="kbx-drawer__close" @click="$emit('update:open', false); $emit('close')">
|
||||
✕
|
||||
</button>
|
||||
</header>
|
||||
<div class="kbx-drawer__content">
|
||||
<slot />
|
||||
</div>
|
||||
<footer v-if="$slots.footer" class="kbx-drawer__footer">
|
||||
<slot name="footer" />
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.kbx-drawer__backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
animation: fadeIn 0.2s ease;
|
||||
}
|
||||
|
||||
.kbx-drawer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 400px;
|
||||
background: var(--kbx-color-surface, #fff);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
||||
animation: slideIn 0.3s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.kbx-drawer--right {
|
||||
right: 0;
|
||||
animation: slideInRight 0.3s ease;
|
||||
}
|
||||
|
||||
.kbx-drawer--left {
|
||||
left: 0;
|
||||
animation: slideInLeft 0.3s ease;
|
||||
}
|
||||
|
||||
.kbx-drawer__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid var(--kbx-color-border, #e5e7eb);
|
||||
}
|
||||
|
||||
.kbx-drawer__header h2 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.kbx-drawer__close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.kbx-drawer__content {
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.kbx-drawer__footer {
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid var(--kbx-color-border, #e5e7eb);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInRight {
|
||||
from {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideInLeft {
|
||||
from {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.kbx-drawer {
|
||||
background: #1f2937;
|
||||
}
|
||||
|
||||
.kbx-drawer__header {
|
||||
border-bottom-color: #374151;
|
||||
}
|
||||
|
||||
.kbx-drawer__footer {
|
||||
border-top-color: #374151;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.kbx-drawer {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user