Styling
SvSeeds components provide a flexible styling system. This document explains the two primary styling methods and their implementation details.
Overview
String-based Styling
Used when a string is specified for the styling prop, or when no value is provided. The specified class name is automatically applied to each part of the component. When no value is provided, the default component name is used.
Object-based Styling
Used when an object of a specific type is specified for the styling prop. This allows you to specify classes individually for each part of the component. Use this approach when working with TailwindCSS.
String-based Styling
In String-based Styling, the specified class name is applied in combination with each component part and variant.
Example
<script>
import { Button } from "svseeds";
const styling = "my-button";
</script>
<Button {styling}>Hello</Button>Generated HTML (class attribute excerpt):
<button class="my-button whole neutral">
<span class="my-button main neutral"> Hello </span>
</button>Object-based Styling
In Object-based Styling, you can specify classes individually for each part of the component. For detailed object specifications, see Object for Styling.
Example
<script>
import { Button } from "svseeds";
const styling = {
whole: "m-1 p-1",
main: "text-md",
};
</script>
<Button {styling}>Hello</Button>Generated HTML (class attribute excerpt):
<button class="m-1 p-1">
<span class="text-md"> Hello </span>
</button>Part Name System
To ensure styling flexibility, all elements within components are assigned part names.
Standard Part Names
The following part names are defined by default:
whole- Overall component wrappertop- Top regionmiddle- Middle regionbottom- Bottom regionleft- Left areamain- Main content arearight- Right arealabel- Label partaux- Auxiliary partextra- Additional part
Since part names are defined as string type, custom components can also define custom part names. For the specific part names used by each component, refer to the individual component documentation.
Variant System
Component styling adapts based on its current appearance variant.
Standard Variants
The following variant names are defined by default:
neutral- Default variantactive- Active variant (such as selected state)inactive- Inactive variant (also used for invalid/error states)
Since variants are defined as string type, custom variants can also be used.
Variant Behavior
Components fall into two categories: those that automatically manage their variant based on user interaction, and those that maintain a fixed variant. For detailed variant behavior of each component, refer to the individual component documentation.
Auto-Managing Components
Components like Toggle and TextField automatically update their variant in response to user interactions. For these components, the variant prop serves as an override for the default neutral variant.
Non-Auto-Managing Components
For these components, the variant prop directly sets the component's variant without any automatic changes.
Theme-based Style Switching
Use CSS prefers-color-scheme to configure theme switching. For theme toggle functionality, refer to the feature details of the DarkToggle component.
Animation & CSS Custom Properties
SvSeeds uses a shared convention for motion values and component-owned CSS custom properties. These props are set directly on the component, or on the child component that owns the motion, and CSS-expressible animation remains in caller CSS keyed off the existing part and variant classes.
cssvar maps a component-defined key to the CSS custom property name that component reads or writes. This lets you wire component internals to your own design tokens without changing the component's styling classes.
<script>
import { Slider } from "svseeds";
</script>
<Slider min={0} max={100} cssvar={{ active: "--brand", inactive: "--muted" }} />duration sets time-based motion in milliseconds. Components that expose CSS-driven timing publish the reduced-motion-aware value through the canonical --svs-duration custom property.
<script>
import { Modal } from "svseeds";
</script>
<Modal duration={200}>Content</Modal>transition is an escape hatch for JS-measured motion that CSS cannot express, such as auto-height or directional transitions. It accepts a { fn, params } object; for example, Disclosure defaults to slide but can be swapped.
<script>
import { fade } from "svelte/transition";
import { Disclosure } from "svseeds";
</script>
<Disclosure label="Details" transition={{ fn: fade, params: { duration: 150 } }}>Content</Disclosure>Object for Styling
Object Type
The object used in object-based styling is defined as the SVSClass type.
<script>
import type { SVSClass } from "svseeds";
const styling: SVSClass = {
whole: "whole-base",
main: {
base: "main-base",
neutral: "main-neutral",
active: "main-active",
},
};
</script>Advanced Class Value Specification
Property values can use clsx library-compatible values that are valid for Svelte's class attribute specification, as well as strings.
const styling = {
whole: ["whole-class", "class1", "class2"],
main: {
base: "main-class",
neutral: { foo, bar: !foo },
},
};Do not confuse the two object shapes. A clsx condition object such as { foo, bar: !foo } has boolean values and is one class value, used as the value of a single variant. The variant map, the object keyed by base, neutral, active, and so on, takes a ClassValue at each key; its values are never booleans.
Fallback Variant Style
If the current variant is not found in the object, the style defined for neutral will be used as a fallback.
<script>
import { Toggle } from "svseeds";
const styling = {
main: {
base: "text-md",
neutral: "bg-gray-400",
},
};
</script>
<Toggle {styling}>Hello</Toggle>Generated HTML (class attribute excerpt):
<!-- off state -->
<button class="text-md bg-gray-400">Hello</button>
<!-- on state -->
<button class="text-md bg-gray-400">Hello</button>Shorthand Notation
You can omit the variant and specify class attribute values directly for part names:
const styling = {
whole: "whole-class",
main: "main-class",
};This is interpreted as:
const styling = {
whole: {
base: "whole-class",
},
main: {
base: "main-class",
},
};Important Note
Shorthand notation also accepts clsx condition objects directly. An object whose values are booleans, such as { foo, bar: !foo }, is recognized as a class value and used as-is; no array wrapping is required:
const styling = {
whole: { foo, bar: !foo },
};This is interpreted as:
const styling = {
whole: {
base: { foo, bar: !foo },
},
};An object is treated as a variant map only when none of its values are booleans, for example { base: "base-class", active: "active-class" }. Wrapping the object in an array still works and is an explicit way to force a plain class value:
const styling = {
whole: [{ foo, bar: !foo }],
};