Pricing

ImageViewer handbook

v1.4.1 · @snowui-design-system/components

License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.

Overview

Preview images or videos in a page-level overlay with previous, next, and close controls. Use it for browsing media in detail.

When to use it

Use it for enlarged image viewing and navigation within a group. Use Image for ordinary images on the page; do not reimplement zoom, close, and keyboard interactions.

  • Use page-level automatic mode when open, items, and index are all omitted. In manual mode, pass the media list and current index explicitly.

  • Providing children replaces all built-in controls. Use parts to change the built-in buttons without removing previous, next, or close behavior.

Quick start

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

<script lang="ts">	import { Button, Image, ImageGroup } from '@snowui-design-system/components';	import { ImageViewer } from '@snowui-design-system/components';	import cover01 from '@snowui-design-system/resource-base/assets/backgrounds/gradient-01-1024.jpg';	import cover02 from '@snowui-design-system/resource-base/assets/backgrounds/gradient-02-1024.jpg';	import cover03 from '@snowui-design-system/resource-base/assets/backgrounds/gradient-03-1024.jpg';</script> <ImageGroup size={80}><Image src={cover01} alt="SnowUI resource cover 1" /><Image src={cover02} alt="SnowUI resource cover 2" /><Image src={cover03} alt="SnowUI resource cover 3" /></ImageGroup><ImageViewer />

API

Keyword Type Default Description
open boolean — Control the Viewer display in manual mode; enter the page-level automatic mode when omitted with items/index
items ImageViewerItem[] — Provide a list of preview items in manual mode; automatically consume the page-level preview status when omitted.
index number — The current display index is provided in manual mode; the page-level preview status is automatically consumed when omitted.
dismissMode "button" | "backdrop" "backdrop" Shutdown policy: backdrop hides the close button and allows clicking the blank outside the media to close; button shows the close button and disables the blank close
backdrop BackdropVariant "opaque" Share mask vision with Dialog: opaque is 10% black mask, blur blurs the background on it, transparent; do not change the closing strategy.
children Snippet — The explicit combination control button; replace all the default built-in buttons after providing
parts ComponentPartsOf<{ Button: typeof Button }> — Batch configure the default built-in prev / next / close Button

See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.

Usage boundaries and details

Control button dual mode

  • Default built-in mode: When children is omitted, three real Button are automatically generated, using ArrowLineLeft, ArrowLineRight, SnowUI Close respectively; default size="md", variant="gray", backgroundBlur={true}.

  • Parts batch configuration: parts.Button configures the configurable Props of all built-in control buttons; as, ARIA, click actions and icons are taken over by ImageViewer.

  • Explicit combination mode: No built-in buttons are generated after entering children; the caller uses Button as="prev|next|close" and directly configures Button Props.

The current main path is: Declare an automatic mode ImageViewer as a shared service in the page root layout. The Image / ImageGroup in the page will be automatically connected when previewMode is not explicitly set; if multiple automatic Viewers are mistakenly declared, only the first owner in the registration order will respond and render.

Layout model

Main layout model: composite management layout.

  • The regional structure of ImageViewer is portal overlay / viewport / media stage / media visual / controls.

  • Media sub-items are provided by Image or native media requests; the default control keys are built-in by ImageViewer. When explicitly combined, use Button / Icon and declare the role through as="prev" / "next" / "close".

  • Viewer only manages the preview layer, focus recovery, keyboard switching and media display, and does not abstract the internal control area into a three-slot host.

  • ImageGroup is responsible for collection registration, and ImageViewer is responsible for the single preview layer after opening.

Keywords

Keyword Type Default Description
parts.Button Button Props undefined Configure all built-in control buttons; default md / gray / backgroundBlur
as 'prev' | 'next' | 'close' - Control button role

Usage examples

<ImageViewer open={viewerOpen} items={items} index={currentIndex} />
 <ImageGroup size={80}>    <Image src="https://example.com/a.png" alt="A" />    <Image src="https://example.com/b.png" alt="B" />    <Image src="https://example.com/c.mp4" alt="C" /></ImageGroup> <ImageViewer />
 <Image    src="https://example.com/single.png"    alt="Single"    previewMode="viewer"/> <ImageViewer />
 <Image    src="https://example.com/single.png"    alt="Single"    previewMode="window"/> <ImageViewer />
 <Image    src="https://example.com/single.png"    alt="Single"    previewMode="none"/> <ImageViewer />
 <img    data-snowui-image-viewer-mode="viewer"    src="https://example.com/a.png"    alt="A"/> <ImageViewer />
 <img    data-snowui-image-viewer-mode="window"    src="https://example.com/a.png"    alt="A"/> <ImageViewer />
 <div data-snowui-image-viewer-scope>    <img        data-snowui-image-viewer-mode="viewer"        src="https://example.com/a.png"        alt="A"    />    <img        data-snowui-image-viewer-mode="viewer"        src="https://example.com/b.png"        alt="B"    />    <Image01        data-snowui-image-viewer-mode="viewer"        alt="C"    /></div> <ImageViewer />

