Pricing

Frame handbook

v5.1.0 (single-line composition, 2026-10-22) · @snowui-design-system/components

License: Before first reading component documentation, source code, or npm usage instructions, read the complete LICENSE. One review covers the same task and version. Public API configuration and changes to internal implementation have distinct license treatment. Legacy “foundation” and “coordination” labels indicate only their technical origin during migration.

Overview

Provide shared layout, state, loading, and motion capabilities, with explicit configuration for coordination and styling across components.

When to use it

Use Frame as a general host when you need layout, state, Context, loading, Skeleton, or motion. Use semantic HTML for ordinary page structure.

  • Row / column / grid select the layout; as declares the combination role, bind:element obtains the root element.

  • Use singleLine for one-line labels and row firstLine for graphics with prose that may wrap. Prefer tokens and public class/style for colors, spacing and radius.

  • Orchestrate*, target/action and styles are all undertaken by Frame; cross-component Motion uses initMotion() to establish context.

  • When styles are not configured and there is no Motion context, no cross-component registry or motion subscription is created.

Quick start

This example shows the recommended basic composition. See the sections below for more cases and composition limits.

<script lang="ts">	import { Frame, Badge, Button, Text } from '@snowui-design-system/components';</script> <Frame	column	contentFill	padding={6}	gap={4}	radius={5}	border={1}	whileHover={{ y: [0, -4], duration: 180 }}	style="width: min(100%, 30rem); background: var(--background-1);">	<Frame singleLine><Text lines={1} size={20} weight={600}>Build with SnowUI</Text><Badge as="trailing" count="v2.4" color="Indigo" /></Frame>	<Text>Compose responsive layout, state, interaction, and motion through one public foundation.</Text>	<Frame row><Button variant="filled" href="/components/quick-start">Quick Start</Button><Button as="trailing" variant="outline" href="/components">Browse components</Button></Frame></Frame>

API

