svelte-toggle-switch 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md ADDED
@@ -0,0 +1,165 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is an NPM package providing a comprehensive, accessible toggle switch component for Svelte applications. The package has been completely rewritten in version 2.0 with TypeScript support, multiple design variants, extensive customization options, and enhanced accessibility features.
8
+
9
+ ## Development Commands
10
+
11
+ ```bash
12
+ # Install dependencies
13
+ npm install
14
+
15
+ # Start development server with hot reload
16
+ npm run dev
17
+
18
+ # Build the package for distribution
19
+ npm run build
20
+
21
+ # Preview production build
22
+ npm run preview
23
+
24
+ # Run TypeScript type checking
25
+ npm run check
26
+ ```
27
+
28
+ ## Tech Stack
29
+
30
+ - **Svelte 5.16.0**: Latest Svelte with runes support
31
+ - **TypeScript 5.7.3**: Full type safety
32
+ - **Vite 6.0.5**: Fast build tooling
33
+ - **svelte-check**: TypeScript checking for Svelte files
34
+
35
+ ## Architecture
36
+
37
+ ### Component Structure
38
+
39
+ The main component is located at `src/lib/Switch.svelte`. This single component supports five distinct design variants controlled by the `design` prop:
40
+
41
+ - **slider/ios**: iOS-style toggle switch (default)
42
+ - **inner**: Toggle button with visible ON/OFF text
43
+ - **modern**: Enhanced slider with optional track icons
44
+ - **material**: Google Material Design inspired toggle
45
+ - **multi**: Radio group styled as a segmented control
46
+
47
+ ### Component API Design
48
+
49
+ The component uses a comprehensive props-based API with full TypeScript support:
50
+
51
+ #### Core Props
52
+ - `value`: Two-way bound state (boolean or string for multi design)
53
+ - `label`: Accessible label text
54
+ - `design`: Design variant selector
55
+
56
+ #### Styling System
57
+ - **Color Schemes**: 6 built-in schemes (blue, green, red, purple, orange, pink) + custom
58
+ - **Size Variants**: xs, sm, md, lg, xl (mapped to rem values) or custom number
59
+ - **Visual Options**: shadow, outline, rounded, labelPosition
60
+
61
+ #### State Management
62
+ - `disabled`: Prevents interaction, shows disabled UI
63
+ - `loading`: Shows spinner animation, prevents interaction
64
+ - `readonly`: Prevents changes but shows current state
65
+
66
+ #### Icon System
67
+ - `showIcons`: Enable icon display
68
+ - `onIcon`/`offIcon`: Customizable icons (text/emoji/symbols)
69
+ - Icons displayed differently per design variant
70
+
71
+ #### Animation Customization
72
+ - `animationDuration`: Transition duration in ms (default 300)
73
+ - `animationEasing`: CSS easing function (default 'ease-in-out')
74
+
75
+ #### Accessibility
76
+ - `ariaLabel`: Custom ARIA label
77
+ - `ariaDescribedBy`: Links to description element
78
+ - `id`: Custom element ID (auto-generated if not provided)
79
+
80
+ ### State Management
81
+
82
+ The component uses Svelte's reactive statements (`$:`) to sync internal and external state:
83
+
84
+ 1. **For slider/inner/modern/material designs**:
85
+ - Internal `checked` boolean tracks state
86
+ - Syncs with `value` prop (boolean or 'on'/'off' string)
87
+ - Two-way binding via `bind:value`
88
+
89
+ 2. **For multi design**:
90
+ - Uses native radio input `bind:group`
91
+ - Value is one of the strings from `options` array
92
+ - No internal checked state needed
93
+
94
+ 3. **Unique IDs**:
95
+ - Auto-generated using `Math.floor(Math.random() * 1000000)`
96
+ - Used for ARIA attributes (`aria-labelledby`, `id` attributes)
97
+ - Can be overridden via `id` prop
98
+
99
+ ### Accessibility Implementation
100
+
101
+ Comprehensive ARIA and keyboard support:
102
+
103
+ - **ARIA Roles**: `role="switch"` for toggles, `role="radiogroup"` for multi
104
+ - **State Attributes**: `aria-checked` reflects current state
105
+ - **Labeling**: `aria-labelledby` connects visual labels, `aria-describedby` for descriptions
106
+ - **Keyboard Navigation**: Space and Enter keys toggle state
107
+ - **Focus Management**: `:focus-visible` for keyboard-only focus rings
108
+ - **Disabled State**: Properly communicated to assistive technologies
109
+
110
+ ### Styling Architecture
111
+
112
+ All styles are scoped within the component using Svelte's `<style>` block:
113
+
114
+ - **CSS Custom Properties**: Used for theming (`--active-color`, `--off-color`, `--animation-duration`, `--animation-easing`)
115
+ - **Design-Specific Classes**: `.switch--slider`, `.switch--inner`, `.switch--modern`, `.switch--material`, `.switch-multi`
116
+ - **State Classes**: `.checked`, `.disabled`, `.loading`, `.shadow`, `.outline`
117
+ - **Conditional Rendering**: `{#if design === 'variant'}` blocks for each design
118
+ - **No External Dependencies**: Self-contained styling, no CSS framework required
119
+
120
+ ### TypeScript Integration
121
+
122
+ The component is written in TypeScript (`<script lang="ts">`):
123
+
124
+ - All props have explicit type annotations
125
+ - Union types for variant options (design, size, colorScheme)
126
+ - Event handlers properly typed (MouseEvent, KeyboardEvent)
127
+ - Exported types available for consumers
128
+
129
+ ### Demo Application
130
+
131
+ `src/App.svelte` serves as a comprehensive showcase of all component features:
132
+
133
+ - Organized into sections by feature category
134
+ - Interactive examples with state display
135
+ - Beautiful gradient background with card-based layout
136
+ - Responsive design for mobile devices
137
+ - Not included in the distributed package (development only)
138
+
139
+ ## Build Configuration
140
+
141
+ ### Vite Config
142
+ - Library mode enabled with entry point `src/lib/Switch.svelte`
143
+ - Package name: 'SvelteToggleSwitch'
144
+ - Standard Svelte plugin configuration
145
+
146
+ ### TypeScript Config
147
+ - Extends `@tsconfig/svelte` base configuration
148
+ - ESNext target for modern JavaScript
149
+ - Includes all `.svelte`, `.ts`, `.js`, and `.d.ts` files in `src/`
150
+ - Composite project with references to `tsconfig.node.json`
151
+
152
+ ### Package Configuration
153
+ - Version 2.0.0 (major rewrite)
154
+ - Peer dependency: Svelte 3.x, 4.x, or 5.x
155
+ - Development dependencies all on latest versions
156
+ - MIT licensed
157
+
158
+ ## Key Design Decisions
159
+
160
+ 1. **Single Component Approach**: All variants in one component file for easier maintenance
161
+ 2. **CSS-in-JS via Custom Properties**: Enables dynamic theming without style duplication
162
+ 3. **Progressive Enhancement**: Basic functionality without JavaScript, enhanced with interactivity
163
+ 4. **Accessibility First**: ARIA and keyboard support built-in, not added later
164
+ 5. **TypeScript Throughout**: Type safety for better DX and fewer runtime errors
165
+ 6. **Zero Dependencies**: No runtime dependencies beyond Svelte peer dependency
package/README.md CHANGED
@@ -1,54 +1,399 @@
1
1
  # Svelte Toggle Switch
