Skip to content

UISwitch

UISwitch

A versatile switch component that provides a sliding toggle interface for boolean values, with support for custom styling, labels, and loading states.

<template>
<UISwitch
v-model="enabled"
:size="'md'"
:disabled="false"
:loading="false"
@change="handleChange"
>
<template #label>
Enable notifications
</template>
</UISwitch>
</template>
<script setup lang="ts">
const enabled = ref(false)
const handleChange = (value: boolean) => {
console.log('Switch toggled:', value)
}
</script>

Props

  • modelValue (boolean): Current state
  • size (string): Switch size (‘sm’ | ‘md’ | ‘lg’)
  • disabled (boolean): Disable switch
  • loading (boolean): Show loading state
  • color (string): Active color
  • name (string): Input name
  • required (boolean): Mark as required
  • error (boolean): Show error state
  • label (string): Switch label
  • labelPosition (string): Label position

Events

  • update:modelValue: State updated
  • change: Value changed
  • focus: Switch focused
  • blur: Switch blurred

Slots

  • label: Custom label content
  • icon: Custom icon content
  • loading: Custom loading state

Usage Examples

  1. Basic Switch:
<template>
<UISwitch v-model="darkMode">
Dark Mode
</UISwitch>
</template>
<script setup>
const darkMode = ref(false)
</script>
  1. Switch with Custom Styling:
<template>
<UISwitch
v-model="status"
class="custom-switch"
>
<template #label>
<div class="flex items-center space-x-2">
<StatusIcon
:class="[
'w-4 h-4',
status ? 'text-success-500' : 'text-gray-400'
]"
/>
<span>{{ status ? 'Active' : 'Inactive' }}</span>
</div>
</template>
</UISwitch>
</template>
<script setup>
const status = ref(false)
</script>
<style>
.custom-switch {
--switch-color: theme('colors.success.500');
--switch-bg: theme('colors.success.100');
}
</style>
  1. Form Integration:
<template>
<form @submit.prevent="handleSubmit">
<div class="space-y-4">
<div class="space-y-2">
<label class="text-sm font-medium">
Preferences
</label>
<div class="space-y-3">
<UISwitch
v-model="preferences.emails"
name="email_notifications"
>
Email notifications
</UISwitch>
<UISwitch
v-model="preferences.updates"
name="product_updates"
>
Product updates
</UISwitch>
<UISwitch
v-model="preferences.newsletter"
name="newsletter"
>
Weekly newsletter
</UISwitch>
</div>
</div>
<UIButton type="submit">
Save Preferences
</UIButton>
</div>
</form>
</template>
<script setup>
const preferences = reactive({
emails: false,
updates: true,
newsletter: false
})
const handleSubmit = () => {
// Handle form submission
}
</script>

Best Practices

  1. Visual Design:

    • Clear states
    • Smooth animation
    • Consistent sizing
    • Proper spacing
  2. User Experience:

    • Immediate feedback
    • Clear labeling
    • Touch targets
    • Loading states
  3. Accessibility:

    • ARIA labels
    • Keyboard support
    • Focus states
    • Screen reader support
  4. Implementation:

    • State management
    • Form integration
    • Error handling
    • Loading feedback

Common Use Cases

  1. Feature Toggle:
<template>
<div class="space-y-4">
<h3 class="text-lg font-medium">
Feature Settings
</h3>
<div class="space-y-3">
<div
v-for="feature in features"
:key="feature.id"
class="flex items-center justify-between p-4 bg-gray-50 rounded-lg"
>
<div>
<div class="font-medium">
{{ feature.name }}
</div>
<div class="text-sm text-gray-500">
{{ feature.description }}
</div>
</div>
<UISwitch
v-model="feature.enabled"
:loading="feature.loading"
@change="toggleFeature(feature)"
/>
</div>
</div>
</div>
</template>
<script setup>
const features = ref([
{
id: 1,
name: 'Beta Features',
description: 'Access to upcoming features',
enabled: false,
loading: false
},
// ... more features
])
const toggleFeature = async (feature) => {
feature.loading = true
try {
await updateFeatureStatus(feature)
} finally {
feature.loading = false
}
}
</script>
  1. Settings Panel:
<template>
<div class="settings-panel">
<div class="space-y-6">
<section>
<h4 class="text-sm font-medium text-gray-500 uppercase">
Appearance
</h4>
<div class="mt-3 space-y-3">
<UISwitch
v-model="settings.darkMode"
@change="updateTheme"
>
Dark Mode
</UISwitch>
<UISwitch
v-model="settings.reducedMotion"
@change="updateAccessibility"
>
Reduced Motion
</UISwitch>
</div>
</section>
<section>
<h4 class="text-sm font-medium text-gray-500 uppercase">
Privacy
</h4>
<div class="mt-3 space-y-3">
<UISwitch
v-model="settings.tracking"
@change="updatePrivacy"
>
<template #label>
<div>
<div>Usage Analytics</div>
<div class="text-sm text-gray-500">
Help us improve by sharing usage data
</div>
</div>
</template>
</UISwitch>
</div>
</section>
</div>
</div>
</template>
  1. Quick Actions:
<template>
<div class="quick-actions">
<div class="flex items-center justify-between p-4 border-b">
<div class="flex items-center space-x-3">
<WifiIcon class="w-5 h-5 text-gray-500" />
<span>Wi-Fi</span>
</div>
<UISwitch
v-model="wifi.enabled"
:loading="wifi.connecting"
@change="toggleWifi"
/>
</div>
<div class="flex items-center justify-between p-4 border-b">
<div class="flex items-center space-x-3">
<BluetoothIcon class="w-5 h-5 text-gray-500" />
<span>Bluetooth</span>
</div>
<UISwitch
v-model="bluetooth.enabled"
:loading="bluetooth.scanning"
@change="toggleBluetooth"
/>
</div>
<div class="flex items-center justify-between p-4">
<div class="flex items-center space-x-3">
<AirplaneModeIcon class="w-5 h-5 text-gray-500" />
<span>Airplane Mode</span>
</div>
<UISwitch
v-model="airplaneMode"
@change="toggleAirplaneMode"
/>
</div>
</div>
</template>
<script setup>
const wifi = reactive({
enabled: true,
connecting: false
})
const bluetooth = reactive({
enabled: false,
scanning: false
})
const airplaneMode = ref(false)
const toggleWifi = async () => {
wifi.connecting = true
try {
await updateWifiStatus(wifi.enabled)
} finally {
wifi.connecting = false
}
}
const toggleBluetooth = async () => {
bluetooth.scanning = true
try {
await updateBluetoothStatus(bluetooth.enabled)
} finally {
bluetooth.scanning = false
}
}
const toggleAirplaneMode = () => {
if (airplaneMode.value) {
wifi.enabled = false
bluetooth.enabled = false
}
}
</script>