Adding Components to a Preset
Once you have created a preset, you can start adding custom component implementations to it. KatluxToolkit uses a dynamic resolution system that searches for components within your `presets/{presetName}/components/` folder.
1. Preset Structure Checklist
Before adding components, ensure your preset follows the standard structure:
presets/modern/
├── assets/ # Global assets (css, images)
└── components/ # Component overrides (Place them here!)
└── KButton/
└── KButton.vue2. How to Add a Component
To add a component (e.g., `KButton`) to your custom preset, simply create its folder and file implementation inside the `components/` sub-directory:
presets/modern/components/
└── KButton/
└── KButton.vue3. The Fallback Mechanism
One of the most powerful features of KatluxToolkit is the fallback mechanism. You don't need to implement every single component for every preset.
Important: If a component is missing in your active preset, KatluxToolkit will automatically fall back to the default component implementation.
This allows you to:
- Incrementally build your preset.
- Only override the components that need a different visual style.
- Ensure your application always works even if a preset is incomplete.
4. Component Resolution Example
When you use a global component like `KButton` while the active preset is set to `modern`:
- The system looks in: `presets/modern/components/KButton/KButton.vue`.
- If found, it renders that component.
- If NOT found, it falls back to the default toolkit implementation.
5. Defining Props and Models
When creating a component in your preset, you must define the `props` and `models` it receives. These are passed down from the global component.
Tip: Use Vue 3.5's `defineModel` for two-way bindings (like selection state) and `defineProps` for data passed down from the logic layer.
Advanced Example: Modern Datatable
For complex components like `KDatatable`, you often need to handle selection states and large data objects.
In `presets/modern/components/KDatatable/KDatatable.vue`:
<script setup lang="ts">
// 1. Define models for two-way binding (e.g., selection)
const selectedRows = defineModel<any[]>('selectedRows', { default: [] })
const selectAll = defineModel<boolean>('selectAll', { default: false })
// 2. Define props for data and actions
defineProps<{
dataProvider: any
visibleFields: Array<string> | null
rowActions: Array<any>
bulkActions: Array<any>
}>()
</script>
<preset lang="pug">
.modern-datatable
table
thead
tr
th: KCheckbox(v-model="selectAll")
th(v-for="field in visibleFields") {{ field }}
tbody
tr(v-for="row in dataProvider.pageData.value")
td: KCheckbox(:value="row" v-model="selectedRows")
td(v-for="field in visibleFields") {{ row[field] }}
</preset>Simplest Example: Modern Button
In `presets/modern/components/KButton/KButton.vue`:
<preset lang="pug">
button.KButton.modern-style(
@click="onClick"
:class="buttonClasses"
)
slot
</preset>
<script setup lang="ts">
defineProps(['buttonClasses', 'onClick'])
</script>
<style scoped>
.modern-style {
border-radius: var(--border-radius-xl);
transition: transform 0.2s;
}
</style>