2
2
 
3
- ## Install
3
+ A comprehensive, accessible, and highly customizable toggle switch component for Svelte applications. Built with TypeScript and designed with accessibility in mind.
4
4
 
5
- Install using NPM
5
+ ## Features
6
6
 
7
- ```js
8
- npm i svelte-toggle-switch
9
- ```
7
+ ✨ **5 Design Variants**: Slider (iOS), Inner, Modern, Material, and Multi-option\
8
+ 🎨 **Multiple Color Schemes**: 6 built-in schemes + custom colors\
9
+ 📏 **5 Size Options**: From extra small to extra large\
10
+ ♿ **Fully Accessible**: ARIA attributes, keyboard navigation, screen reader support\
11
+ 🔄 **State Management**: Disabled, loading, and read-only states\
12
+ 🎯 **Icon Support**: Custom icons with flexible positioning\
13
+ ⚡ **Smooth Animations**: Customizable duration and easing\
14
+ 📦 **TypeScript**: Full TypeScript support with proper types\
15
+ 🎭 **Flexible Styling**: Shadow, outline, and label positioning options\
16
+ 🚀 **Modern Stack**: Built with Svelte 5, Vite 6, and TypeScript 5
17
+
18
+ ## Installation
10
19
 
11
- Install using YARN
20
+ ### NPM
21
+ ```bash
22
+ npm install svelte-toggle-switch
23
+ ```
12
24
 