Keyword Type Default Description
componentParts ComponentParts — The parts inside the composite component propagate the boundary; the ordinary page is used by the public parts through the host component, and this field is not directly configured.
enableResponsive boolean true Responsive listening ability. Control ResizeObserver and breakpoint detection.
enableContext boolean true The ability to provide context. Control FramePerception Context.
enableScaleObserver boolean false Dimensional proportional monitoring ability. Turn on the back CSS variable to write the runtime width and height, height-to-width ratio and unified size.
enableDefaultMotion boolean true New in v3.6.0 Default dynamic switch. When set to false, all while* of the Frame are not automatically injected into the default motion of the system. The while* configuration explicitly transmitted by the user will not be affected.
enableAutoLayout boolean true Automatic layout protocol switch. When Frame declares the direction of row / column, it is activated by default, and the data-auto-layout attribute is output on the root DOM, inheriting the three-slot perception, first-line alignment, Wrap, Gap and other rules of auto-layout.css. Set it to false to turn it off. For details, please refer to LayoutProtocol.md (source code reference: specs/maintainers/LayoutProtocol.md).
contentFill boolean false The width of ordinary content sub-items fills the Frame content area; the priority is higher than contentHug.
contentHug boolean false The width of ordinary content sub-items shrinks according to the content.
pinOffset number | string — Pin layout offset in two directions; numbers press px, and the string is output as it is; the new usage uses the corresponding Token string.
pinOffsetX number | string — Pin horizontal offset takes precedence over pinOffset; numbers are output by px, and the string is output as it is.
pinOffsetY number | string — Pin vertical offset takes precedence over pinOffset; numbers are output according to px, and the string is output as it is.
scaleHeightVar string --snowui-scale-height-runtime Runtime height variable name
scaleWidthVar string --snowui-scale-width-runtime Runtime width variable name
scaleAspectRatioVar string --snowui-scale-aspect-ratio-runtime Runtime aspect ratio variable name
scaleSizeVar string --snowui-scale-size-runtime Runtime unified size variable name
scaleObserverTarget "self" | "parent" 'self' Monitor the target node
scaleBasis "height" | "width" | "mixed" | "aspect" 'height' Proportional calculation based on the model
scaleMixHeightWeight number 0.5 High weight in mixed mode
scaleAspectBaseRatio number 1 aspect mode reference height and width ratio
sizeRatio number 1 Uniform size ratio (the multiplier of relative basis size; 1= equal to basis size)
iconSizeRatio number sizeRatio Icon independent proportion
avatarSizeRatio number sizeRatio Avatar independent ratio
class string — External CSS class name for style overlay or layout adjustment
style string — Inline style
children Snippet<[any]> — Sub-content (container component)
as string — Role declaration, used to declare one's own role in combination mode
tag string div Rendered HTML tag name
id string — Element ID. The motion must be manually specified by the user
element HTMLElement — Bind the root element (bindable)
use any[] — Svelte Actions Array
size number — Logical size of components. Used to pass to subcomponents through Context (such as resource components to select resolution)
iconSize number — New Independently control the size of the internal Icon (Context transmission)
avatarSize number — New Independently control the size of internal Avatar (Context transmission)
loading boolean false Whether to enter the loading state. It only indicates the status, not the specific visual presentation.
skeleton boolean true Whether the loading state renders the skeleton. The parent loading protocol can be inherited.
renderHints RenderHints — Self-registration for the component root’s Skeleton. The component supplies its final shape, size, corner radius, and line count; callers may override individual fields.
currentState CoreState "Idle" Externally controlled core state. For scenarios where the life cycle is managed by the parent, such as Toast / Portal, the status of Appear / Disappear / Active is handed over to the default dynamic system of Frame.
customStates string[] — Custom state name array to extend the state machine
StartLoad StateTransition — Change after loading
Load StateTransition — Change after loading is completed
Reload StateTransition — Transform after reloading, call onReload callback
Appear StateTransition — Transformation after the appearance is completed
Disappear StateTransition — Transformation after disappearing
Idle StateTransition — Change after free time
Active StateTransition — Transformation after activation
Disabled StateTransition — Transition after disabling
Validating StateTransition — Transition after validation starts
Uploading StateTransition — Change after uploading
Editing StateTransition — Change after editing
onReload () => Promise<void> — The callback performed when entering the Reload state is used for data refresh.
stateVars Record<string, StateValueMap<any>> — General state variable mapping (arbitrary variable name -> take values according to state)
stateClass StateValueMap<string> — Add class by status
stateStyle StateValueMap<string | Record<string, string | number>> — Add style by status
stateContent StateValueMap<any> — New in v3.6.0 Switch sub-content by status (Snippet), Frame automatically handles cross-fade inter-complement motion (Crossfade)
Click EventTrigger — Triggered when clicking
Drag EventTrigger — Triggered when dragging
Hover EventTrigger — Triggered when hovering
Focus EventTrigger — Triggered when focusing
Key | { key: string; state: CoreState } | { key: string; target: string; action: string; reverse?: boolean; } | { key: string; run: (e?: any) => void } — Triggered when specifying keyboard keys
Scroll EventTrigger — Triggered when scrolling to the component
collapsed boolean — The declaration closes the form and is consumed by the form and state ability; the trigger button is not automatically provided.
expanded boolean — The declaration unfolds the form and is consumed by the form and state ability; no additional content is automatically created.
responsive FrameResponsiveProps | false — Content adaptation configuration or false based on container width; when the response ability is enabled, the direction and content shrinkage are parsed according to the public FrameResponsiveProps.
xs "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy xs breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
sm "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy sm breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
md "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy md breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
lg "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy lg breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
xl "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy xl breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
2xl "row" | "column" | "grid" | "row-reverse" | "column-reverse" — Legacy 2xl breakpoint direction. With enableResponsive, it cascades mobile-first. Prefer page-level responsive utilities in new pages.
singleLine boolean false Explicit single-line graphics or text composition: horizontal centering, no wrapping, at least 4 CSS px spacing, stable leading/trailing attachments and shrinkable content. Takes priority over direction breakpoints and responsive structural fallback. It does not identify children or generate text or tooltips. Text lines=1 owns truncation and full-text access. Disabled when enableAutoLayout=false.
firstLine boolean false Explicit first-line alignment for graphics with prose that may wrap. Use singleLine for one-line labels; Frame does not identify content automatically. In row or row-reverse three-slot layout, center leading/trailing attachments on the first text line. Text inherits the host line height. No enhancement without row, attachments or auto layout; compatible with Pin.
row boolean — Set the horizontal layout; row takes priority when declaring column or grid at the same time.
column boolean — Set the vertical layout; it will take effect when row is not enabled, and change the direction with reverse.
grid boolean — Set the basic layout of the grid; it will take effect when row and column are not enabled, and the grid column is configured by public class/style.
reverse boolean — Whether to reverse execution
morph boolean — Enable your own layout change transition; do not replace the professional timeline inside the chart, table or text.
whileLoad MotionConfig | boolean — Motion configuration of Load state or trigger stage; object expression explicit motion, boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileReload MotionConfig | boolean — The motion configuration of the Reload state or trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileAppear MotionConfig | boolean — The motion configuration of the Appear state or trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileDisappear MotionConfig | boolean — The motion configuration of the Disappear state or trigger stage; the object expresses explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileIdle MotionConfig | boolean — Motion configuration of Idle state or trigger stage; object expression explicit motion, boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileActive MotionConfig | boolean — Active status or the motion configuration of the trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileDisabled MotionConfig | boolean — Motion configuration of Disabled state or trigger stage; object expression explicit motion, boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileClick MotionConfig | boolean — Motion configuration of Click state or trigger stage; object expression explicit motion, boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileDrag MotionConfig | boolean — Motion configuration of Drag status or trigger stage; object expression explicit motion, boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileHover MotionConfig | boolean — Hover state or the motion configuration of the trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileFocus MotionConfig | boolean — Focus state or the motion configuration of the trigger stage; the object expresses explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileKey MotionConfig | boolean — The motion configuration of the Key state or trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileScroll MotionConfig | boolean — Scroll state or the motion configuration of the trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Do not actively create business status, and do not take over the professional internal timeline of subcomponents.
whileValidating MotionConfig | boolean — Motion configuration of Validating state or trigger stage; object expresses explicit motion, and boolean controls the default ability of this stage. Compatible with migration capabilities, the new page does not expand the use.
whileUploading MotionConfig | boolean — The motion configuration of the Uploading status or trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Compatible with migration capabilities, the new page does not expand the use.
whileEditing MotionConfig | boolean — The motion configuration of the Editing status or trigger stage; the object expresses the explicit motion, and boolean controls the default ability of this stage. Compatible with migration capabilities, the new page does not expand the use.
whileCollapsed MotionConfig — Motion configuration of Collapsed state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
whileExpanded MotionConfig — Motion configuration of Expanded state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
whileXs MotionConfig — Motion configuration of Xs state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
whileSm MotionConfig — Motion configuration of Sm state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
whileMd MotionConfig — Explicit motion for the Md state or trigger. A compatibility feature; avoid introducing it in new pages.
whileLg MotionConfig — Explicit motion for the Lg state or trigger. A compatibility feature; avoid introducing it in new pages.
whileXl MotionConfig — Motion configuration of Xl state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
while2xl MotionConfig — 2xl motion configuration of state or trigger stage; object expression explicit motion. Compatible with migration capabilities, the new page does not expand the use.
variants Record<string, MotionConfig> — Dynamic variant attributes
delay number 0 Delayed execution time (ms)
loopMotion LoopMotionConfig — Loop animation configuration. By default, write duration / easing / iteration / direction / playState to Frame's --snowui-frame-loop-motion-motion-* variable; when preset="rotateClockwise", the Frame root node directly enables the built-in continuous rotation.
scroll ScrollConfig — Rolling linkage configuration
layoutId string — Shared element transfer ID
itemId string — Element replacement anchor ID (recommended; semantics is the same as layoutId)
scope FrameScope — Context ability scope: self, children, descendants, explicit; no additional restrictions on the dissemination of non-transmission.
access FrameAccess — Context operation permission; readonly is read-only, and writeable allows operations within the scope of the public agreement.
timeline string — Timeline statement: timeline:[ID]:[Order]
orchestrate boolean — Enable the motion arrangement of the parent Frame for sub-items.
orchestrateMode "sequential" | "random" | "parallel" — Sequential arranges sub-items in order, random and parallel at the same time.
orchestrateDelay number — The interval of sub-item arrangement is in milliseconds; the duration of each sub-item is not changed.
orchestrateOrder | "visual-row" | "visual-column" | "visual-row-reverse" | "visual-column-reverse" | "dom" — Sub-items are sorted in the order of visual rows, visual columns and their reverse or dom.
orchestrateGroup string — Arrange group identifiers to distinguish collaborative sub-items.
orchestrateTrigger "appear" | "hover" | "click" | "scroll" | "none" — Arrange trigger: appear, hover, click, scroll or none; none does not trigger automatically.
orchestrateTarget string — Arrange target selectors and restrict participating sub-items.
styles Record<string, Record<string, string | number>> — Configure the cross-Frame style arrangement according to the target ID; the key is #id, and the value is the style field and value, not the CSS selector of any descendants.
padding number — Legacy scalar visual field. New pages should use a padding token and public class/style, without adding a dependency on this compatibility prop.
gap number — Compatible spacing number, direct layout path mapping --gap-N; the new page has priority to correspond to gap Token, do not fill in the unregistered file.
radius number | "full" — Legacy corner radius field. New pages should use a radius token or a component’s public corner radius prop, without adding a dependency on the old scalar field.
border number — Compatible border fields; the new page uses border Token or component public border entrance.
innerBorder boolean | string — Compatible with the inner border field; the new page uses the component public entrance and registered Token, and the inner border can be created without any input.
fontSize number | string — Compatible font size fields; new page pairing uses --text-* and --leading-*, and does not use size Token to express the font size.
minWidth number | string — Minimum width; numbers are converted to px, and strings are used as CSS values; design restoration uses Token or applicable layout expressions.
minHeight number | string — Compatible with the minimum height field; ordinary pages are expressed through root style and size Token, and do not rely on unclear scalar parsing paths.
width number | string — Width; numbers are converted to px, and strings are used as CSS values; new usage priority components API and Token.
height number | string — Compatible with height fields; ordinary pages are expressed through root style and size Token.
opacity number — Transparency

This table is the shared API of Frame; the field is only valid in Frame.

Usage boundaries and details

Capabilities, responsibilities and costs

Frame is the only public host; layout, state, Context, loading / Skeleton, DOM transmission and motion share a set of implementations. Cross-component Motion establishes the context by initMotion(), and styles establishes the style arranger when explicitly configured. The internal timeline of pure algorithms, Observer and text or charts continues to be the responsibility of independent shared modules.

Native event wrappers read the current disabled and loading state from stable sources. If an ancestor capture handler synchronously changes either state during the same event, the later bubbling phase still blocks interaction using the latest value; if it also unmounts the Frame, no destroyed derived state is read.

The responsive content adapts to the props input of Frame, and the corresponding observer is not established when the ability is turned off. Cross-component listening is only enabled when there is a context; rolling listening is cleared when it is destroyed. Merging the component entrance does not mean that the global arranger is created by default.

Quick Reference for Keywords (Quick Reference)

