Rapidly create, exercise, and share Svelte component states via URL-encoded permalinks.
Developing and testing components should be seamless. Svelte Gym provides a playground environment to exercise your components and ensure they respond correctly to various inputs and constraints.
Key Features:
npm install -D svelte-gym
# or
pnpm install -D svelte-gym
# or
bun install -D svelte-gym
Create a +page.svelte route for your component (e.g., src/routes/gym/my-component/+page.svelte):
<script lang="ts">
import { TestHarness, restoreProps, GymCheckbox, GymTextbox } from "svelte-gym";
import MyComponent from '$lib/MyComponent.svelte';
// 1. Define your component properties
let props = $state({
label: "Hello World",
isActive: true,
count: 0
});
// 2. Restore properties from URL parameters automatically
// This allows the URL to drive the component state
restoreProps(props);
</script>
<!-- 3. Wrap your component in the TestHarness -->
<TestHarness>
{#snippet componentToTest()}
<MyComponent {...props} />
{/snippet}
<!-- 4. Add controls to manipulate props -->
{#snippet controls()}
<ul>
<li><GymCheckbox bind:props name="isActive" /></li>
<li><GymTextbox bind:props name="label" /></li>
</ul>
{/snippet}
</TestHarness>
Svelte Gym is designed to be "interpreter-friendly." To ensure the best results and visual parity when using LLMs for component development:
componentToTest SnippetThe componentToTest snippet should only contain the component being tested.
[!IMPORTANT] Avoid wrapping the component in extra
divorsectiontags. This ensures that the component's layout and styles are tested in isolation, matching how it will appear when deployed.
Correct:
{#snippet componentToTest()}
<MyComponent {...props} />
{/snippet}
Incorrect:
{#snippet componentToTest()}
<div class="wrapper"> <!-- ❌ DON'T DO THIS -->
<MyComponent {...props} />
</div>
Gym* Input ComponentsAlways use the built-in Gym prefixed input components (e.g., GymSlider, GymTextbox, GymCheckbox) in the controls snippet.
[!IMPORTANT] Do not use standard HTML inputs or other custom components.
Gym*inputs are specifically designed to handle and test edge cases likenull,undefined,NaN, andInfinity, which are critical for robust component testing and are not supported by standard inputs.
http://localhost:5173/gym/button?label=Super+Long+Label+That+Breaks+LayoutTestHarnessThe main wrapper for your component playground.
Props:
maxWidth (number, optional): Maximum width constraint for the test area.maxHeight (number, optional): Maximum height constraint for the test area.maxFontSize (number, optional): Maximum font size for the test area.Snippets:
componentToTest: Place the component you want to test here.controls: Place Gym* controls here to modify props.restoreProps(props)Synchronizes the URL search parameters with your local props object. This must be called in your component's <script> section.
Gym* Components)All controls support bind:props and a name attribute corresponding to the property key in props.
GymCheckbox: Boolean toggle.GymTextbox: String input.GymSlider: Numeric slider (requires min, max).GymDropdown: Select from a list of options.GymRadioGroup: Radio button group.GymLog: Displays a log of events (passed as an array of strings).Svelte Gym supports nested properties using dot notation. This is useful for complex state objects.
<script lang="ts">
let props = $state({
config: {
theme: {
mode: 'dark'
}
}
});
</script>
In your controls:
<GymDropdown bind:props name="config.theme.mode" options={['light', 'dark']} />
MIT