13
- ```js
25
+ ### Yarn
26
+ ```bash
14
27
  yarn add svelte-toggle-switch
15
28
  ```
16
29
 
17
- ## How to use
30
+ ### PNPM
31
+ ```bash
32
+ pnpm add svelte-toggle-switch
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ```svelte
38
+ <script>
39
+ import Switch from 'svelte-toggle-switch';
40
+
41
+ let enabled = false;
42
+ </script>
43
+
44
+ <Switch bind:value={enabled} label="Enable notifications" />
45
+ ```
46
+
47
+ ## Design Variants
48
+
49
+ ### Slider (iOS Style)
50
+ The default design, inspired by iOS toggles.
51
+
52
+ ```svelte
53
+ <Switch bind:value={enabled} label="Enable dark mode" design="slider" />
54
+ ```
55
+
56
+ ### Inner
57
+ Toggle with visible ON/OFF text inside the button.
58
+
59
+ ```svelte
60
+ <Switch bind:value={enabled} label="Auto-save" design="inner" />
61
+ ```
62
+
63
+ ### Modern
64
+ Enhanced slider with optional icon displays on the track.
65
+
66
+ ```svelte
67
+ <Switch
68
+ bind:value={enabled}
69
+ label="Wi-Fi"
70
+ design="modern"
71
+ showIcons={true}
72
+ onIcon="✓"
73
+ offIcon="✕"
74
+ />
75
+ ```
76
+
77
+ ### Material
78
+ Google Material Design inspired toggle.
79
+
80
+ ```svelte
81
+ <Switch bind:value={enabled} label="Bluetooth" design="material" />
82
+ ```
83
+
84
+ ### Multi-option
85
+ Radio group styled as a segmented control.
86
+
87
+ ```svelte
88
+ <Switch
89
+ bind:value={selectedOption}
90
+ label="View mode"
91
+ design="multi"
92
+ options={['Grid', 'List', 'Table']}
93
+ />
94
+ ```
95
+
96
+ ## Color Schemes
97
+
98
+ 6 built-in color schemes plus custom color support.
99
+
100
+ ```svelte
101
+ <!-- Built-in schemes -->
102
+ <Switch bind:value={enabled} colorScheme="blue" />
103
+ <Switch bind:value={enabled} colorScheme="green" />
104
+ <Switch bind:value={enabled} colorScheme="red" />
105
+ <Switch bind:value={enabled} colorScheme="purple" />
106
+ <Switch bind:value={enabled} colorScheme="orange" />
107
+ <Switch bind:value={enabled} colorScheme="pink" />
108
+
109
+ <!-- Custom colors -->
110
+ <Switch
111
+ bind:value={enabled}
112
+ colorScheme="custom"
113
+ color="#FF6B6B"
114
+ offColor="#F0F0F0"
115
+ />
116
+ ```
117
+
118
+ ## Size Variants
119
+
120
+ ```svelte
121
+ <Switch bind:value={enabled} size="xs" label="Extra Small" />
122
+ <Switch bind:value={enabled} size="sm" label="Small" />
123
+ <Switch bind:value={enabled} size="md" label="Medium (Default)" />
124
+ <Switch bind:value={enabled} size="lg" label="Large" />
125
+ <Switch bind:value={enabled} size="xl" label="Extra Large" />
126
+
127
+ <!-- Custom size (in rem) -->
128
+ <Switch bind:value={enabled} size={2} label="Custom Size" />
129
+ ```
130
+
131
+ ## States
132
+
133
+ ### Disabled
134
+ ```svelte
135
+ <Switch bind:value={enabled} label="Disabled" disabled />
136
+ ```
137
+
138
+ ### Loading
139
+ Shows a spinner animation.
140
+
141
+ ```svelte
142
+ <Switch bind:value={enabled} label="Loading..." loading />
143
+ ```
144
+
145
+ ### Read-only
146
+ Displays current state without allowing changes.
147
+
148
+ ```svelte
149
+ <Switch bind:value={enabled} label="Read-only" readonly />
150
+ ```
151
+
152
+ ## Icons
153
+
154
+ Add custom icons to your toggles.
155
+
156
+ ```svelte
157
+ <!-- Slider with icons -->
158
+ <Switch
159
+ bind:value={enabled}
160
+ label="Theme"
161
+ showIcons={true}
162
+ onIcon="🌙"
163
+ offIcon="☀"
164
+ />
165
+
166
+ <!-- Modern design with track icons -->
167
+ <Switch
168
+ bind:value={enabled}
169
+ label="Airplane Mode"
170
+ design="modern"
171
+ showIcons={true}
172
+ onIcon="✈"
173
+ offIcon="✕"
174
+ />
175
+ ```
176
+
177
+ ## Advanced Customization
178
+
179
+ ### Label Position
180
+ ```svelte
181
+ <Switch
182
+ bind:value={enabled}
183
+ label="Label on left"
184
+ labelPosition="left"
185
+ />
186
+ ```
187
+
188
+ ### Visual Enhancements
189
+ ```svelte
190
+ <!-- With shadow -->
191
+ <Switch bind:value={enabled} label="Shadow effect" shadow />
192
+
193
+ <!-- With outline -->
194
+ <Switch bind:value={enabled} label="Outline style" outline />
195
+
196
+ <!-- Without rounded corners (inner design only) -->
197
+ <Switch bind:value={enabled} design="inner" rounded={false} />
198
+ ```
199
+
200
+ ### Custom Animations
201
+ ```svelte
202
+ <Switch
203
+ bind:value={enabled}
204
+ label="Custom animation"
205
+ animationDuration={800}
206
+ animationEasing="cubic-bezier(0.68, -0.55, 0.265, 1.55)"
207
+ />
208
+ ```
209
+
210
+ ### Accessibility Props
211
+ ```svelte
212
+ <Switch
213
+ bind:value={enabled}
214
+ id="custom-id"
215
+ ariaLabel="Toggle notifications"
216
+ ariaDescribedBy="notification-description"
217
+ />
218
+ ```
219
+
220
+ ## Complete API Reference
221
+
222
+ ### Props
223
+
224
+ | Prop | Type | Default | Description |
225
+ |------|------|---------|-------------|
226
+ | `value` | `boolean \| string` | `false` | Current value (use with `bind:value`) |
227
+ | `label` | `string` | `''` | Label text displayed next to the switch |
228
+ | `design` | `'inner' \| 'slider' \| 'modern' \| 'ios' \| 'material' \| 'multi'` | `'slider'` | Visual design variant |
229
+ | `options` | `string[]` | `[]` | Options array (required for `multi` design) |
230
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| number` | `'md'` | Size variant or custom size in rem |
231
+ | `color` | `string` | `'#007AFF'` | Custom active color (CSS color value) |
232
+ | `offColor` | `string` | `'#E5E7EB'` | Custom inactive color (CSS color value) |
233
+ | `colorScheme` | `'blue' \| 'green' \| 'red' \| 'purple' \| 'orange' \| 'pink' \| 'custom'` | `'blue'` | Built-in color scheme |
234
+ | `disabled` | `boolean` | `false` | Disables interaction |
235
+ | `loading` | `boolean` | `false` | Shows loading spinner |
236
+ | `readonly` | `boolean` | `false` | Makes switch read-only |
237
+ | `showIcons` | `boolean` | `false` | Display icons on the switch |
238
+ | `onIcon` | `string` | `'✓'` | Icon shown when active |
239
+ | `offIcon` | `string` | `'✕'` | Icon shown when inactive |
240
+ | `animationDuration` | `number` | `300` | Animation duration in milliseconds |
241
+ | `animationEasing` | `string` | `'ease-in-out'` | CSS easing function |
242
+ | `ariaLabel` | `string` | `''` | ARIA label for accessibility |
243
+ | `ariaDescribedBy` | `string` | `''` | ARIA described-by attribute |
244
+ | `id` | `string` | auto-generated | Custom element ID |
245
+ | `labelPosition` | `'left' \| 'right'` | `'right'` | Position of the label |
246
+ | `rounded` | `boolean` | `true` | Use rounded corners (inner design) |
247
+ | `shadow` | `boolean` | `false` | Add box shadow |
248
+ | `outline` | `boolean` | `false` | Add border outline |
249
+
250
+ ## Accessibility
251
+
252
+ This component follows WAI-ARIA best practices:
253
+
254
+ - Proper `role="switch"` and `role="radiogroup"` attributes
255
+ - `aria-checked` state management
256
+ - `aria-labelledby` and `aria-describedby` support
257
+ - Full keyboard navigation (Space and Enter keys)
258
+ - Focus indicators with `:focus-visible`
259
+ - Screen reader friendly
260
+ - Disabled state properly communicated
261
+
262
+ ## Browser Support
263
+
264
+ - Chrome/Edge (latest)
265
+ - Firefox (latest)
266
+ - Safari (latest)
267
+ - iOS Safari (latest)
268
+ - Chrome for Android (latest)
269
+
270
+ ## TypeScript
271
+
272
+ This package includes TypeScript definitions. All props are fully typed for the best development experience.
273
+
274
+ ```typescript
275
+ import type { ComponentProps } from 'svelte';
276
+ import Switch from 'svelte-toggle-switch';
277
+
278
+ type SwitchProps = ComponentProps<Switch>;
279
+ ```
18
280
 
19
- ```js
281
+ ## Examples
282
+
283
+ ### Dark Mode Toggle
284
+ ```svelte
285
+ <script>
286
+ let darkMode = false;
287
+
288
+ $: if (darkMode) {
289
+ document.documentElement.classList.add('dark');
290
+ } else {
291
+ document.documentElement.classList.remove('dark');
292
+ }
293
+ </script>
294
+
295
+ <Switch
296
+ bind:value={darkMode}
297
+ label="Dark mode"
298
+ showIcons={true}
299
+ onIcon="🌙"
300
+ offIcon="☀"
301
+ colorScheme="purple"
302
+ />
303
+ ```
304
+
305
+ ### Form Integration
306
+ ```svelte
307
+ <script>
308
+ let formData = {
309
+ notifications: false,
310
+ marketing: false,
311
+ newsletter: true
312
+ };
313
+ </script>
314
+
315
+ <form>
316
+ <Switch bind:value={formData.notifications} label="Push notifications" />
317
+ <Switch bind:value={formData.marketing} label="Marketing emails" />
318
+ <Switch bind:value={formData.newsletter} label="Newsletter" />
319
+ </form>
320
+ ```
321
+
322
+ ### Async Toggle
323
+ ```svelte
20
324
  <script>
21
- import Select from 'svelte-toggle-switch';
325
+ let enabled = false;
326
+ let loading = false;
22
327
 
23
- let switchValue;
24
- let sliderValue;
25
- let multiValue;
328
+ async function handleToggle() {
329
+ loading = true;
330
+ try {
331
+ await api.updateSetting(enabled);
332
+ } catch (error) {
333
+ // Revert on error
334
+ enabled = !enabled;
335
+ } finally {
336
+ loading = false;
337
+ }
338
+ }
26
339
 
340
+ $: if (enabled !== undefined) {
341
+ handleToggle();
342
+ }
27
343
  </script>
28
344
 
29
- <Switch bind:value={switchValue} label="Enable Toggle" design="inner" />
30
- <p>
31
- Switch is {switchValue}
32
- </p>
345
+ <Switch bind:value={enabled} {loading} label="Enable feature" />
346
+ ```
347
+
348
+ ## Development
349
+
350
+ ```bash
351
+ # Install dependencies
352
+ npm install
33
353
 
34
- <Switch bind:value={sliderValue} label="Enable Toggle" fontSize={24} design="slider" />
35
- <p>
36
- Switch is {sliderValue}
37
- </p>
354
+ # Start development server
355
+ npm run dev
38
356
 
39
- <Switch bind:value={multiValue} label="Choose an Option" design="multi" options={['true', 'false']} fontSize={12}/>
40
- <p>
41
- Switch is {multiValue}
42
- </p>
357
+ # Build for production
358
+ npm run build
43
359
 
360
+ # Type checking
361
+ npm run check
44
362
  ```
