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.vue

2. 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.vue

3. 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`:

  1. The system looks in: `presets/modern/components/KButton/KButton.vue`.
  2. If found, it renders that component.
  3. 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>