Category Keyword
Capability switch enableResponsive, enableContext, enableScaleObserver, enableDefaultMotion
Identity attributes class, style, tag, id, as, size, iconSize, avatarSize, loading, skeleton, renderHints, element, use, children, customStates, ...rest
Scale scaleHeightVar, scaleWidthVar, scaleAspectRatioVar, scaleSizeVar, scaleObserverTarget, scaleBasis, scaleMixHeightWeight, scaleAspectBaseRatio, sizeRatio, iconSizeRatio, avatarSizeRatio
Status configuration currentState, StartLoad, Load, Reload, Appear, Disappear, Idle, Active, Disabled, Validating, Uploading, Editing
Status variables stateVars, stateClass, stateStyle
Status trigger Click, Drag, Hover, Focus, Key, Scroll
Form collapsed, expanded
Responsive responsive content adaptation; xs–2xl only compatible with old breakpoints
LAYOUT row, column, grid, reverse, firstLine, singleLine, morph, contentFill, contentHug, pinOffset, pinOffsetX, pinOffsetY
Motion triggers whileLoad, whileReload, whileAppear, whileDisappear, whileIdle, whileActive, whileDisabled, whileClick, whileDrag, whileHover, whileFocus, whileKey, whileScroll, whileValidating, whileUploading, whileEditing
Morphological motion whileCollapsed, whileExpanded
Responsive motion whileXs, whileSm, whileMd, whileLg, whileXl, while2xl
Motion parameters delay, loopMotion, variants, timeline, scroll, layoutId, itemId
Choreography orchestrate, orchestrateMode, orchestrateDelay, orchestrateOrder, orchestrateGroup, orchestrateTrigger, orchestrateTarget
Callback onReload

Capability Switches

Related files: Frame.svelte (source code reference: components/src/components/Frame.svelte) · frame-types.ts · frame-dom-runtime.svelte.ts

New in v3.2.0: Scale supports four calculation bases of height/width/mixed/height-to-width ratio, and can be written to runtime aspect ratio variables.

Layout model

Main layout model: Slot host layout. See the definition.. /.. /../specs/maintainers/LayoutProtocol.md §12.3 (source code reference: specs/maintainers/LayoutProtocol.md) and.. /.. /../specs/maintainers/LayoutProtocol.md §2 (source code reference: specs/maintainers/LayoutProtocol.md).

Frame is the infrastructure of the slot host layout:

  • When declaring row / column, or explicitly passing in enableAutoLayout={true}, the root node outputs data-auto-layout="true".

  • as="leading" / as="trailing" will be data-as, and the three paragraphs Leading / Content / Trailing will be processed by auto-layout.css.

  • Use row firstLine for graphics with prose that may wrap. It emits data-first-line="true"; prose inherits the host line height and attachments align with its first line. See LayoutProtocol section 4.4 (source reference: specs/maintainers/LayoutProtocol.md).

  • as="pin-*" will be seen as data-as="pin-*", and the absolute positioning of nine directions is uniformly processed by auto-layout.css; pinOffsetX / pinOffsetY takes precedence over pinOffset.

  • leading and trailing are always treated as Hug sub-terms; ordinary direct sub-terms as Content must allow min-width: 0.

  • The default automatic judgment of ordinary content width: Frame is Fill when there is an explicit width (width prop, style="width:...", w-full / size-full and other width class); Frame is Hug when the width is Hug. You can use contentFill / contentHug to force overwriting, and contentFill takes precedence when both appear at the same time.

  • enableAutoLayout={false} only turns off the protocol output of ordinary Frame; Input / Select / MenuItem / Field such control hosts will fix the protocol inside the component, and the external false does not close the internal slot layout.

Basic Properties (Base Props)

Related file: Frame.svelte (source code reference: components/src/components/Frame.svelte) · frame-identity.svelte.ts · frame-types.ts · frame-dom-runtime.svelte.ts · frame-class-state.svelte.ts (source code reference: components/src/logic/frame-class-state.svelte.ts)

...Rest | - | - | Attribute transmission. All undefined attributes are transmitted to the root element |

2.1 Size Control (Size Control)

Frame realizes cross-level size control through size attributes and context mechanisms:

  1. As a Provider: When Frame sets size={N}, the size N will be passed down through SIZE_CONTEXT_KEY.

  2. As Consumer: Internal Icon, Avatar and other components will automatically perceive and apply this size.

  3. Block: Subcomponents (such as Button or nested Frame) can overwrite the parent context by explicitly setting the size attribute to establish a new size benchmark.

 <Frame    size={32}           // Base size 32px (Fallback)    iconSize={20}       // All Icons become 20px    avatarSize={40}     // All Avatars become 40px>    <Avatar />    <Icon />      <Frame>        <Icon />        <Avatar />    </Frame>      <Button iconOnly aria-label="Action">        <Icon />    </Button></Frame>

Interaction and State (Interaction & State)

Related files: Frame.svelte (source: components/src/components/Frame.svelte) · frame-state.svelte.ts (source: components/src/logic/frame-state.svelte.ts) · frame-motion.svelte.ts (source: components/src/logic/frame-motion.svelte.ts) · frame-dom-runtime.svelte.ts · frame-class-state.svelte.ts (source: components/src/logic/frame-class-state.svelte.ts)

3.1 Core States (Core States)

Related file: frame-state.svelte.ts (source code reference: components/src/logic/frame-state.svelte.ts)

The core state supports chain transformation: automatically transition to the next state when the state is completed.

Support custom states: use the customStates attribute to define business-specific states

Transition Type:

  • State: Only transform the state

  • [State, 'auto']: Automatic transformation after the motion is completed

  • () => void: Only execute callback

  • { next?: State, auto?: boolean, run?: () => void }: combination configuration

auto keyword: indicates that automatic transformation after the motion is completed, without external triggering.

 <Button    Click={Active}    Active={[Disabled, 'auto']}    Disabled={[Idle, 'auto']}    whileActive={{ duration: 1500 }}    whileDisabled={{ duration: 2000 }}/>

Reload status and onReload callback

The Reload status is used to refresh the dynamic data in the component, and the onReload callback is automatically called when entering the Reload state.

 <Button    Click={Reload}    Reload={[Idle, 'auto']}    whileReload={{ duration: 1000, component: Spin }}    onReload={async () => { await fetchData(); }}>    <Refresh /> Refresh</Button>

3.2 Morphology (Morphology)

Related file: frame-state.svelte.ts (source code reference: components/src/logic/frame-state.svelte.ts)

Keyword Description
collapsed Close the state control attribute (boolean)
expanded Expand state control attribute (boolean)

3.3 Events (Events)

Related file: frame-state.svelte.ts (source code reference: components/src/logic/frame-state.svelte.ts) · frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

The event can drive the state transformation: When the event is triggered, the component enters the specified state.

Trigger Type:

  • State: Change to one-way fixed-point state

  • Record<State, State>: State mapping dictionary, which automatically flows to the next target state according to the current state (such as { Idle: "Active", Active: "Idle" })

  • LinkageControl: Control other components

  • () => void: Execute the callback function

  • { run: () => void, ... }: Combination configuration

 <Button    Click={{ Idle: "Active", Active: "Idle" }}    stateStyle={{        Idle: "opacity: 0.5; transform: scale(1);",        Active: "opacity: 1; transform: scale(1.1);"    }}>    Toggle Me</Button>

<Button Click={Active} />

<Input Key={{ key: 'Enter', state: Active }} />

3.4 State-driven content (State Content)

Related file: Frame.svelte (source code reference: components/src/components/Frame.svelte) · frame-class-state.svelte.ts (source code reference: components/src/logic/frame-class-state.svelte.ts)

New in v3.6.0: Using the stateContent attribute, you can directly render different content according to the current state (Snippet). The internal frame will automatically process the inter-intermation effect of the content ( crossfade of isosos replacement: the old content gradually disappears 150ms, and then the new content gradually appears 150ms).

