packages/lynx-ui-swiper/SKILL.md
# lynx-ui-swiper SKILL `Swiper` is a high-performance, fully customizable carousel. It supports horizontal swiping, looping, auto-play, RTL, edge bounces, and both built-in and custom layouts/animations. This guide is written for AI code agents to generate correct, production-ready code with minimal back-and-forth. ## 1. Core Capabilities - Horizontal swipe with inertial paging and configurable `duration` and easing - Looping with `loop` and `loopDuplicateCount` - Auto Play with `autoPlay` an
npx skillsauth add lynx-family/lynx-ui packages/lynx-ui-swiperInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Swiper is a high-performance, fully customizable carousel. It supports horizontal swiping, looping, auto-play, RTL, edge bounces, and both built-in and custom layouts/animations. This guide is written for AI code agents to generate correct, production-ready code with minimal back-and-forth.
duration and easingloop and loopDuplicateCountautoPlay and autoPlayIntervalmode='normal' and mode='custom'main-thread:customAnimation (+ customAnimationFirstScreen for first screen rendering)bounceConfig and release callbacksRTL (true or 'lynx-rtl')consumeSlideEvent, and event coordination via blockNativeEventSwiperRef (swipeNext, swipePrev, swipeTo, cancelAnimation)Each <Swiper> must provide data, itemWidth, and render children via a function that returns a <SwiperItem>.
import { Swiper, SwiperItem } from '@lynx-js/lynx-ui'
const data = ['red', 'green', 'blue']
function Example() {
return (
<Swiper data={data} itemWidth={300}>
{({ item, index }) => (
<SwiperItem>
<view
style={{ width: '100%', height: '200px', backgroundColor: item }}
>
<text>Item {index}</text>
</view>
</SwiperItem>
)}
</Swiper>
)
}
<Swiper> calls your children function once per item with { item, index }.<SwiperItem> as the root of that function; place your content inside it.index for app content such as labels, item lookup, and indicators.Scenario + Layout Mode/Align + Sizes (
itemWidth,containerWidth) + Data + Interaction (loop, auto-play, bounces, RTL) + Callbacks + Optional custom animation
Examples:
spaceBetween=16, 5 items, itemWidth=350, an indicator, and Prev/Next buttons.”autoPlayInterval=2500), align start, and an end bounce for ‘Show More’.”mode='custom' Swiper with scale and translateX animation using main-thread:customAnimation.”mode='normal' with modeConfig.align (start/center/end) and optional spaceBetween.loop={true} and autoPlay={true} with autoPlayInterval.bounceConfig with startBounceItem/endBounceItem and widths; release callbacks fire with { type, offset }. Bounces are ignored when loop=true.mode='custom' and provide main-thread:customAnimation(value, index) => style. Duplicate this logic in customAnimationFirstScreen for first-screen rendering.RTL={true} or RTL={'lynx-rtl'}. The latter applies Lynx’s direction: lynx-rtl explicitly.scroll-view or other vertical scrollers, set experimentalHorizontalSwipeOnly={true} and, if native events are being swallowed, set blockNativeEvent={true}; tune consumeSlideEvent if needed.current from onChange, render an external indicator, and use SwiperRef to control navigation.containerWidth explicitly (screen width minus paddings) to avoid mis-measure; use style={{ overflow: 'visible' }} if centered items need to bleed.<Swiper
data={['red', 'green', 'yellow', 'purple']}
itemWidth={315}
itemHeight={220}
containerWidth={(lynx.__globalProps.screenWidth || 375) - 16}
loop
autoPlay
autoPlayInterval={2000}
mode='normal'
modeConfig={{ align: 'start', spaceBetween: 8 }}
experimentalHorizontalSwipeOnly
>
{({ item, index }) => (
<SwiperItem>
<view style={{ width: '100%', height: '100%', backgroundColor: item }} />
<text>Number.{index}</text>
</SwiperItem>
)}
</Swiper>
<Swiper
data={colors}
itemWidth={250}
itemHeight={200}
mode='normal'
bounceConfig={{
enable: true,
endBounceItemWidth: 100,
endBounceItem: (
<view style='display: linear; linear-orientation: vertical; height: 100%; width: 30px;'>
<text>Show More</text>
</view>
),
onEndBounceItemBounce: ({ type, offset }) => {
console.log('bounce', type, offset)
},
}}
>
{({ index }) => (
<SwiperItem>
{/* content */}
</SwiperItem>
)}
</Swiper>
mode='custom')import { interpolate, interpolateJS } from '@lynx-js/lynx-ui'
const ITEM_WIDTH = 250
function customAnimation(value: number) {
'main thread'
const scale = interpolate(value, [-1, 0, 1], [0.8, 1, 0.8])
const centerOffset = (lynx.__globalProps.screenWidth - ITEM_WIDTH) / 2
const translateX = interpolate(value, [-1, 0, 1], [
-ITEM_WIDTH + centerOffset,
centerOffset,
ITEM_WIDTH + centerOffset,
], 'extend')
return {
transform: `translateX(${translateX}px) scale(${scale})`,
'transform-origin': 'center',
}
}
function customAnimationFirstScreen(value: number) {
const scale = interpolateJS(value, [-1, 0, 1], [0.8, 1, 0.8])
const centerOffset = (lynx.__globalProps.screenWidth - ITEM_WIDTH) / 2
const translateX = interpolateJS(value, [-1, 0, 1], [
-ITEM_WIDTH + centerOffset,
centerOffset,
ITEM_WIDTH + centerOffset,
], 'extend')
return {
transform: `translateX(${translateX}px) scale(${scale})`,
'transform-origin': 'center',
}
}
<Swiper
data={colors}
itemWidth={ITEM_WIDTH}
itemHeight={200}
mode='custom'
main-thread:customAnimation={customAnimation}
customAnimationFirstScreen={customAnimationFirstScreen}
>
{({ index }) => (
<SwiperItem>
{/* content */}
</SwiperItem>
)}
</Swiper>
<Swiper
data={items}
itemWidth={350}
itemHeight={200}
mode='normal'
modeConfig={{ align: 'start', spaceBetween: 8 }}
RTL={true}
>
{({ index }) => (
<SwiperItem>
{/* content */}
</SwiperItem>
)}
</Swiper>
data: array of items to render; consumed by children render functionitemWidth: per-item width in px; requireditemHeight: optional per-item height; omit for natural/content-driven heightcontainerWidth: Swiper container width; default to lynx.__globalProps.screenWidthmode: 'normal' | 'custom'; affects item placementmodeConfig: { align?: 'start' | 'center' | 'end'; spaceBetween?: number } for normal modeloop / loopDuplicateCount: enable loop and control cloned head/tail countautoPlay / autoPlayInterval: enable and tune auto pagingbounceConfig: edge views and behavior; ignored when loop=trueoffsetLimit: limit offset to avoid blank edges, e.g. [0, containerWidth - itemWidth]consumeSlideEvent: angle windows for handling touches; default covers horizontalblockNativeEvent: when Swiper is inside other scroll containersRTL: true or 'lynx-rtl'onChange, onSwipeStart, onSwipeStop, main-thread:onOffsetChangemain-thread:easing, main-thread:customAnimation, customAnimationFirstScreeninterface SwiperRef {
swipeNext(): void
swipePrev(): void
swipeTo(
index: number,
options?: { animate?: boolean, onFinished?: () => void },
): void
cancelAnimation(): void // use with caution
}
{ item, index } and must return <SwiperItem>.initialIndex update after mount? It is only applied at first screen; later updates are ignored. Use swiperKey or resetOnReuse to reset.align='start'. Provide offsetLimit={[0, containerWidth - itemWidth]} to clamp the range.loop=true. Correct—bounce is ignored in looping.scroll-view, swipes feel conflicted. Set experimentalHorizontalSwipeOnly={true} and consider blockNativeEvent={true}; adjust consumeSlideEvent if needed.customAnimationFirstScreen? It mirrors main-thread:customAnimation for first-screen rendering until main-thread first-screen support arrives.overlap on <SwiperItem>’s direct child as needed.development
# lynx-ui-sortable SKILL `Sortable` is a headless drag-to-reorder list primitive for ReactLynx. It performs reordering on the main thread for smooth, gesture-driven animations and exposes a composable `SortableRoot` / `SortableItem` / `SortableItemArea` API. For massive datasets, prefer `List` or `FeedList`; `Sortable` targets small to medium reorder-able lists. ## 1. Core Capabilities - **Headless Composition**: Three building blocks — `SortableRoot`, `SortableItem`, and (optional) `Sortable
development
# lynx-ui-sheet SKILL ## What It Is `lynx-ui-sheet` is a headless Sheet primitive for ReactLynx. It supports bottom-sheet semantics and side-drawer semantics through the same composition model, state model, drag handling, backdrop, and snap-point APIs. Use it when a UI needs a dismissible panel that slides from an edge of the viewport and may be controlled by refs, external state, snap points, or drag gestures. ## Building Blocks - **`SheetRoot`**: Owns visibility state, side, snap points,
development
# Lynx UI Popover SKILL `lynx-ui-popover` is a headless primitive for building accessible, positioned floating elements. It handles the complex logic of positioning, stacking context, and enter/exit animations via `usePresence`. ## 1. Core Capabilities - **Headless & Composable**: Provides raw functional components (`Root`, `Trigger`, `Positioner`, `Content`) that you compose to build custom UIs. - **Auto Positioning**: The `PopoverPositioner` automatically calculates coordinates to anchor th
development
# lynx-ui-dialog SKILL `Dialog` is a dialog component, used to display important information or require user interaction, interrupting the current workflow. `lynx-ui-dialog` is a composite component built on `primitives`, offering high flexibility and customizability. ## 1. Core Capabilities - **Composite Component Structure**: Composed of `DialogRoot`, `DialogView`, `DialogBackdrop`, `DialogContent`, `DialogTrigger`, and `DialogClose`, allowing for free assembly of the dialog's structure. -