Intelligent behavior

  1. Independent component: Split the preview state and the display state to avoid Image assuming the elastic layer, navigation and group index state.

  2. Full page sharing service: The root of the page declares an automatic mode ImageViewer; all Image/ImageGroups that do not explicitly specify previewMode automatically share it.

  3. Automatic mode and owner: open/items/index is registered to the page service when all are omitted; the first registration instance becomes owner, only the owner responds to the request and renders the Portal, and the owner automatically takes over after uninstalling.

  4. Manual mode: When open/items/index is explicitly passed in, ImageViewer will no longer take over page-level clicks, but will still establish a local preview status based on the input value, and support the default previous/next/close action.

  5. Default built-in control: The real Button control key is automatically generated when children is omitted; prev / next is hidden according to the boundary; close is only generated when dismissMode="button".

  6. Explicit combination control: If the external Button as="prev" / "next" / "close" is not explicitly transmitted to your own onclick, the previous, next and close actions of the Viewer will be automatically called; both automatic mode and manual mode are applicable.

  7. Resource compatibility: items supports string picture address, string video address and resource-svelte picture components at the same time.

  8. Video Preview: The video item is automatically played in the Viewer; use autoplay + muted + playsinline + loop to ensure that the preview layer is visible as soon as it is opened.

  9. Single Picture Preview: When Image is not in ImageGroup, the automatic mode Viewer will open the currently clicked media according to the single list.

  10. Intragroup switching: When Image is in ImageGroup, the automatic mode Viewer will consume the entire media list, so the previous/next can work.

  11. Component access link: When there is a shared Viewer on the page, the Image / ImageGroup of previewMode that is not explicitly declared will automatically enter the Viewer; the explicit viewer / window / none always takes priority.

  12. Native picture access: In automatic mode, native HTML <img data-snowui-image-viewer-mode="viewer" /> will also be captured and opened by ImageViewer.

  13. Resource image support: A resource-svelte image can forward data-snowui-image-viewer-mode="viewer" to its root <img> and join the page-level Viewer.

  14. DOM grouping: When the native <img> or resource-svelte picture is located in the [data-snowui-image-viewer-scope] container, the Viewer will establish the previous/next list in the DOM order in the scope; when there is no scope, it will be opened according to a single picture.

  15. Window DOM Link: In automatic mode, the native <img data-snowui-image-viewer-mode="window" /> will open directly in a new window without entering the Viewer.

  16. Backdrop fade-in: Opacity and blur appear gradually from transparent, using the Dialog backdrop preset. Show the backdrop immediately when reduced motion is requested; media and navigation remain responsive.

  17. Light prefetching before and after items: After opening the Viewer, light prefetching of the previous and next string pictures will be done to reduce the switching waiting feeling; the video does not participate in this prefetching chain.

  18. Prefetch deduplication: Prefetch each image URL only once per opening cycle, even as users navigate between items.

  19. Lightweight event handling: Automatic mode receives open requests through browser custom events and keeps preview state locally, without relying on a global Svelte store.

  20. DOM click adaptation: The automatic mode will also listen to the browser click event and identify the data-snowui-image-viewer-mode attribute on the native <img> / resource-svelte root <img>.

  21. Full page float: Viewer now uses fixed positioning to cover the entire page and floats above the page element through a higher z-index.

  22. Media maximization: The media shell is no longer covered with a gray background, but changed to a transparent container; pictures and videos are displayed according to the maximum size contain in the available display area.

  23. Margin rules: The maximum display area of the media should be kept at a distance of 10% from the left and right edges of the screen; the control button should be kept at a distance of 3% from the edge of the screen.

  24. Proportion rules: The media always maintains the original proportion and ensures that it is fully displayed in the visible area; the width is adaptive when the height touches the edge first, and the height is adaptive when the width touches the edge first.

  25. Click blank to close: Only when dismissMode="backdrop", click the preview area outside the media to close ImageViewer.

  26. Keyboard Control: In automatic mode, Esc closes the Viewer, A / W / ArrowLeft / ArrowUp switches to the previous one, and S / D / ArrowRight / ArrowDown switches to the next one.

  27. Boundary Stop: When the current item is the first one, the previous button is not displayed, and the previous keyboard operation is invalid; when the current item is the last one, the next button is not displayed, and the next keyboard operation is invalid.

  28. Portal mount: ImageViewer is directly mounted to document.body to avoid the transform / filter / contain of the ancestor layer from interfering with the fixed positioning.

  29. Three-layer Overlay structure: Viewer is now disassembled into three blocks: independent viewport, independent media-hitbox and independent controls. Media layout, blank closure, button clicks do not grab each other.

  30. 10% hard margin: viewport directly uses inset: 10vh 10vw, and the media can only be displayed in the remaining 80vw / 80vh visual frame.

  31. Root-level backdrop dismissal: In backdrop mode, a click outside the media and controls closes the Viewer. In button mode, backdrop clicks do nothing.

  32. Button separate layer: The control button is placed in the independent controls layer, the layer itself pointer-events: none, and only the button itself restores pointer-events: auto.

  33. Dismiss policy: dismissMode="button" shows a close Button and disables backdrop dismissal. dismissMode="backdrop" hides the close Button and lets users close the Viewer by clicking outside the media.