{#snippet iconA()}    <Icon><Bell /></Icon>{/snippet}{#snippet iconB()}    <Icon><Star /></Icon>{/snippet}  <Frame    Click="Active"    Active={["Idle", "auto"]}    stateContent={{        Idle: iconA,        Active: iconB,    }}/>

3.5 Native event synchronization

Associated file: frame-state.svelte.ts (source code reference: components/src/logic/frame-state.svelte.ts) · frame-dom-runtime.svelte.ts

Frame automatically perceives and synchronizes all native DOM events to ensure that the internal state machine is consistent with the external event listener.

Supported event categories:

  • Mouse: click, dblclick, contextmenu, mouseenter, mouseleave, mousemove, mousedown, mouseup

  • Touch: touchstart, touchend, touchmove, touchcancel

  • Keyboard: keydown, keyup, keypress

  • Focus: focus, blur

  • Form: input, change, submit

  • UI: scroll


Text truncation (migration instructions)

Starting from v3.5.0, lines / onTruncate has been migrated from Frame to Text component. Frame no longer initializes the truncated module, and no longer consumes relevant keywords.

Related files: Text.svelte · frame-truncation.svelte.ts

 <Text lines={1}>    Very long text...    <Tooltip as="tooltip">Full content</Tooltip></Text>  <Text lines={0}>    Expandable content...    <Button as="more">Expand</Button></Text>

Responsiveness

Associated file: frame-responsive.svelte.ts

Keyword Description
responsive Inherit the content adaptation rules of Frame: the spacing is first compressed to the lower limit, and when it still cannot be released, the return direction, alignment and ordinary sub-item size; minPadding supports all / x / y / four unilateral lower limits

Switch semantics: When enableResponsive={false}, the breakpoint detection is not initialized; xs/sm/md/lg/xl/2xl overwriting will not take effect, and the layout only uses the basic direction (row/column/grid + reverse).

5.1 Breakpoints (Breakpoints)

Associated file: frame-responsive.svelte.ts

Layout value: row | column | grid | row-reverse | column-reverse

Inheritance logic: Breakpoint attributes support downward inheritance. For example, if you set sm="column", the larger breakpoint will also default to column, unless it is explicitly overwritten.

 <Frame row sm="column" lg="row" />

2 Scale Capability (Scale Capability)

Related files: frame-scale-observer.svelte.ts (source: components/src/logic/frame-scale-observer.svelte.ts) · scale.css (source: components/src/styles/scale.css) · frame-inline-style.svelte.ts (source: components/src/logic/frame-inline-style.svelte.ts)

Scale first observes size changes in the component itself or its parent (self/parent) to measure runtime width, height, aspect ratio, and unified size. It then calculates a ratio using height, width, mixed, or aspect. sizeRatio, iconSizeRatio, and avatarSizeRatio scale text, Icon, Avatar, padding, gap, corners, inner borders, and borders. By default, it observes and calculates only; styles change only when explicitly configured.

Calculation instructions and examples

The complete Scale calculation link, width change example (including H=28px scene) and 11 keywords are affected one by one, and are uniformly maintained in:

  • Frame-scale-observer.md (source code reference: components/src/logic/frame-scale-observer.md)

Default behavior (don't interfere with the existing style)

  • enableScaleObserver is only responsible for writing runtime variables (observation layer) by default.

  • By default, the existing text, icon, padding, gap, rounded corner, border and other visual styles of the component will not be automatically overwritten.

  • Only when entering the apply mode, the scale calculation value is applied:

    • data-scale-apply="true"(Frame is automatically written when explicitly setting sizeRatio / iconSizeRatio / avatarSizeRatio)

    • Or class snowui-scale-apply (external manual activation)

Scale ability characteristics

  • By default, only observation is turned on, not application; there is explicit configuration before application.

  • The observation layer is responsible for writing runtime size variables (width/height/height-to-width ratio/uniform size).

  • The application layer is only effective in apply mode, which is used to take over text, Icon, Avatar, padding, gap, rounded corners, inner border and other proportional styles.

Scale Override Priority

  1. External class overlay variable

  2. Props inject variables

  3. Default calculation value

Namely: class > props > default.

The perception relationship between Scale and Context

Related file: frame-perception.svelte.ts (source code reference: components/src/logic/frame-perception.svelte.ts) · Frame.svelte (source code reference: components/src/components/Frame.svelte)

Current design conclusion: Scale default does not access FRAME_CONTEXT_KEY.

Reason:

  1. The core output of Scale is CSS variables (style system consumption), which does not require subcomponents to be read through JS.

  2. Avoid the expansion of Context structure and reduce irrelevant subscriptions and couplings.

  3. The external class override priority is clearer: it is determined by the CSS variable link and does not rely on Context transmission.

Addition:

  • If there is a clear scenario in the future that "subcomponents must read the parent scaleBasis and do JS branches accordingly", then expose read-only fields to Context incrementally (such as scaleBasis) as needed.


Layout and Style (Layout & Style)

Related files: frame-layout.svelte.ts · Frame.svelte (source: components/src/components/Frame.svelte) · layout.css (styles) · auto-layout.css (styles) · frame-class-state.svelte.ts (source: components/src/logic/frame-class-state.svelte.ts)

[! IMPORTANT] Development ban (Redline): Frame and all subcomponents built on it are strictly prohibited from using tools from snowui.css. All display logic must be implemented in the component's own <style> block through the var(--token) reference tokens.css. See StyleSpec.md §2.11 for details (source code reference: specs/maintainers/StyleSpec.md)

6.1 Internal Layout Control (Direction)

Frame generates the corresponding style class name (Level 1 weight) by calculating direction:

Category Class name (Level 1) Description
row .snowui-direction-row Horizontal layout (flex)
column .snowui-direction-column Vertical layout (flex)
grid .snowui-direction-grid Grid layout (grid)
reverse .*-reverse Reverse layout modifier

For details of the style priority system, please refer to StyleSpec.md §2.6 (source code reference: specs/maintainers/StyleSpec.md)

6.1.1 Auto Layout Protocol (Auto Layout Protocol)

When enableAutoLayout={true} (default) and Frame declares row / column, Frame will output the data-auto-layout attribute in the root DOM and automatically inherit the Level 1 structured rule provided by auto-layout.css:

  • First-line alignment: use row firstLine for graphics with prose that may wrap, retaining the three-slot roles. See LayoutProtocol section 4.4 (source reference: specs/maintainers/LayoutProtocol.md).

  • Pin: Through as="pin-*" positioning, it does not occupy the three slots and the first row track, and can be aligned with the first row.

  • Three-slot perception: sub-elements declare roles through data-as="leading" / data-as="trailing", and CSS :has() automatically switches Flex ↔ Grid

  • Wrap is turned on by default, and it is automatically suppressed in Grid mode.

  • Gap default var(--gap-2)

  • The width of ordinary content automatically follows the container width strategy by default; contentFill / contentHug can be explicitly overwritten

  • Mirror arrangement: flip the visual order through direction: rtl when reverse + Grid

When setting enableAutoLayout={false}, this attribute is not output, and only the basic direction class of layout.css is used.

For the complete protocol specification, please refer to LayoutProtocol.md (source code reference: specs/maintainers/LayoutProtocol.md).

Single-line graphics and text

Use singleLine for single-line names, dates, status labels or avatar/name combinations. It implies row layout and prevents labels or flex children from wrapping, including direction breakpoint and responsive.direction fallbacks. Mark attachments as leading/trailing to retain Hug or Fixed sizing; ordinary content can shrink, and Pin stays outside the gap. Ordinary Frame wrapping, firstLine prose and internal Tag spacing remain unchanged.

<script lang="ts">    import {Frame, Icon, Text} from '@snowui-design-system/components';    import {Calendar} from '@snowui-design-system/resource-svelte';</script><Frame singleLine style="width: 12rem;">    <Icon as="leading" icon={Calendar} size={20} />    <Text lines={1}>Last updated just now</Text></Frame>

Text continues to own truncation, tooltips and full-text access; Frame does not duplicate them. Independent text elements can also use this composition, but consecutive characters in one text flow do not need artificial gaps. Shrink or truncate text first. When attachments and the minimum 4px gap cannot fit, retain content through outer local scrolling rather than shrinking or clipping attachments.

The preferred default gap remains 8px. Explicit gap index zero uses a 4 CSS px floor, including when root font size or gap-scale decreases. Larger preferred gaps retain existing responsive compression and restoration. Public class/style overrides must respect minimum spacing and single-line semantics. enableAutoLayout=false disables the preset; enableResponsive=false only stops observation. No observer, automatic child detection or DOM wrapper is added.

6.2 Layout Stability (Layout Stability)

Keyword Class name (Level 1) Description
morph .snowui-morph-container Open the morphological transition container and use CSS Grid Stacking to overlap different state contents.

6.3 Surface Hover Overwrite Variables

Related files: layout.css(styles) · StyleSpec.md §2.4.6 (source code reference: specs/maintainers/StyleSpec.md) · frame-inline-style.svelte.ts (source code reference: components/src/logic/frame-inline-style.svelte.ts)

When .snowui-hoverable needs to override the default hover overlay, the following variables can be used (no !important, no event script required):

Variable Effect Default retress
--snowui-frame-hover-image-override Directly overwrite the background-image of hover Default color-mix overlay

Example (white complete overlay):

<Frame  class="bg-red text-black-100"  style="--snowui-frame-hover-image-override: linear-gradient(#ffffff, #ffffff);"/>

Motion Capabilities (Motion Capabilities)

Related file: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · motion-config.ts · frame-inline-style.svelte.ts (source code reference: components/src/logic/frame-inline-style.svelte.ts)

7.0 Default Motion System (Default Motion System)

Related file: frame-motion-defaults.ts · frame-motion-defaults.md · motion/ (source code reference: components/src/motion) · FlowText.svelte (source code reference: components/src/components/FlowText.svelte) · FlowText.md · frame-inline-style.svelte.ts (source code reference: components/src/logic/frame-inline-style.svelte.ts)

Changed in v3.6.0: The dynamic file is migrated to the components/src/motion/ directory, and the enableDefaultMotion switch is added.

Frame's default dynamic system adopts the rule of "keyword trigger":

  • Switch Control: enableDefaultMotion defaults to true, and all default motion effects are automatically injected. When set to false, all while* of the Frame are not automatically injected into the system's default motion, and the while* configuration explicitly transmitted by the user is not affected.

  • As long as the state chain or trigger is used (such as Click / Hover / Load / Active), the corresponding while* will automatically inject the default motion.

  • The page can directly declare the visual channel: in while*={{ ... }}, the object is a complete visual channel declaration, and only the opacity / scale / x / y / blur / rotate and other channels that appear in the object are executed; the default visual channel will not be mixed in. The undeclared duration / easing / delay and spring dynamics parameters can still use the while* default value.

  • You can turn off the default motion by keyword: whileXxx={false}.

  • You can use other dynamic files to overwrite the default dynamic: whileActive={FLIP_MOTION}.

  • The default motion file is placed in the src/ directory and centrally managed by frame-motion-defaults.ts. Each while* corresponds to an independent while-*.ts file.

  • The basic motion definition file (replace.ts, fade-out.ts, morph.ts, move.ts, rotate.ts, number.ts) is stored in the src/ directory.

  • The default digital change motion uses FlowText (motionDefaults.number / motionDefaults.numberComponent).

  • Current strategy:

    • Status/life cycle keyword default injection visible motion (whileAppear→fadeIn, scale needs to be explicitly declared; whileDisappear→fadeOut, whileActive→morph, whileReload→rotateClockwise, whileDisabled→opacity 0.2);

    • Interactive keywords (Hover/Click/Focus/Drag/Key) are injected into empty configuration by default (no visual effects);

    • The page can be through while*={{...}} Overwrite, or while*={false} close.

In children snippet, Frame will transmit the default motion registry:

<Frame Click="Load">    {#snippet children({ motionDefaults })}        <Frame whileAppear={true} />    {/snippet}</Frame>

7.0.1 The boundaries of responsibilities with the internal special motion of the component

The default motion of Frame is the component-level outer motion and control layer, which is not the only implementation entrance of all internal animation algorithms:

  • Frame is responsible for the overall state, life cycle, transparency, displacement, scaling of the root element, and the parent arrangement of multiple sub-Frames.

  • With the special general ability of formal specification and shared realization, it can realize internal animation completely independently of the default motion of Frame, and does not require conversion to while* or consume Frame bridge timing. Characters, glyphs and digital animations of text motions are typical examples.

  • The special dynamic component must still take Frame as the root and transmit the applicable Frame Props. Therefore, when the parent level makes all sub-levels fade, explicitly sets the sub-level whileDisappear, or performs displacement/scaling on the component as a whole, the special dynamic component must respond like other Frame sub-levels.

  • The outer frame motion and the internal special motion are allowed to run at the same time: Frame controls the component as a whole, and the internal ability controls the details of the content. The two layers shall not cover the state and style of each other's responsibility.

  • enableDefaultMotion={false} Only turn off the automatic default injection of the current root Frame; the internal special effect continues to be valid, and the explicit while* configuration also continues to be valid.

Whether the special capability has been "universalized" is determined by the corresponding specifications and shared modules. The private animation of a single component should not bypass Frame or duplicate existing dynamic infrastructure on the grounds of this section. See TextMotionSpec.md §5.1 for the complete boundary of text motion effects (source code reference: specs/maintainers/TextMotionSpec.md).

The function of while* keywords

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

The keyword while* is dynamic caller, not a dynamic definition.

 <script>    const heightGrow = { height: '+20px', duration: 300 };</script>  <Frame whileIdle={heightGrow} /><Frame whileHover={{ scale: 1.05, duration: 200 }} />

While* Dynamic value configuration

Related file: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · motion-config.ts

whileActive={{  // Motion properties  scale: 1.1,  opacity: [0, 1],  height: '+20px',    // Supports relative syntax   // Execution options  delay: 100,  duration: 1500,  easing: 'cubicOut',  timeline: 'main:1',   // Import motion components  component: FlowText,   // Orchestration mode (for containers)  orchestrate: true,  orchestrateMode: 'sequential',  orchestrateDelay: 100,  orchestrateOrder: 'visual-row'}}

The visual channel of the explicit object will not be merged with the default visual shallow: whileAppear={{ opacity: [0, 1] }} only gradually appear, whileAppear={{ scale: [0.95, 1] }} only zooms; both can inherit the default timing. When you need to combine, write both channels to the object. whileAppear={true} means using a complete default visual.

If there is a clear default vision inside the SnowUI component, the component family preset should be directly referenced; the component vision should not be bound to the frame fallback that may evolve with whileXxx={true}. Frame's public API, page-level generic usage and document examples can still use boolean. Ordinary components need to explicitly retain the old generic opacity + scale to use GENERIC_SCALE_APPEAR_MOTION when entering.

7.1 Event-driven motion

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

Keyword Description
whileLoad Loading state motion. Only define the motion of real components in the loading state, and are no longer responsible for entering the loading state.
whileReload Motion when reloading
whileAppear Motion when it appears
whileDisappear Motion when disappearing
whileIdle Motion when idle
whileActive Motion when activated
whileDisabled Activation effect when disabled
whileClick Click motion
whileDrag Motion when dragging
whileHover Motion when hovering
whileFocus Focus motion
whileKey Keyboard motion
whileScroll Triggered when scrolling to the component center
whileValidating Verify the motion
whileUploading Uploading motion
whileEditing Motion in editing

7.1.1 Default Loading Protocol (Default Loading Protocol)

Associated file: Frame.svelte (source code reference: components/src/components/Frame.svelte) · frame-skeleton-runtime.svelte.ts · frame-dom-runtime.svelte.ts · frame-inline-style.svelte.ts (source code reference: components/src/logic/frame-inline-style.svelte.ts)

Changed in v3.8.0: loading becomes the entrance of the loading state, whileLoad returns to the pure loading state dynamic configuration, and skeleton independently controls whether the skeleton is displayed.

Current rules:

  • The root node of the page or block only needs to provide one loading signal, such as <Frame loading={pageLoading}>

  • Subcomponents do not need to declare loading one by one, and will automatically inherit parent loading through SKELETON_CONTEXT_KEY

  • skeleton defaults to true; when set to false, the real component content is retained, and only whileLoad is responsible for loading the motion.

  • The component root provides renderHints to complete the skeleton self-registration; Frame outputs the registration mark and automatically renders the corresponding form.

  • Parent Frame only detects the registered child of the first layer, and transmits the final variant / width / height / radius / rows

  • Unregistered ordinary Frame still renders general fallback; concentrated class mapping only retains the compatibility of the old caller.

  • Container type Frame When there is children and a specific component mapping is not hit, the subtree is reserved first, so that the subcomponents can render the skeleton separately.

  • When the leaf node fails to hit the mapping, the general rectangular skeleton is rendered back.

  • During loading, the root node will automatically output aria-busy="true" and data-loading="true", and block the interaction.

<Frame    loading={pageLoading}    renderHints={{ variant: "circle", width: 80, height: 80 }}/>

This means that:

  • There is no longer a need to write a whole set of Skeleton HTML parallel to real components for the page.

  • A clear source of loading signal is still required, but it usually only appears in the page root or block root.

<ScrollArea axis="horizontal" ariaLabel="Profile actions" width="100%"><Frame singleLine minWidth="max-content" loading={pageLoading}>    <Avatar as="leading" src={user.avatar} />    <Text lines={1}>{user.name}</Text>    <Button as="trailing">Submit</Button></Frame></ScrollArea> 
<Frame    loading={pageLoading}    skeleton={false}    whileLoad={{ opacity: 0.6, scale: 0.98 }}>    <Button>Submit</Button></Frame>

7.2 Morphological driving effect

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · motion/expand.ts (source code reference: components/src/motion/expand.ts) · motion/expand.md (source code reference: components/src/motion/expand.md)

Keyword Description Default motion
whileCollapsed Close the motion EXPAND_OUT_MOTION(scale 1→0.95 + fade away, 250ms easeOut)
whileExpanded Motion when unfolding EXPAND_IN_MOTION(scale 0.95→1 + gradual appearance, 250ms easeOut)

EXPAND_IN_MOTION / EXPAND_OUT_MOTION can also be directly used for whileAppear / whileDisappear, which is suitable for full-screen magnification, drawer pop-up and other scenarios.

 <script>    import { EXPAND_IN_MOTION } from "../expand";</script> {#if isOpen}    <Frame        bind:this={panelFrame}        whileAppear={EXPAND_IN_MOTION}    >     </Frame>{/if}

7.3 Responsive driving effect

Related file: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · frame-responsive.svelte.ts

Keyword Description
whileXs Ultra-small screen motion
whileSm Small screen motion
whileMd Middle screen motion
whileLg Big screen motion
whileXl Super-large screen motion
while2xl Super-large screen motion

7.4 Dynamic parameters

Related file: motion-config.ts · frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

Top Props (directly sent to Frame):

MotionConfig internal attributes (used in the while* configuration object):

Attribute Type Default Description
duration number 300 Animation duration (ms)
easing EasingFunction cubicOut Slow-motion function
scale number | [number, number] - Zoom
blur number | string | [number | string, number | string] - Blurred radius; numbers are processed by px
component Component - Dynamic components (FlowText, Spin, etc.)
 <Frame whileHover={{ scale: 1.05, duration: 200, easing: 'easeOut' }} />  <Frame loopMotion={{ duration: 1000, easing: 'linear', iterationCount: 'infinite' }} />  <Frame loopMotion={{ preset: 'rotateClockwise', duration: 1000, easing: 'linear', iterationCount: 'infinite' }} />

7.5 Scroll-Linked (Scroll-Linked)

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

Bind the motion attribute to the scrolling progress through the scroll attribute.

<Frame    scroll={{        offset: ["start center", "end center"],        y: [50, -50],      // Parallax movement        opacity: [0, 1],   // Opacity change        scale: [0.8, 1.2]  // Scale change    }}>    Parallax Item</Frame>

7.6 Shared Element Transfer (Shared Element / FLIP)

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · layout-flip.ts (source code reference: components/src/logic/layout-flip.ts)

Use layoutId or itemId for seamless FLIP transitions (First → Last → Invert → Play). Timing follows the system’s other motion and defaults to 300ms ease-out.

Share layout-flip.ts to provide two transfer strategies:

strategy Realize Applicable scenarios
"transform" (default) Transition translate + scale Images, cards, and fast shared-element transitions that do not need to preserve internal glyph size
"layout" Actual transition top / left / width / height The typesetting content of the code, text and other font sizes is consistent; the internal glyphs do not participate in scaling, and the width and height changes are rearranged by the browser in real time.

The layout strategy belongs to the shared module capability. When entering, the component calls beginFlipEnter(id, element, { strategy: "layout" }) after the target is mounted; when exiting, you can call applyFlipExit(element, target, { strategy: "layout" }), or pass the same option to Frame controller's playFlipTo. The existing layoutId of the undeclared policy automatically keeps the default transform behavior.

Automatic trigger (mount and play): Just declare the same layoutId in the target Frame, and Frame will automatically read the starting point from the module registry in $effect and play the entry effect:

 <Frame layoutId=”product-image-1” class=”size-40 rounded-4” />  <Frame layoutId=”product-image-1” class=”w-full h-300 rounded-0” />

Manual triggering (component self-controlled entry and exit): It is suitable for scenarios such as overlay layer and full-screen magnification that need to be controlled in the JS layer. Frame controller exposes four methods, of which captureFlip / playFlipTo without initMotion() context, which can be used in any component:

Way Do you need initMotion? Description
captureFlip(layoutId?) No Capture the current Frame location and write it to the module-level registry for reading the starting point when the target Frame is mounted.
playFlipTo(target, options?) No Withdraw the current Frame to the target HTMLElement or DOMRect in a FLIP way, and call options.onComplete after the animation is over. Time sequence 300ms ease-out.
captureLayout(layoutId?) Yes Same as above, but the context storage through Motion arrangement is suitable for scenarios that require global Motion coordination.
playLayoutTo(target, options?) Yes The same as above, it is driven by the Motion arranger, which supports more complex timing reading (appear bridge variable).
<script lang="ts">  import { Frame, Button } from '@snowui-design-system/components';  let rootFrame: ReturnType<typeof Frame>;  let fullscreenFrame: ReturnType<typeof Frame>;  let cardElement = $state<HTMLElement>();  let isFullscreen = $state(false);  function enterFullscreen() {    rootFrame.getController().captureFlip('my-fullscreen');    isFullscreen = true;  }  function exitFullscreen() {    if (!cardElement) return;    fullscreenFrame.getController().playFlipTo(cardElement, {      onComplete: () => { isFullscreen = false; }    });  }</script> <Frame bind:this={rootFrame} bind:element={cardElement}>  <Button onclick={enterFullscreen}>Expand card</Button></Frame>{#if isFullscreen}  <Frame bind:this={fullscreenFrame} layoutId="my-fullscreen" style="position: fixed; inset: 0; background: var(--white-100); padding: var(--padding-6);">    <Button onclick={exitFullscreen}>Return to card</Button>  </Frame>{/if}

7.7 Orchestration Mode (Orchestration)

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

The parent component controls the startup timing of the subcomponent motion through simple keywords.

Keyword Description
orchestrate Enable the arrangement mode
orchestrateMode Mode: sequential, random, parallel
orchestrateDelay Subcomponent startup interval (ms), default 100ms
orchestrateOrder Sort: visual-row, visual-column, dom
orchestrateGroup Arranged group ID
orchestrateTrigger Trigger timing: appear, hover, click, scroll, none
orchestrateTarget Target selector
 <Frame orchestrate orchestrateMode="sequential" orchestrateDelay={200} orchestrateOrder="visual-row">    <Card whileAppear={{ opacity: [0, 1] }} />    <Card whileAppear={{ opacity: [0, 1] }} />    <Card whileAppear={{ opacity: [0, 1] }} /></Frame>

Linkage Control (Linkage Control)

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts) · frame-state.svelte.ts (source code reference: components/src/logic/frame-state.svelte.ts)

All event keywords (Click, Hover, Focus, etc.) support control the motion of other components.

Use

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

Attribute Type Description
target string id of the target component
action 'play' | 'reset' | 'pause' Action type

Give a demonstration

Related files: frame-motion.svelte.ts (source code reference: components/src/logic/frame-motion.svelte.ts)

 <Button Click={{ target: 'chart-bars', action: 'play' }}>Start</Button>  <Card Hover={{ target: 'tooltip-1', action: 'play' }}>Hover me</Card>  <Button Click={{ target: 'chart-bars', action: 'reset' }}>Reset</Button>

Frame Evolution (Frame Evolution)

Related file: layout.css · frame-perception.svelte.ts (source code reference: components/src/logic/frame-perception.svelte.ts)

9.1 CSS Behavioral Tools

Associated file: layout.css

Frame no longer provides role attributes. When the component needs to share behavior, actively declare the tool class in class; component semantic-related cursor, user-select, link hover, etc. are autonomous by the component CSS.

Tools Description Default behavior
.snowui-hoverable The hover overlay of the operable surface Only background overlay is provided, cursor is not provided.
.snowui-field-bordered Enter the outer box Border, hover border, focus-within ring
<Frame>Click Me</Frame>

9.2 Ability Scope (Scope)

Related file: frame-perception.svelte.ts (source code reference: components/src/logic/frame-perception.svelte.ts)

The spread range of the ability is controlled through the scope attribute.

Scope Description
undefined Default, no restrictions
self It only acts on the components themselves.
children Only direct subcomponents (depth = 1)
descendants Act on the whole subtree
explicit Only explicitly specified targets

9.3 Context Permission (Access)

Related file: frame-perception.svelte.ts (source code reference: components/src/logic/frame-perception.svelte.ts)

Control the interaction permissions of the component to the context through the access attribute.

Access Description
writeable Default, can trigger the operation
readonly Read-only, can't trigger the operation of others
<Frame access="readonly">    I can read context, but I can't trigger actions.</Frame>

This section is protected. An AI must request user review before modifying it.

Add your custom instructions, business logic constraints or specific examples here.


Style Orchestration (Style Orchestration)

Related file: frame-orchestrator.svelte.ts (source code reference: components/src/logic/frame-orchestrator.svelte.ts) · frame-orchestrator.md (source code reference: components/src/logic/frame-orchestrator.md) · frame-inline-style.svelte.ts (source code reference: components/src/logic/frame-inline-style.svelte.ts) · frame-dom-runtime.svelte.ts

Frame style arrangement system is a centralized, high-priority style control system that supports complex operations. It allows developers to accurately control the style of any deep subcomponent (Target) through ID in the parent container (Orchestrator) and establish a linkage relationship between components.

10.1 Core Competencities

  1. Penetration control: root -> #child_btn, no need to pass Props layer by layer.

  2. Complex operation: Support JS expressions (e.g. size > 20 ? 4 : 0).

  3. Linkage response: Listen to the status of component A (width, hover) to drive component B style in real time.

  4. High priority: Default as an Inline Style application (P6), which can be upgraded to P7 through force if necessary (!important).

10.2 API Overview

Define the styles attribute on the root Frame:

<Frame    id="root"    styles={{        // Simple assignment (overrides default Props)        "#frame3": { padding: 8, radius: 4 },         // Nested component positioning        "#frame3_btn": { size: 32 },         // Dependency calculation (coordination)        "#frame3_icon": {            // When frame3_btn grows, the icon grows 1.2×            size: "1.2 * $#frame3_btn.size",            // Conditional logic            opacity: "$#root.width > 500 ? 1 : 0"        }    }}> </Frame>

10.3 Arrangeable attributes (Keywords)

Related file: frame-orchestrator.md (source code reference: components/src/logic/frame-orchestrator.md)

[! NOTE] Unique identifier (ID Requirement) style arrangement depends on the id attribute of the component for addressing. The rules are as follows:

  • Controlled component (Target): Must provide id (e.g., id="icon"), otherwise it cannot be selected by the styles rule.

  • Provider: Optionalprovide id. ID is only required when you need to refer to your own attributes (such as $#root.width) as the calculation source.

  • Variable Exposure: Only the attributes of components that explicitly set the ID will be exposed as CSS variables (e.g. --[id]-padding). The exposed rules follow StyleSpec.md §2.1 (source code reference: specs/maintainers/StyleSpec.md) and adopt the calculated benchmark mode.

Attribute Description Corresponding CSS variables (automatic exposure of calculated values)
width Width --[id]-width
height Height --[id]-height
minWidth Minimum width --[id]-min-width
minHeight Minimum height --[id]-min-height
size Uniform size --[id]-size
padding Inner margin --[id]-padding
gap Spacing --[id]-gap
radius Rounded corners --[id]-radius
fontSize Font size (1-8, automatic pairing line height) --[id]-font-size + --[id]-line-height (StyleSpec §2.1 mapping mode)
border Outer border --[id]-border
innerBorder Inner border --[id]-inner-border
opacity Transparency (0-1) --[id]-opacity

10.4 Expression Syntax (Expression Syntax)

Support JS subset syntax, and variables need to add the prefix $:

  • Reference variable: $#target.prop (e.g. $#sidebar.width)

  • Self-reference: $self.width

  • Mathematical operation: +, -, *, /, %

  • Logical operation: >, <, >=, <=, ==, ! =, &&, ||

  • Ternary operation: condition ? trueVal: falseVal

  • Math function: Math.max(...) , Math.min(...) , Math.floor(...)

Example:

// Show text when sidebar expands beyond 200px; otherwise hide itopacity: "$#sidebar.width > 200 ? 1 : 0" // Dynamic font size: add 1 for each 100px of widthfontSize: "12 + Math.floor($self.width / 100)"

10.5 Priority Rules (Priority)

Scene Weight Result
Orchestration vs Props P6 vs P4 Orchestration wins (Inline Style > CSS Var)
Orchestration vs Class P6 vs P5 Orchestration wins (Inline Style > Class)
Orchestration vs Style P6 vs P6 The style applied last wins (usually after the Orchestrator).
Orchestration(Force) P7 WIN (!important overwrite inline)

If you want to force overwrite all (including inline styles), please use the force modifier (API has not been opened yet, and it is currently processed internally on demand).


Site guide: frame

When to use Frame {#when-to-use}

Frame is the shared host for layout, state, loading, motion, and explicit coordination between components. Use semantic HTML when a page only needs ordinary structure.

Import {#import}

import { Frame, initMotion } from '@snowui-design-system/components';

Layout and content {#layout-and-content}

Use singleLine with leading/trailing attachments and Text lines={1} for one-line labels. Use row firstLine for wrapping prose; row, column, grid, and as compose other layouts. Use public tokens and class/style for visual values. loading and skeleton share the same inherited context.

Coordination {#coordination}

Call initMotion() during parent component initialization when using cross-component motion. Frame supports orchestrate*, target/action triggers, and styles rules. These capabilities use the same Frame implementation and context as ordinary layout.

API and examples {#api-and-examples}

API reference · Complete manual · Quick Start

Next steps {#next-steps}

Frame style overlay

Read the full LICENSE first; reuse that review for the same task, version, and scope.

First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.

This component source does not directly consume a registered component-specific override. Style composed children through public parts or an explicit child; do not guess variable names.

Design Guide · Token · Combination boundary

Frame type and status

Required Props: no named required Props.

Two-way binding: bind:element.

Inheritance: FrameProps. Consult the base class public documentation; fields excluded by Omit cannot be passed through unchanged.

Share Frame API · Return API

The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.

ComponentParts

Source: components/src/logic/component-parts.svelte.ts

export type ComponentParts = Record<string, ComponentPartProps | undefined>;

ComponentPartProps

Source: components/src/logic/component-parts.svelte.ts

export type ComponentPartProps = Record<string, unknown>;

RenderHints

Source: components/src/logic/frame-types.ts

export interface RenderHints {    variant?: SkeletonRenderVariant;    width?: string | number;    height?: string | number;    radius?: string | number;    rows?: number;}

SkeletonRenderVariant

Source: components/src/logic/frame-types.ts

export type SkeletonRenderVariant = "line" | "circle" | "rect";

CoreState

Source: components/src/logic/frame-types.ts

export type CoreState =    | "StartLoad"    | "Load"    | "Reload"    | "Appear"    | "Disappear"    | "Idle"    | "Active"    | "Disabled"    | "Validating"    | "Uploading"    | "Editing"    | (string & {});

StateTransition

Source: components/src/logic/frame-types.ts

export type StateTransition =    | CoreState    | [CoreState, "auto"]    | ((e?: any) => void)    | { next?: CoreState; auto?: boolean; run?: (e?: any) => void };

StateValueMap

Source: components/src/logic/frame-types.ts

export type StateValueMap<T = any> = Partial<Record<CoreState, T>>;

EventTrigger

Source: components/src/logic/frame-types.ts

export type EventTrigger =    | CoreState    | LinkageControl    | ((e?: any) => void)    | { run?: (e?: any) => void; stop?: boolean; prevent?: boolean; next?: CoreState; state?: CoreState;[key: string]: any }    | Partial<Record<CoreState, any>>;

LinkageControl

Source: components/src/logic/frame-types.ts

export interface LinkageControl {    target: string | object; // Support object ref (component instance)    action: "play" | "reset" | "pause"; // Action type    reverse?: boolean; // Whether to run in reverse    stop?: boolean; // Stop propagation    prevent?: boolean; // Prevent default}

FrameResponsiveProps

Source: components/src/logic/frame-types.ts

export interface FrameResponsiveProps {    /** Layout direction when content does not fit. Omission keeps the current direction. */    direction?: FrameResponsiveDirection;    /** Cross-axis alignment when content does not fit. */    align?: FrameResponsiveAlignment;    /** Main-axis alignment when content does not fit. */    justify?: "start" | "center" | "end" | "between";    /** When content does not fit, ordinary direct children shrink to content or fill the container. */    childrenWidth?: "hug" | "fill";    /** Minimum width of ordinary direct children when content does not fit; numbers are px. */    childrenMinWidth?: number | string;    /** Responsive minimum gap; numbers are px, default 4px. */    minGap?: number;    /**     * Responsive minimum padding; a number applies to all four sides, while an object supports all / x / y / individual-side overrides,     * all numbers are px, default 4px.     */    minPadding?: number | FrameResponsivePaddingMinimum;}

FrameResponsiveDirection

Source: components/src/logic/frame-types.ts

export type FrameResponsiveDirection =    | "row"    | "column"    | "row-reverse"    | "column-reverse";

FrameResponsiveAlignment

Source: components/src/logic/frame-types.ts

export type FrameResponsiveAlignment = "start" | "center" | "end" | "stretch";

FrameResponsivePaddingMinimum

Source: components/src/logic/frame-types.ts

export interface FrameResponsivePaddingMinimum {    /** Shared minimum for all four sides. */    all?: number;    /** Shared minimum for left and right. */    x?: number;    /** Shared minimum for top and bottom. */    y?: number;    top?: number;    right?: number;    bottom?: number;    left?: number;}

MotionConfig

Source: components/src/logic/motion-config.ts

export interface MotionConfig {    // === Transform properties ===    /** Scale factor (1 = 100%) */    scale?: number | [number, number];    /** Horizontal displacement (px or a unit-bearing string) */    x?: number | string | [number | string, number | string];    /** Vertical displacement (px or a unit-bearing string) */    y?: number | string | [number | string, number | string];    /** Rotation angle (degrees) */    rotate?: number | [number, number];    /** Y-axis rotation (degrees) for front/back flips */    rotateY?: number | [number, number];    /** Opacity (0–1) */    opacity?: number | [number, number];    /** Blur radius (numbers are px) */    blur?: number | string | [number | string, number | string];    /** Height (supports relative syntax such as "+20px") */    height?: number | string;    /** Width */    width?: number | string;    /** Background color */    backgroundColor?: SnowUIColor | string;    /** Foreground (text/icon) color for color transitions */    color?: SnowUIColor | string;     // === Timing options ===    /** Delay (ms) */    delay?: number;    /** Duration (ms) */    duration?: number;    /** Easing function */    easing?: EasingFunction;     // === Physics simulation ===    /** Motion type */    type?: 'spring' | 'tween';    /** Spring stiffness (higher is stiffer) */    stiffness?: number;    /** Spring damping (higher stops sooner) */    damping?: number;    /** Spring mass */    mass?: number;    /** Spring velocity threshold (below this counts as stopped) */    velocity?: number;     // === Component reference ===    /** Use a custom component as the motion carrier (such as FlowText or Spin) */    component?: any;     // === Orchestration controls ===    /** Whether to join parent orchestration */    orchestrate?: boolean;}

SnowUIColor

Source: components/src/lib/color.ts

export type SnowUIColor = keyof typeof SNOWUI_COLOR_TOKENS;

EasingFunction

Source: components/src/logic/motion-config.ts

export type EasingFunction =    | 'linear'    | 'easeIn' | 'easeOut' | 'easeInOut'    | 'cubicIn' | 'cubicOut' | 'cubicInOut'    | 'quadIn' | 'quadOut' | 'quadInOut'    | 'quartIn' | 'quartOut' | 'quartInOut'    | 'quintIn' | 'quintOut' | 'quintInOut'    | 'sineIn' | 'sineOut' | 'sineInOut'    | 'expoIn' | 'expoOut' | 'expoInOut'    | 'circIn' | 'circOut' | 'circInOut'    | 'backIn' | 'backOut' | 'backInOut'    | 'elasticIn' | 'elasticOut' | 'elasticInOut'    | 'bounceIn' | 'bounceOut' | 'bounceInOut'    | (string & {});

LoopMotionConfig

Source: components/src/logic/frame-types.ts

export interface LoopMotionConfig {    /** Loop preset (enables full looping motion on the Frame root) */    preset?: LoopMotionPreset;    /** Loop duration (ms) */    duration?: number;    /** Loop easing function */    easing?: MotionConfig["easing"];    /** Loop count (default infinite) */    iterationCount?: number | "infinite" | (string & {});    /** Loop direction (default normal) */    direction?:        | "normal"        | "reverse"        | "alternate"        | "alternate-reverse";    /** Playback state (default running) */    playState?: "running" | "paused";}

LoopMotionPreset

Source: components/src/logic/frame-types.ts

export type LoopMotionPreset = "rotateClockwise";

ScrollConfig

Source: components/src/logic/motion-config.ts

export interface ScrollConfig {    /** Scroll range ["start center", "end center"] */    offset?: [string, string];    /** Vertical displacement mapping */    y?: [number, number];    /** Horizontal displacement mapping */    x?: [number, number];    /** Opacity mapping */    opacity?: [number, number];    /** Scale mapping */    scale?: [number, number];    /** Vertical displacement mapping (alias for y) */    translateY?: [number, number];    /** Horizontal displacement mapping (alias for x) */    translateX?: [number, number];    /** Rotation mapping */    rotate?: [number, number];}

FrameScope

Source: components/src/logic/frame-types.ts

export type FrameScope = 'self' | 'children' | 'descendants' | 'explicit';

FrameAccess

Source: components/src/logic/frame-types.ts

export type FrameAccess = 'readonly' | 'writeable';