45
363
 
46
- ### Options
364
+ ## Contributing
365
+
366
+ Contributions are welcome! Please feel free to submit a Pull Request.
367
+
368
+ ## License
369
+
370
+ MIT © [Ishan Karunaratne](https://github.com/ishansasika)
371
+
372
+ ## Repository
373
+
374
+ [GitHub Repository](https://github.com/ishansasika/svelte-toggle-switch)
375
+
376
+ ## Changelog
377
+
378
+ ### Version 2.0.0 (Latest)
379
+
380
+ **Major Rewrite** - Complete redesign with modern features:
381
+
382
+ - ✨ Added TypeScript support
383
+ - ✨ Added 3 new design variants (Modern, Material, Multi)
384
+ - ✨ Added 6 built-in color schemes + custom colors
385
+ - ✨ Added 5 size variants (xs, sm, md, lg, xl)
386
+ - ✨ Added loading state with spinner animation
387
+ - ✨ Added icon support with custom positioning
388
+ - ✨ Added disabled and read-only states
389
+ - ✨ Added customizable animations
390
+ - ✨ Added shadow and outline options
391
+ - ✨ Added label positioning (left/right)
392
+ - ✨ Enhanced accessibility (ARIA, keyboard navigation)
393
+ - 📦 Updated to Svelte 5, Vite 6, TypeScript 5
394
+ - 🎨 Complete UI/UX improvements
395
+ - 📚 Comprehensive documentation
47
396
 
48
- | API | Value |
49
- | --- | --- |
50
- | `label` | `Your Text` |
51
- | `design` | `inner`, `slider`, `multi` |
52
- | `fontSize` | `16px` |
53
- | `options` | `['true', 'false']` |
397
+ ### Version 1.0.0
54
398
 
399
+ - Initial release with basic toggle functionality
package/package.json CHANGED
@@ -1,17 +1,24 @@
1
1
  {
2
2
  "name": "svelte-toggle-switch",
3
3
  "private": false,
4
- "version": "1.0.0",
4
+ "version": "2.0.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
8
8
  "build": "vite build",
9
- "preview": "vite preview"
9
+ "preview": "vite preview",
10
+ "check": "svelte-check --tsconfig ./tsconfig.json"
10
11
  },
11
12
  "devDependencies": {
12
- "@sveltejs/vite-plugin-svelte": "^1.0.0-next.30",
13
- "svelte": "^3.44.0",
14
- "vite": "^2.9.9"
13
+ "@sveltejs/vite-plugin-svelte": "^5.0.4",
14
+ "@tsconfig/svelte": "^5.0.4",
15
+ "svelte": "^5.16.0",
16
+ "svelte-check": "^4.1.1",
17
+ "typescript": "^5.7.3",
18
+ "vite": "^6.4.1"
19
+ },
20
+ "peerDependencies": {
21
+ "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0"
15
22
  },
16
23
  "repository": {
17
24
  "type": "git",
@@ -23,7 +30,11 @@
23
30
  "toggle",
24
31
  "svelte switch",
25
32
  "toggle switch",
26
- "svelte-toggle-switch"
33
+ "svelte-toggle-switch",
34
+ "svelte component",
35
+ "ui component",
36
+ "accessible",
37
+ "typescript"
27
38
  ],
28
39
  "author": "Ishan Karunaratne <ishansasika@gmail.com> (https://ishansasika.mn.co/)",
29
40
  "license": "MIT",