Settings Panels
Gadgets can provide their own settings panel that appears in the Torchsnap settings window. This lets users configure gadget-specific options through a native-feeling UI rather than editing files manually. Settings panels use the same React and SDK infrastructure as views, but run in the settings window instead of the launcher.
Component contract
Section titled “Component contract”Settings panel components receive an empty props object. All data access happens through hooks:
import type { GadgetSettingsProps } from "@torchsnap/gadget-sdk";
export function MySettings(props: GadgetSettingsProps) { // ...}The host wraps your component in a standardized settings header (gadget name,
description, enable/disable toggle) and a GadgetContextProvider. Your
component renders the gadget-specific configuration controls below that header.
useGadgetSetting
Section titled “useGadgetSetting”The primary hook for settings panels. It provides reactive read/write access to a single setting key, scoped to the gadget’s namespace:
import { useGadgetSetting } from "@torchsnap/gadget-sdk/hooks";
const [retentionDays, setRetentionDays] = useGadgetSetting<number>("retentionDays");| Return | Description |
|---|---|
value: T |
The current value, JSON-parsed. Available synchronously on first render (the settings store is pre-loaded). |
setValue: (v: T) => Promise<void> |
Write a new value. The change propagates to all windows and to the backend’s on_setting_changed callback. |
Keys are relative to the gadget’s namespace. Requesting "retentionDays" reads
the full key gadgets.<gadget-id>.retentionDays in the store, but you never
see the prefix.
Default values
Section titled “Default values”Declare defaults in the manifest’s [settings] section. These are seeded into
the store on first load and never overwrite existing user values:
[settings]retentionDays = 30historyEnabled = truetheme = "auto"Your useGadgetSetting calls will return these defaults until the user changes
them.
Shared UI components
Section titled “Shared UI components”The SDK provides pre-built UI components that match the host’s design language.
Import them from @torchsnap/gadget-sdk/components:
Switch
Section titled “Switch”A toggle switch for boolean settings:
import { Switch } from "@torchsnap/gadget-sdk/components";
const [enabled, setEnabled] = useGadgetSetting<boolean>("historyEnabled");
<Switch checked={enabled} onChange={setEnabled} aria-label="Enable history"/>Slider
Section titled “Slider”A numeric range input with optional value formatting:
import { Slider } from "@torchsnap/gadget-sdk/components";
const [days, setDays] = useGadgetSetting<number>("retentionDays");
<Slider value={days} onChange={setDays} min={1} max={90} step={1} formatValue={(v) => `${v} days`}/>Section
Section titled “Section”Groups related settings under an optional heading:
import { Section } from "@torchsnap/gadget-sdk/components";
<Section title="History"> {/* Setting controls */}</Section>A labeled row for a single setting, with an optional description:
import { Entry } from "@torchsnap/gadget-sdk/components";
<Entry label="Retention period" description="How long to keep history entries"> <Slider value={days} onChange={setDays} min={1} max={90} /></Entry>A structured list with optional per-item actions:
import { List } from "@torchsnap/gadget-sdk/components";
<List items={[ { key: "item-1", primary: "First item", secondary: "Description text", actions: [ { label: "Remove", onClick: () => remove("item-1"), variant: "danger" }, ], }, ]} emptyState={<p>No items yet.</p>}/>Manifest registration
Section titled “Manifest registration”Register the settings panel in the manifest. The component value is the
JavaScript named export from the settings bundle:
[frontend]settings-bundle = "frontend/dist/settings.js"settings-css = "frontend/dist/settings.css"
[frontend.settings]component = "MySettings"Your settings entry point must export the matching name:
export { Settings as MySettings } from "./settings/Settings";