# Creating Custom UI Components for Settings
When adding new setting types to BetterSEQTA+, you'll often need to create custom UI components to render and edit these settings. This guide covers how to create Svelte components for the settings UI and how to integrate them with the settings system.
## Understanding the Settings UI
Settings in BetterSEQTA+ are rendered by the `src/interface/pages/settings/general.svelte` component. This component:
1. Loads settings from all plugins
2. Maps setting types to appropriate UI components
3. Renders the settings UI
4. Handles updates when settings are changed
## Basic Component Requirements
Every setting UI component should follow these conventions:
1. **Accept a `state` prop** for the current value
2. **Accept an `onChange` prop** for updating the value
3. **Accept any additional props** specific to the setting type (e.g., `options`, `min`, `max`)
4. **Handle user input** and call `onChange` with the new value
## Creating a Basic Component
Here's an example of a basic Svelte component for a custom setting type:
```svelte
```
## Example: Slider Component
BetterSEQTA+ includes a Slider component for number settings:
```svelte
{stringValue}
```
## Example: Color Picker Component
Here's a more complex example of a color picker component:
```svelte
{#if isOpen}
{#each presets as preset}
{/each}
{/if}
```
## Integrating with the Settings System
Once you've created your component, you need to update `general.svelte` to use it for your custom setting type.
### 1. Import Your Component
At the top of `src/interface/pages/settings/general.svelte`, add an import for your component:
```typescript
import ColorPicker from "../../components/ColorPicker.svelte"
```
### 2. Update Component Mapping
Find the `getPluginSettingEntries` function in `general.svelte` and update the component mapping:
```typescript
function getPluginSettingEntries() {
const entries: any[] = [];
pluginSettings.forEach(plugin => {
if (Object.keys(plugin.settings).length === 0) return;
Object.entries(plugin.settings).forEach(([key, setting]) => {
const id = getPluginSettingId(plugin.pluginId, key);
entries.push({
title: setting.title || key,
description: setting.description || '',
id,
Component: setting.type === 'boolean' ? Switch :
setting.type === 'select' ? Select :
setting.type === 'number' ? Slider :
setting.type === 'color' ? ColorPicker : // Add your component here
setting.type === 'string' ? (setting.options ? Select : null) : Switch,
props: {
state: pluginSettingsValues[plugin.pluginId]?.[key] ?? setting.default,
onChange: (value: any) => {
updatePluginSetting(plugin.pluginId, key, value);
},
options: setting.options,
// Add any additional props your component needs
presets: setting.presets,
min: setting.min,
max: setting.max,
step: setting.step
}
});
});
});
return entries;
}
```
## Handling Different UI Needs
Different setting types may have different UI needs:
### Toggle Switches
For boolean settings, a toggle switch is usually appropriate:
```svelte
```
### Text Inputs
For string settings, a text input with validation:
```svelte
{#if error}
{error}
{/if}
```
### Complex Interactive Components
For more complex settings, you may need more interactive components with dropdowns, modals, or other features. Consider using additional Svelte features like:
- `{#if}...{/if}` blocks for conditional rendering
- Svelte transitions for animations
- Svelte actions for DOM interactions
- Svelte stores for shared state
## Best Practices
1. **Keep Components Focused**: Each component should do one thing well
2. **Use TypeScript**: Define proper types for your props
3. **Handle Errors**: Validate input and show meaningful error messages
4. **Use Clear UI**: Make it obvious how to interact with the component
5. **Add Accessibility**: Include proper ARIA attributes and keyboard handling
6. **Support Theming**: Use CSS variables or design system tokens for consistent styling
7. **Test Edge Cases**: Ensure your component handles all possible inputs
## Complete Example
Here's a complete example of a custom file picker component:
```svelte
{fileName}
{#if state}
{/if}
{#if error}
{error}
{/if}
```
To use this in the settings system, you would:
1. Define a `FileSetting` interface in `types.ts`
2. Create a `FileSetting` decorator in `settings.ts`
3. Update the `getPluginSettingEntries` function in `general.svelte`
This component demonstrates:
- Handling file input (a more complex input type)
- Input validation
- Error handling
- Multiple interactive elements
- Binding to DOM elements
- Clean UI that follows platform conventions