Switch (Multiple Conditions)
Handle multiple mutually exclusive conditions.
Basic Usage
import { createSignal, Switch, Match } from '@luna_ui/luna';
function StatusBadge() {
const [status, setStatus] = createSignal("pending");
return (
<Switch fallback={<span>Unknown</span>}>
<Match when={status() === "pending"}>
<span class="yellow">Pending</span>
</Match>
<Match when={status() === "active"}>
<span class="green">Active</span>
</Match>
<Match when={status() === "error"}>
<span class="red">Error</span>
</Match>
</Switch>
);
}
Switch vs Nested Show
Nested Show (verbose)
<Show when={status() === "loading"} fallback={
<Show when={status() === "error"} fallback={
<Show when={status() === "success"} fallback={
<DefaultView />
}>
<SuccessView />
</Show>
}>
<ErrorView />
</Show>
}>
<LoadingView />
</Show>
Switch (clean)
<Switch fallback={<DefaultView />}>
<Match when={status() === "loading"}>
<LoadingView />
</Match>
<Match when={status() === "error"}>
<ErrorView />
</Match>
<Match when={status() === "success"}>
<SuccessView />
</Match>
</Switch>
Extracting Values
Like <Show>, <Match> can extract truthy values:
const [response, setResponse] = createSignal(null);
<Switch>
<Match when={response()?.error}>
{(error) => <p>Error: {error.message}</p>}
</Match>
<Match when={response()?.data}>
{(data) => <DataView data={data} />}
</Match>
</Switch>
Order Matters
The first matching <Match> wins:
const [score, setScore] = createSignal(85);
<Switch fallback={<p>F</p>}>
<Match when={score() >= 90}><p>A</p></Match>
<Match when={score() >= 80}><p>B</p></Match> {/* This matches for 85 */}
<Match when={score() >= 70}><p>C</p></Match>
<Match when={score() >= 60}><p>D</p></Match>
</Switch>
Common Patterns
Tab Content
const [tab, setTab] = createSignal("overview");
<div>
<nav>
<button onClick={() => setTab("overview")}>Overview</button>
<button onClick={() => setTab("details")}>Details</button>
<button onClick={() => setTab("reviews")}>Reviews</button>
</nav>
<Switch>
<Match when={tab() === "overview"}>
<OverviewPanel />
</Match>
<Match when={tab() === "details"}>
<DetailsPanel />
</Match>
<Match when={tab() === "reviews"}>
<ReviewsPanel />
</Match>
</Switch>
</div>
Loading/Error/Success
const [state, setState] = createSignal({ status: "idle" });
<Switch fallback={<IdleState />}>
<Match when={state().status === "loading"}>
<Spinner />
</Match>
<Match when={state().status === "error"}>
<ErrorMessage error={state().error} />
</Match>
<Match when={state().status === "success"}>
<DataView data={state().data} />
</Match>
</Switch>
User Roles
const [user, setUser] = createSignal(null);
<Switch fallback={<GuestView />}>
<Match when={user()?.role === "admin"}>
<AdminDashboard user={user()} />
</Match>
<Match when={user()?.role === "moderator"}>
<ModeratorDashboard user={user()} />
</Match>
<Match when={user()}>
{(u) => <UserDashboard user={u} />}
</Match>
</Switch>
Step Wizard
const [step, setStep] = createSignal(1);
<div>
<Switch>
<Match when={step() === 1}>
<Step1 onNext={() => setStep(2)} />
</Match>
<Match when={step() === 2}>
<Step2
onBack={() => setStep(1)}
onNext={() => setStep(3)}
/>
</Match>
<Match when={step() === 3}>
<Step3
onBack={() => setStep(2)}
onSubmit={handleSubmit}
/>
</Match>
</Switch>
<p>Step {step()} of 3</p>
</div>
Media Type
const [media, setMedia] = createSignal({ type: "image", url: "..." });
<Switch fallback={<p>Unsupported media</p>}>
<Match when={media().type === "image"}>
<img src={media().url} />
</Match>
<Match when={media().type === "video"}>
<video src={media().url} controls />
</Match>
<Match when={media().type === "audio"}>
<audio src={media().url} controls />
</Match>
</Switch>
Dynamic Fallback
The fallback can also be reactive:
<Switch fallback={<p>No data for {category()}</p>}>
<Match when={items().length > 0}>
<ItemList items={items()} />
</Match>
</Switch>
Try It
Create a traffic light component with three states (red, yellow, green) that cycles through them:
Solution
function TrafficLight() {
const [light, setLight] = createSignal("red");
const cycle = () => {
setLight(current => {
switch (current) {
case "red": return "green";
case "green": return "yellow";
case "yellow": return "red";
}
});
};
return (
<div>
<div class="traffic-light">
<Switch>
<Match when={light() === "red"}>
<div class="light red">STOP</div>
</Match>
<Match when={light() === "yellow"}>
<div class="light yellow">CAUTION</div>
</Match>
<Match when={light() === "green"}>
<div class="light green">GO</div>
</Match>
</Switch>
</div>
<button onClick={cycle}>Next</button>
</div>
);
}
Next
Learn about onMount โ