@eikonstudio/variant
v0.1.0
Published
React-friendly helpers for switching between full landing page variants
Downloads
22
Readme
@eikonstudio/variant
React-friendly helpers for switching between multiple landing page variants.
@eikonstudio/variant is built for the case where one website has multiple full landing-page
designs and the user can choose which one they prefer from a toggle or switcher UI. The selected
variant is persisted, and the whole landing experience can swap seamlessly through one active
variant state.
Install
bun add @eikonstudio/variantreact is a peer dependency, so install it in your app if it is not already present.
What this package gives you
createLandingRegistry()to define the available landing variantsLandingPreferenceProviderto manage the active variant in ReactuseLandingPreference()anduseSetLandingPreference()hooksLandingVariantTogglefor a minimal unstyled toggle UILandingVariantRendererfor swapping the whole landing-page componentgetStoredVariant()/setStoredVariant()helpers for persistence
Quick Start
import {
createLandingRegistry,
LandingPreferenceProvider,
LandingVariantRenderer,
LandingVariantToggle,
type LandingRenderableVariant,
} from "@eikonstudio/variant";
function MinimalLanding({ headline }: { headline: string }) {
return <section>{headline} Minimal landing</section>;
}
function BoldLanding({ headline }: { headline: string }) {
return <section>{headline} Bold landing</section>;
}
const registry = createLandingRegistry([
{
id: "minimal",
label: "Minimal",
description: "Clean and simple",
component: MinimalLanding,
},
{
id: "bold",
label: "Bold",
description: "High contrast and punchy",
component: BoldLanding,
},
] as const satisfies readonly [
LandingRenderableVariant<{ headline: string }>,
LandingRenderableVariant<{ headline: string }>,
]);
export function LandingPage() {
return (
<LandingPreferenceProvider registry={registry} initialVariantId="minimal">
<LandingVariantToggle />
<LandingVariantRenderer componentProps={{ headline: "Welcome" }} />
</LandingPreferenceProvider>
);
}How it works
- Create a registry with 2 or more variants.
- Wrap your landing page area in
LandingPreferenceProvider. - Render
LandingVariantToggleso the user can choose a design. - Render
LandingVariantRendererto swap the full active landing component. - The selected variant id is saved to
localStorageby default.
Full-page variant switching
Use LandingVariantRenderer when each variant represents a different complete landing-page design:
const registry = createLandingRegistry([
{ id: "classic", label: "Classic", component: ClassicLanding },
{ id: "modern", label: "Modern", component: ModernLanding },
{ id: "editorial", label: "Editorial", component: EditorialLanding },
] as const);
export function MarketingSite() {
return (
<LandingPreferenceProvider registry={registry}>
<header>
<h1>Choose your preferred design</h1>
<LandingVariantToggle />
</header>
<main>
<LandingVariantRenderer componentProps={{}} />
</main>
</LandingPreferenceProvider>
);
}When the active variant changes, the rendered landing component changes with it.
Hooks
useLandingPreference()
Use this when you want full access to the active variant, the full variant list, and the setter:
import { useLandingPreference } from "@eikonstudio/variant";
function VariantBadge() {
const { activeVariant, variants, setVariant } = useLandingPreference();
return (
<div>
<p>Current: {activeVariant.label}</p>
{variants.map((variant) => (
<button key={variant.id} onClick={() => setVariant(variant.id)}>
{variant.label}
</button>
))}
</div>
);
}useSetLandingPreference()
Use this when you only need to change the variant:
import { useSetLandingPreference } from "@eikonstudio/variant";
function ChooseBoldButton() {
const setVariant = useSetLandingPreference<{
id: "minimal" | "bold";
label: string;
}>();
return <button onClick={() => setVariant("bold")}>Use bold design</button>;
}Persistence
By default, the package uses:
- storage key:
eikonstudio.variant.preference - storage adapter: browser
localStoragewhen available
You can override both:
<LandingPreferenceProvider
registry={registry}
storageKey="my-site.landing-variant"
storage={window.localStorage}
>
<LandingVariantRenderer componentProps={{}} />
</LandingPreferenceProvider>You can also use the low-level storage helpers directly:
import {
clearStoredVariant,
getStoredVariant,
setStoredVariant,
} from "@eikonstudio/variant";
const current = getStoredVariant({ registry });
setStoredVariant("modern", { registry });
clearStoredVariant({});SSR behavior
The package is SSR-safe:
- it does not read
windowduring module evaluation - it uses
initialVariantIdor the registry default during the initial render - it upgrades to the persisted client-side value after mount when one exists
That makes it suitable for React apps that render on the server and then hydrate on the client.
Development
cd packages/variant
bun run test
bun run lint
bun run buildLicense
MIT
