Declarative placements
Pass aplacements array to createSwish() and the SDK mounts them automatically at initialization. This is the recommended approach when you know which placements you need upfront.
swish.placements.list
After initialization, all declarative placements are available at swish.placements.list. Each entry is an object with spec, mount, and unmount properties, so you can control individual placements programmatically:
swish.placements.create(spec)
Creates a placement and returns an object with mount() and unmount() methods.
mount()starts observing the DOM and inserts elements when targets are found.unmount()removes all inserted elements and stops observing.
Placement spec
id
string
required
Unique identifier for this placement. Used internally for deduplication,
stylesheet scoping, and DOM attributes.
target
Defines which elements in the page the placement should attach to. The SDK uses a MutationObserver to watch for matching elements, including elements added after initial page load.
string
required
CSS selector to match target elements.
boolean | ((element: Element) => boolean)
Optional filter. Return
false to skip a matched element. A plain boolean is
also accepted, so config-authored placements can serialize the switch without
a function.IntersectionObserverInit
If provided, the element is only mounted when it becomes visible in the
viewport. Accepts standard
IntersectionObserver options.mount
Controls where the Swish element is inserted relative to the target.
string
required
Insertion mode. One of:
MountAt
Determines the reference element for insertion. Defaults to the target element itself. Options:
element
The Swish element to insert.
string
required
Element type. Currently supports
"save-button" and "header-button".Record<string, unknown>
Attributes to set on the element. Keys are converted to kebab-case (e.g.
productId becomes product-id).For save-button, supported props include match: "variant" | "product" | "auto" to control how saved state is interpreted. Use match: "product" for cards that show a default variant but should reflect product-level saved state. See match options for details.icon: "heart" | "bookmark" | "star" picks this button’s glyph. Leave it out to use the store’s Save button icon style.string[]
CSS classes to add to the element.
HTMLElement for full control:
style
"on-image" | "on-page"
Which look a
save-button renders. On image is an icon-only chip for buttons over product media - by default a #121212 heart on a white chip. On page is a heart with its label for buttons in the page flow - by default white on a #121212 button, sized like your theme’s buttons. Each look has its own design tokens, and a look’s tokens never affect the other.A placement on a collection grid (element.props.context: "product-card") is always On image, whatever style says. Otherwise the default is "on-page". The SDK reflects the resolved look on the <swish-ui> host as swish-save-style="on-image" or swish-save-style="on-page", so custom CSS can target one look.save-button also plays the store’s save animation. The SDK reflects it on the host as swish-save-animation, for example swish-save-animation="pulse", and "none" when the store picked none.
layout
Optional layout strategy for positioning the inserted element.
Overlay
Positions the element absolutely over the target’s parent. Useful for floating a Save button on top of a product card image.string
Corner to anchor to. One of
"top-left", "top-right", "bottom-left",
"bottom-right". Defaults to "bottom-right".{ x?: number, y?: number }
Pixel offset from the anchor corner. Supports responsive values.
number | string
Custom z-index for the overlay: an integer (as a number or a string such as
"20"), "auto", or a CSS-wide keyword such as "inherit". Any other value
is ignored and the default 10 applies.Inline
Wraps the reference element and the Swish element in a flex row, placing them side by side. Useful for adding a Save button next to an Add to Cart button.string
If provided, the SDK uses an existing container as the flex row instead of
creating a wrapper. The selector is resolved via
closest() from the
reference element.Anchored
Positions the element relative to any element in the DOM, regardless of where the element is inserted. Unlike overlay, which requires the element to be a child of its positioning reference, anchored decouples DOM insertion from visual positioning. Use this when the element you want to overlay is a sibling or cousin of the mount target.MountAt
The element to visually anchor to, resolved from the target element. Accepts
the same values as
mount.at. Defaults to the resolved mount target
(renderTargetEl).string
Where to position relative to the anchor element. Accepts any Floating UI
placement string such
as
"top-start", "top-end", "bottom-start", "bottom-end", "top",
"bottom", "left", or "right". Defaults to "bottom-end".boolean
Position inside the anchor element’s bounds rather than adjacent to it. When
true, the placement maps to corners within the anchor - for example,
"top-end" places the element at the top-right corner inside the anchor.
Defaults to false.number
Pixel offset from the anchor. When
inside is false, this pushes the
element away from the anchor edge. When inside is true, this acts as an
inward inset from the corner.number | string
Custom z-index for the anchored element: an integer (as a number or a string
such as
"20"), "auto", or a CSS-wide keyword such as "inherit". Any
other value is ignored. Defaults to 10.design
Design tokens specific to the element type. Values are emitted as CSS custom properties scoped to the placement.
Save button design tokens
Home button design tokens
Left alone, the button is a 44px hit target around a 20px heart drawn in the header’s text colour — the look of a theme’s own header icons. The badge is centred on a corner of the heart icon itself, with no outline, so it stays on the heart when the button shows text:statusIndicatorInset picks the corner and the two offsets nudge from there.
background, color and radius were removed — no header stylesheet read
them, so they persisted and published while rendering nothing. Use
statusIndicatorBackground for the badge and iconColor for the icon.container
Wraps the Swish element in an additional container element.
keyof HTMLElementTagNameMap
HTML tag for the container. Must be a valid HTML element tag name (e.g.,
"div", "span", "section"). Defaults to "div".string[]
CSS classes to add to the container.
breakpoints
Customize the responsive breakpoints used by design and layout.offset values. Defaults to { sm: 500, lg: 700 }.
css
Raw CSS string appended after all generated styles. Use this as an escape hatch for styling that design tokens don’t cover.
onMount / onUnmount
Lifecycle callbacks invoked when the element is inserted into or removed from the DOM.
MountContext passed to onMount includes:
Responsive values
Anydesign token or overlay offset accepts responsive values. Pass an object with base and breakpoint keys:
base value applies at all screen sizes. Breakpoint values apply at their min-width and above.
Ignoring elements
Add theswish-ignore attribute to any element to prevent placements from mounting on it: