Skip to content

Reka UI Preset

Enforma includes a built-in preset for Reka UI, making it easy to create forms using Reka UI's unstyled, accessible primitives. This integration provides a seamless experience that leverages Reka UI's headless component library while maintaining Enforma's powerful form management capabilities.

What is Reka UI?

Reka UI is an open-source library of unstyled, accessible Vue components (similar to Radix UI for React). It provides primitive components that you can style however you want, making it perfect for creating custom-designed forms.

Installation

To use the Reka UI preset, you need to have Reka UI installed in your project:

bash
npm install reka-ui

Follow the Reka UI setup instructions to get started.

Basic Usage

Because Reka UI provides unstyled primitives, you need to create wrapper components that compose Reka UI primitives with your desired styling. Here's how to set it up:

Step 1: Create Wrapper Components

Create styled wrapper components for the form inputs you need. Here's an example for a text input:

vue
<!-- components/MyInput.vue -->
<template>
  <input
    v-bind="$attrs"
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
    class="my-input"
  />
</template>

<script setup>
defineProps({
  modelValue: String,
  id: String,
  placeholder: String,
  disabled: Boolean
})

defineEmits(['update:modelValue'])
</script>

<style scoped>
.my-input {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: 1px solid #ddd;
  border-radius: 0.25rem;
}
.my-input:focus {
  border-color: #4f46e5;
  outline: none;
}
</style>

For components like Select and Switch, you'll compose Reka UI primitives:

vue
<!-- components/MySelect.vue -->
<template>
  <SelectRoot v-model="localValue" v-bind="$attrs">
    <SelectTrigger class="my-select-trigger">
      <SelectValue :placeholder="placeholder" />
      <SelectIcon>▼</SelectIcon>
    </SelectTrigger>
    <SelectPortal>
      <SelectContent class="my-select-content" position="popper">
        <SelectViewport>
          <SelectItem
            v-for="item in items"
            :key="item.value"
            :value="item.value"
            class="my-select-item"
          >
            <SelectItemText>{{ item.label }}</SelectItemText>
          </SelectItem>
        </SelectViewport>
      </SelectContent>
    </SelectPortal>
  </SelectRoot>
</template>

<script setup>
import { computed } from 'vue'
import {
  SelectRoot, SelectTrigger, SelectValue, SelectIcon,
  SelectPortal, SelectContent, SelectViewport,
  SelectItem, SelectItemText
} from 'reka-ui'

const props = defineProps({
  modelValue: String,
  items: Array,
  placeholder: String
})

const emit = defineEmits(['update:modelValue'])

const localValue = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})
</script>

<style scoped>
/* Add your styles here */
</style>

Step 2: Configure the Preset

js
// main.js
import { createApp } from 'vue'
import { EnformaPlugin } from '@encolajs/enforma'
import { useRekauiPreset } from '@encolajs/enforma/presets/rekaui'
import App from './App.vue'

// Import your wrapper components
import MyInput from './components/MyInput.vue'
import MySelect from './components/MySelect.vue'
import MySwitch from './components/MySwitch.vue'
import MyButton from './components/MyButton.vue'

const app = createApp(App)

// Configure Enforma
app.use(EnformaPlugin)

// Apply Reka UI preset with your components
useRekauiPreset({
  input: MyInput,
  text: MyInput,
  select: MySelect,
  switch: MySwitch,
  toggle: MySwitch,
  button: MyButton,
})

app.mount('#app')

Step 3: Use in Your Forms

vue
<template>
  <Enforma :data="formData" :validator="validator" :submit-handler="submit">
    <RekauiField name="name" label="Full Name" />
    <RekauiField name="email" label="Email Address" />
    <RekauiField
      name="role"
      label="Role"
      input-component="select"
      :input-props="{ items: roles }"
    />
    <RekauiField name="active" label="Active" input-component="switch" />
  </Enforma>
</template>

<script setup>
import { ref } from 'vue'
import { Enforma } from '@encolajs/enforma'
import { createEncolaValidator } from '@encolajs/enforma/validators/encola'
import RekauiField from '@encolajs/enforma/presets/rekaui/Field'

const formData = ref({
  name: '',
  email: '',
  role: '',
  active: false
})

const validator = createEncolaValidator({
  name: 'required',
  email: 'required|email',
  role: 'required'
})

const roles = [
  { value: 'admin', label: 'Administrator' },
  { value: 'user', label: 'Regular User' },
  { value: 'guest', label: 'Guest' }
]

function submit(data) {
  console.log('Form submitted:', data)
}
</script>

Component Mapping

The preset supports the following component types that you can provide:

Field TypePurpose
inputText input field
selectDropdown selection
switchBoolean toggle
toggleAlias for switch
buttonAction buttons

The preset also configures button components for form actions:

ButtonUsage
EnformaSubmitButtonSubmit form button
EnformaResetButtonReset form button
EnformaRepeatableAddButtonAdd repeatable item
EnformaRepeatableRemoveButtonRemove repeatable item
EnformaRepeatableMoveUpButtonMove item up
EnformaRepeatableMoveDownButtonMove item down

Tree-Shaking

Because you only import the Reka UI primitives you actually use in your wrapper components, this preset is extremely tree-shakable. You only bundle what you need!

Benefits

Full Control: Style components exactly how you want ✅ Accessible: Built on Reka UI's accessible primitives ✅ Lightweight: Only bundle what you use ✅ Flexible: Easy to customize for your design system

NOTE

Since Reka UI is a headless library, you have complete control over the styling and behavior of your form components. The examples above are just starting points - customize them to match your design system!

Released under the MIT License