1. Running mode

  • ImageViewer has two operating modes:

    • Automatic mode: open/items/index is all omitted and driven by the page-level event bus.

    • Manual mode: explicitly pass in open/items/index, do not take over page-level events, but the internal will still mirror these values for default navigation and shutdown.

  • In automatic mode, the component will call the registerImageViewer() in image-preview.ts (source code reference: components/src/logic/image-preview.ts) to register that there is an available Viewer on the current page.

  • In automatic mode, the component will listen to the snowui:image-preview:open event and write the local status after receiving the event:

    • autoItems

    • autoIndex

    • autoOpen

  • In automatic mode, the component will also listen to window.click in the capture stage:

    • When it hits .snowui-image, it will be skipped and handled by Image itself.

    • When hitting the native <img data-snowui-image-viewer-mode="viewer"> or resource-svelte root <img data-snowui-image-viewer-mode="viewer">, directly build the DOM preview request

    • When hit <img data-snowui-image-viewer-mode="window">, open the string picture directly in a new window

2. Data processing

  • The current preview item is calculated by the following derived values:

    • resolvedItems

    • resolvedOpen

    • resolvedIndex

  • clampedIndex will constrain the index within the legal scope to avoid crossing the boundary in the previous/next.

  • currentItem is the media item that is actually rendered at present.

  • The media type is judged by string suffix:

    • Picture: ordinary string URL or resource-svelte component

    • Video: mp4 / webm / ogg / mov / m4v

  • When DOM picture is adapted:

    • Scope gives priority to reading the latest [data-snowui-image-viewer-scope]

    • All img[data-snowui-image-viewer-mode="viewer"] in scope will be composed of items in DOM order

    • Open according to the single picture when there is no scope.

3. Interaction logic

  • showPrev() / showNext():

    • Automatic mode is shared with manual mode

    • Requires itemCount > 1

    • Stop switching the boundary based on the current clampedIndex

    • The first one will no longer cycle forward to the last one, and the last one will no longer cycle backwards to the first one.

  • close():

    • In the automatic mode, markImageViewerClosed() of image-preview.ts (source code reference: components/src/logic/image-preview.ts) will be called first, and then autoOpen = false

    • Only turn off the manualOpen of the internal mirror in manual mode

  • The root layer onclick is uniformly handed over to handleRootClick():

    • If it hits the real media node (img / video / .snowui-image-viewer-media), it will not be closed.

    • If the control button layer controlsEl is hit, it will not be closed.

    • Click to close the rest of the area.

  • Keyboard control only takes effect in automatic mode:

    • Escape -> close()

    • A / W / ArrowLeft / ArrowUp -> showPrev()

    • S / D / ArrowRight / ArrowDown -> showNext()

4. Prefetching

  • When the Viewer is opened and the number of media is greater than 1, the previous and next items will be lightly prefetched.

  • Prefetching is only for string picture URL:

    • Video does not participate in prefetching

    • resource-svelte component does not participate in prefetching

  • prefetchedUrls deduplicates URLs within one opening cycle so window.Image() is not constructed repeatedly.

