Overview
Toggle elements provide simple on/off controls. They’re perfect for enabling/disabling features or choosing between two states.
| Element | Use Case | Returns |
|---|
switch | Enable/disable features | boolean |
linkBehavior | Embed vs. direct link (Linktree-specific) | 'embedLabel' | 'linkOffLabel' |
Switch Toggle
Boolean toggle for enabling/disabling features. Provides a visual on/off switch UI.
Properties
| Property | Type | Description |
|---|
id | string | Unique identifier (becomes prop name) |
inputType | 'switch' | Must be 'switch' |
title | string | Field title |
description | string | Help text |
label | string | Label text next to switch |
defaultValue | boolean | Initial state (true = on, false = off) |
validation | object | Validation rules |
Validation
| Rule | Type | Description |
|---|
required | boolean | Switch must be ON (value must be true) |
Setting required: true means the switch must be ON. This is useful for terms acceptance or required opt-ins. Most switches should not be required.
Example
{
id: "showTitle",
inputType: "switch",
title: "Display Options",
description: "Toggle title visibility",
label: "Show title",
defaultValue: true,
validation: {
required: false // Optional - can be on or off
}
}
Usage in Layout
type Settings = {
showTitle: boolean
}
export default function ClassicLayout({ showTitle }: AppProps<Settings>) {
return (
<div>
{showTitle && <h1>My LinkApp</h1>}
<p>Content</p>
</div>
)
}
Common Patterns
Feature toggle:
{
id: "enableNotifications",
inputType: "switch",
title: "Notifications",
label: "Enable email notifications",
defaultValue: false
}
Display option:
{
id: "showDescription",
inputType: "switch",
title: "Display Options",
description: "Show or hide the description text",
label: "Show description",
defaultValue: true
}
Required acceptance:
{
id: "agreeToTerms",
inputType: "switch",
title: "Terms of Service",
description: "You must accept the terms to continue",
label: "I agree to the Terms of Service",
defaultValue: false,
validation: {
required: true // Must be ON
}
}
Privacy setting:
{
id: "publicProfile",
inputType: "switch",
title: "Privacy",
description: "Make your profile visible to everyone",
label: "Public profile",
defaultValue: false
}
Multiple Switches
Group related switches under one title:
elements: [
{
id: "showTitle",
inputType: "switch",
title: "Display Options", // Section title
description: "Control what appears on your LinkApp",
label: "Show title",
defaultValue: true
},
{
id: "showDescription",
inputType: "switch",
title: "", // Same section, no title
label: "Show description",
defaultValue: true
},
{
id: "showAuthor",
inputType: "switch",
title: "", // Same section
label: "Show author name",
defaultValue: false
}
]
Usage:
type Settings = {
showTitle: boolean
showDescription: boolean
showAuthor: boolean
}
export default function ClassicLayout({
showTitle,
showDescription,
showAuthor
}: AppProps<Settings>) {
return (
<div>
{showTitle && <h1>Title</h1>}
{showDescription && <p>Description</p>}
{showAuthor && <span>By Author</span>}
</div>
)
}
Switch vs. Checkbox
When to use switch vs. single checkbox:
| Use Switch When | Use Checkbox When |
|---|
| Enabling/disabling a feature | Accepting terms/agreement |
| Toggling display options | Opting into something |
| Turning something on/off | Confirming understanding |
| Immediate effect expected | Explicit consent required |
// ✅ Switch - for feature toggle
{ id: "enableDarkMode", inputType: "switch", label: "Enable dark mode" }
// ✅ Checkbox - for acceptance
{ id: "terms", inputType: "checkbox", options: [{ label: "I agree to terms", value: "agreed" }] }
Link Behavior
Linktree-specific control for how links behave when clicked. Users choose between showing your LinkApp UI (embed) or navigating directly to the URL (link off).
Properties
| Property | Type | Description |
|---|
id | string | Unique identifier |
inputType | 'linkBehavior' | Must be 'linkBehavior' |
title | string | Field title |
description | string | Help text |
label | string | Label for radio group |
defaultValue | 'embedLabel' | 'linkOffLabel' | Initial behavior |
linkBehaviorLabels | object | Labels for the two options |
validation | object | Validation rules |
Link Behavior Labels
| Property | Type | Description |
|---|
embedLabel | string | Label for showing LinkApp UI |
linkOffLabel | string | Label for direct navigation |
Link Behavior lets users choose:
- Embed (
embedLabel): Display your LinkApp’s UI when clicked (renders your layout)
- Link Off (
linkOffLabel): Navigate directly to the URL (bypass your layout)
If not specified, defaults to embedLabel (show your LinkApp).
Example
{
id: "linkBehavior",
inputType: "linkBehavior",
title: "Link Behavior",
description: "How should this link behave when clicked?",
label: "Click behavior",
defaultValue: "embedLabel",
linkBehaviorLabels: {
embedLabel: "Show custom video player",
linkOffLabel: "Go directly to YouTube"
},
validation: {
required: true
}
}
Usage in Layout
type Settings = {
linkBehavior: 'embedLabel' | 'linkOffLabel'
}
export default function ClassicLayout({
linkBehavior,
linkUrl
}: AppProps<Settings>) {
// If user chose "link off", redirect immediately
if (linkBehavior === 'linkOffLabel') {
window.location.href = linkUrl
return null
}
// Otherwise, show your custom UI
return (
<div className="custom-video-player">
<VideoEmbed url={linkUrl} />
</div>
)
}
Common Use Cases
Video embed:
{
id: "videoDisplay",
inputType: "linkBehavior",
title: "Video Display",
description: "Choose how to display YouTube videos",
linkBehaviorLabels: {
embedLabel: "Show video player on Linktree",
linkOffLabel: "Open YouTube in new tab"
},
defaultValue: "embedLabel"
}
Content preview:
{
id: "contentBehavior",
inputType: "linkBehavior",
title: "Content Preview",
linkBehaviorLabels: {
embedLabel: "Show article preview",
linkOffLabel: "Go directly to article"
},
defaultValue: "embedLabel"
}
Social media:
{
id: "socialEmbed",
inputType: "linkBehavior",
title: "Social Post Display",
description: "Display Instagram post or link to it",
linkBehaviorLabels: {
embedLabel: "Embed Instagram post",
linkOffLabel: "Open Instagram post"
},
defaultValue: "embedLabel"
}
When to Use
Use linkBehavior when:
✅ Your LinkApp embeds or displays content from the URL
✅ Users might want to bypass your UI and go straight to the source
✅ You’re building a media player, content previewer, or social embed
Don’t use when:
❌ Your LinkApp doesn’t use the linkUrl at all
❌ Going directly to the URL doesn’t make sense
❌ Your LinkApp is purely decorative
Validation
| Rule | Type | Description |
|---|
required | boolean | A behavior must be selected |
Typically, linkBehavior should have validation: { required: true } so users explicitly choose their preference.
Complete Example
Here’s a video embed LinkApp using both toggle types:
export default {
settings: {
title: "Video Player",
uses_url: true, // This app uses the linkUrl prop
elements: [
// Link behavior - embed vs. direct link
{
id: "linkBehavior",
inputType: "linkBehavior",
title: "Link Behavior",
description: "Choose how videos open",
linkBehaviorLabels: {
embedLabel: "Play video in Linktree",
linkOffLabel: "Open YouTube directly"
},
defaultValue: "embedLabel",
validation: { required: true }
},
// Feature switches
{
id: "autoplay",
inputType: "switch",
title: "Playback Options",
label: "Autoplay video",
defaultValue: false
},
{
id: "showControls",
inputType: "switch",
title: "", // Same section
label: "Show player controls",
defaultValue: true
},
{
id: "loop",
inputType: "switch",
title: "", // Same section
label: "Loop video",
defaultValue: false
}
]
}
}
Layout implementation:
type VideoSettings = {
linkBehavior: 'embedLabel' | 'linkOffLabel'
autoplay: boolean
showControls: boolean
loop: boolean
}
export default function ClassicLayout({
linkBehavior,
linkUrl,
autoplay,
showControls,
loop
}: AppProps<VideoSettings>) {
// Direct link - redirect to YouTube
if (linkBehavior === 'linkOffLabel') {
window.location.href = linkUrl
return null
}
// Embed - show custom player
return (
<div className="video-player">
<VideoEmbed
url={linkUrl}
autoplay={autoplay}
controls={showControls}
loop={loop}
/>
</div>
)
}
Best Practices
Use Clear Labels
// ✅ Good - descriptive
{ label: "Enable email notifications" }
{ label: "Show author name and profile picture" }
// ❌ Unclear
{ label: "Notifications" }
{ label: "Author" }
Set Sensible Defaults
// ✅ Good - off by default for optional features
{ id: "betaFeatures", defaultValue: false }
// ✅ Good - on by default for core features
{ id: "showTitle", defaultValue: true }
Use a single title for the group, empty strings for subsequent items:
{
id: "showTitle",
title: "Display Options", // Group title
label: "Show title"
},
{
id: "showDate",
title: "", // Same group
label: "Show date"
}
Link Behavior Labels Should Be Specific
// ✅ Good - tells users exactly what happens
linkBehaviorLabels: {
embedLabel: "Play video in Linktree",
linkOffLabel: "Open YouTube in new tab"
}
// ❌ Too generic
linkBehaviorLabels: {
embedLabel: "Embed",
linkOffLabel: "Link"
}
Type Safety
Define boolean types for switches:
type MySettings = {
showTitle: boolean
enableNotifications: boolean
autoplay: boolean
linkBehavior: 'embedLabel' | 'linkOffLabel'
}
export default function ClassicLayout(props: AppProps<MySettings>) {
// Full type safety ✨
const { showTitle, enableNotifications, autoplay, linkBehavior } = props
return <div>...</div>
}
Next Steps