5. Host context

  • The component will expose the control protocol to the subcomponent through IMAGE_VIEWER_CONTEXT_KEY.

  • Expose three role-specific style entry points:

    • prevStyle

    • nextStyle

    • closeStyle

  • Expose three pin-direction entry points:

    • prevAs → pin-left

    • nextAs → pin-right

    • closeAs → pin-bottom

  • Provide 3 default action entrances to the outside world:

    • showPrev

    • showNext

    • close

  • Therefore, Button.svelte (source code reference: components/src/components/Button.svelte) / Icon.svelte (source code reference: components/src/components/Icon.svelte) can be automatically connected to the Viewer through as="prev" / "next" / "close".

6. Portal and root node

  • The Viewer root uses Frame.svelte (source: components/src/components/Frame.svelte):

    • Ordinary Frame

    • enableResponsive / enableContext / enableScaleObserver explicit transmission

  • Mount the overlay under document.body with use={[portalToBody]} instead of rendering it in place in the page tree.

  • Keep bind:element so the portal host remains within the Frame system and follows the existing portal component contract.

1. Root layer

  • Root class name: .snowui-image-viewer

  • Responsibilities:

    • Fixed full-screen floating layer

    • Set z-index

    • Provide typesetting benchmark font-size / line-height

    • Declare internal variables:

      • --snowui-image-viewer-viewport-padding

      • --snowui-image-viewer-control-margin

      • --snowui-image-viewer-background

2. Viewport layer

  • .snowui-image-viewer-viewport

  • Adopt position: fixed

  • Provide 10% safety margin on all sides through inset: var(--snowui-image-viewer-viewport-padding)

  • pointer-events: none

  • It is only responsible for providing the media available display area, and is not responsible for receiving clicks.

3. Media layer

  • .snowui-image-viewer-media-shell

    • Occupy the available viewport

    • Center the media.

    • Do not receive pointer events

  • .snowui-image-viewer-media-hitbox

    • The same layer as the media layout

    • At present, it is only used as a package layer for media hit judgment.

    • Do not actively receive pointer events

  • .snowui-image-viewer-media

    • It is the actual media node.

    • pointer-events: auto

    • object-fit: contain

    • max-width / max-height: 100%

    • Therefore, pictures and videos will be enlarged as much as possible at the original ratio within the 10% safe margin.

4. Control layer

  • .snowui-image-viewer-controls

    • Full screen coverage

    • pointer-events: none

    • Only as a positioning container for the role button

  • Selectors for the control buttons:

    • [class*="-role-prev"]

    • [class*="-role-next"]

    • [class*="-role-close"]

  • These buttons will restore pointer-events: auto

  • Positioning rules:

    • prev: Vertically centered on the left.

    • next: Vertically centered on the right.

    • close: Horizontally centered at the bottom.

  • All three use --snowui-image-viewer-control-margin, corresponding to the edge of the screen 3%

5. Default close button

  • When custom children are not passed and dismissMode="button", the built-in Button as="close" + SnowUI Close is rendered.

  • dismissMode="backdrop" does not create a built-in close Button; the explicitly combined Button as="close" is also hidden by Context.

  • The built-in close button follows the default configuration of ImageViewer's Button: md / gray / backgroundBlur.

1. Recommended usage: page-level automatic mode

  • Put only one ImageViewer in one page.

  • Do not transmit open/items/index

  • Image access it through previewMode="viewer"

  • Native HTML <img data-snowui-image-viewer-mode="viewer" /> and resource-svelte pictures can also be directly accessed

  • ImageGroup is responsible for providing group lists, and ImageViewer is responsible for displaying

This is the recommended page-level usage.

2. Manually controlled mode

  • When the page does not want to use global automatic takeover, it can explicitly pass open/items/index

  • At this time, ImageViewer is just an ordinary controlled preview component.

  • Pages suitable for demo, special business state or external existing state machines

3. The relationship with Image

  • Define the media source by src on Image

  • ImageViewer does not require the media link to be written again inside the component.

  • In automatic mode, only Image of previewMode="viewer" will send the click request to Viewer.

  • If the Image is not in the group, open it according to the single picture.

  • previewMode="window": Always open a new window, do not enter the Viewer

  • previewMode="none": Don't participate in preview at all

4. Relationship with ImageGroup

  • ImageGroup Size and layout of Image in the unified control group

  • At the same time, maintain snapshots of the media list in the group

  • After clicking Image in the group, ImageViewer will receive the whole group of media list and current index.

  • Therefore, prev / next is really meaningful only in the group scene.

5. Regressive behavior

  • Whether the Image component enters the Viewer is decided by its own previewMode.

  • Whether the native HTML <img> and resource-svelte pictures enter the Viewer is decided by data-snowui-image-viewer-mode.

  • previewMode="window": Even if there is a Viewer in the page, it will force the new window to be changed.

  • previewMode="none": The current picture does not participate in the preview at all.

  • data-snowui-image-viewer-mode="window": Native HTML / resource-svelte pictures open directly in a new window.

6.1 Image component

  • previewMode="viewer": Access page level ImageViewer

  • previewMode="window": Open a new window

  • previewMode="none": Don't participate in the preview

<Image src="https://example.com/a.png" alt="A" previewMode="viewer" /><Image src="https://example.com/b.png" alt="B" previewMode="window" /><Image src="https://example.com/c.png" alt="C" previewMode="none" /><ImageViewer />

6.2 ImageGroup component

  • ImageGroup previewMode="viewer": Image in the group is connected to ImageViewer by default

  • ImageGroup previewMode="window": Image in the group opens a new window by default

  • A Image in the group can also overwrite its own previewMode alone.

<ImageGroup size={80} previewMode="viewer">    <Image src="https://example.com/a.png" alt="A" />    <Image src="https://example.com/b.png" alt="B" />    <Image src="https://example.com/c.mp4" alt="C" /></ImageGroup> <ImageViewer />

6.3 Native HTML and resource-svelte

  • data-snowui-image-viewer-mode="viewer": Access ImageViewer

  • data-snowui-image-viewer-mode="window": Open a new window

  • data-snowui-image-viewer-scope: Form a group of media in the scope in order of DOM

Seven Example of DOM grouping

There is no scope: open according to the single picture

<img    data-snowui-image-viewer-mode="viewer"    src="https://example.com/a.png"    alt="A"/> <img    data-snowui-image-viewer-mode="viewer"    src="https://example.com/b.png"    alt="B"/>
  • Click the first one and only open the first one.

  • Click the second one and only open the second one.

  • Two pictures will not form the previous one/the next one with each other.

With scope: group in the same scope by DOM order

<div data-snowui-image-viewer-scope>    <img        data-snowui-image-viewer-mode="viewer"        src="https://example.com/a.png"        alt="A"    />    <img        data-snowui-image-viewer-mode="viewer"        src="https://example.com/b.png"        alt="B"    />    <Image01 data-snowui-image-viewer-mode="viewer" alt="C" /></div>
  • Click the first one to open the first of these three.

  • Click the second one to open the second one of these three.

  • Click Image01 to open the third of these three.

  • The previous/next one can only be switched within this scope, and will not jump to other pictures on the page.

8. Video definition

  • ImageViewer supports mixed preview of pictures and videos

  • The video is automatically played in the Viewer by default.

  • The video behavior in the thumbnail stage is not the responsibility of ImageViewer, but Image is responsible for hover playback.

ImageViewer 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.

Variable Purpose and default reference
--snowui-backdrop-background-override Share the mask background; take the background variant by default
--snowui-image-viewer-background-override Background (see component source for the default).
--snowui-image-viewer-z-index-override Z-index (see the component source code for the default value)

Design Guide · Token · Combination boundary

ImageViewer type and status

Required Props: no named required Props.

Bindable Props: this component declares no named two-way binding; handle state updates through public callbacks or its host.

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.

ImageViewerItem

Source: components/src/components/ImageViewer.svelte

interface ImageViewerItem {        src?: string | Component;        alt?: string;    }

BackdropVariant

Source: components/src/lib/backdrop.ts

export type BackdropVariant = "opaque" | "blur" | "transparent";

ComponentPartsOf

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

export type ComponentPartsOf<    T extends Record<string, Component<any>>,> = {    [K in keyof T]?: ConfigurableComponentPartProps<T[K]>;};

ConfigurableComponentPartProps

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

export type ConfigurableComponentPartProps<C extends Component<any>> = Partial<    Omit<ComponentProps<C>, ComponentPartControlledKey>>;

ComponentPartControlledKey

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

export type ComponentPartControlledKey =    | "children"    | "as"    | "value"    | "defaultValue"    | "open"    | "selected"    | "checked"    | "disabled"    | "readonly"    | "id"    | `on${string}`    | `aria-${string}`;