反应无头旋转木马
无头旋转木马组件,零依赖性:可滚动;可刷取旋转木马,甚至在桌面上,完成 与快闪, 摩擦 橡皮筋和过卷.
安装
npm install @daformat/react-headless-carousel
yarn add @daformat/react-headless-carousel
pnpm add @daformat/react-headless-carousel
bun add @daformat/react-headless-carousel
deno add npm:@daformat/react-headless-carousel
演示
https://hello-mat.com/design-engineering/组件/焦耳-组件
构成部分结构
/* Provides context to the carousel components */
<Carousel.Root>
{/* The scrollable area */}
<Carousel.Viewport>
{/* The container for the items */}
<Carousel.Content>
{/* A carousel item */}
<Carousel.Item />
<Carousel.Item />
<Carousel.Item />
</Carousel.Content>
</Carousel.Viewport>
{/* The pagination buttons */}
<Carousel.PrevPage />
<Carousel.NextPage />
</Carousel.Root>
构成部分
Carousel.Root
最外道的包装 为所有儿童旋转木马部件提供上下文。 显示 a <div>。 。 。 .
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
loop | boolean | false | 将两侧的孩子们拷贝并包好卷轴位置,因此旋转木马从未到尽头. 见 循环。 。 。 . |
autoplay | boolean | AutoplayOptions | false | 卷出自活马. true 每三秒跳到下一个项目;通过一个对象来选择速度和速度。 见 自动播放。 。 。 . |
boundaryOffset | { x: number; y: number } | ((root: HTMLElement) => { x: number; y: number }) | defaultBoundaryOffset | 将项目滚动到带有预览/下个按钮的视图端点时,从视图端点和后端的像素中插入。 默认执行读取内容从取景口淡出大小,所以项目永远不会被滚动到淡出后. 传递一个普通对象或接收根元素的函数并返回 { x, y } 以覆盖. |
reducedMotion | "respect" | "ignore" | "respect" | 怎么办 prefers-reduced-motion: reduce。见 减少动议。 。 。 . |
ref | Ref<HTMLDivElement> | 无 | 转发到根 <div>。 。 。 . |
...props | ComponentPropsWithoutRef<"div"> | 无 | 所有标准 <div> 道具( r)className, (中文(简体) ), style, (中文(简体) ), children(见a/c.5/49/70,附件). |
循环
loop 默认关闭。 打开它使旋转木马双向无尽: 它让孩子们三个
上面还有很多额外拷贝 用来覆盖几处景点 然后传送到
每当快用完时,滚动位置以一整批拷贝回放. 它离开的位置和
显示同样的像素,所以跳跃本身是看不见的.
在第一个孩子的木马公园上 瞬间没有明显的卷轴 拷贝是
标记 data-loop-clone, (中文(简体) ), aria-hidden 财务报告和审定财务报表 tabindex="-1",因此复制的元素本身被
辅助技术 和被打动, 当卷轴解决了 旋转木马回家 你真正的孩子.
覆盖每个副本,而不是里面的内容: 持有链接或按钮的副本仍然在标签中拥有控制
命令,因为两个属性都没有达到后人. 因此,持有可聚焦物品的项目将会通过
复制件,屏幕上的复制件仍可点击。 这通常是你想要的 用户可以明白的
看吧,但这确实意味着 偷袭可以降落在 aria-hidden 复制件,按DOM顺序,这不是复制件的顺序
来回在屏幕上。 有三样东西能防止它出现:
- 在屏幕上偷袭土地. 制表单的第一件事 坐在第一本里面, 在内容的开头, 所以去取它 扫描旋转木马回到开始。 到达 焦点被交给第一个完全可见的元素取而代之,而卷轴则停留在原地. 移动抓取 取最后一个可见的.
- {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}不 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}不 {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}不. 当标签顺序中的下个元素远远落后于当前时 位置,旋转木马首先跳出 整个副本朝它。 这种跳跃的两边都显示相同的像素,所以 没有看到任何距离, 其余的短到足以激活 已经前进的方式 而不是反对它。 当卷轴不能走那样, 因为那里没有更多的内容, 焦点 完全没有移动.
- 焦点环去焦点去的地方. 跳跃带着任何被聚焦在屏幕上的东西. 焦点交给了被取代的元素,所以环会停留在用户正在寻找的地方而不是 突然间消失.
三个都只供键盘使用. 点击时将焦点聚焦到任何点击、复制或不点击并获得普通 卷起最需要的治疗.
循环和快活是最佳的配对. 每个浏览器都驱动一个方向盘滚动,朝向一个坐标点 选择手势何时开始, 他们都不要在移动到下方的滚动位置: Chromium 卷回它选的那件东西 萨法里吞下剩下的动力 Firefox 掉下它要的 申请。 所以当包装扰动了卷轴时 旋转木马会从浏览器上扣下 一旦一切停止 动画化到位置
scroll-snap-type问. 铬 承诺尽早实现目标,整个姿态必须如此。 拖拉不受影响,因为它已经 总是靠自己来控制自己 自己在某一点上着陆.截图:每逢旋转木马休息时 怎么样 它到达那里 不同程度的 引擎, 和非常长的放出 仍然可能显示接合。 如果你在任何情况下都需要精确的,请离开
loop关闭.
自动播放
autoplay 自己卷起旋转木马 过 true 用于默认,或用于配置它的对象.
<Carousel.Root autoplay />
<Carousel.Root autoplay={{ mode: "continuous", speed: 90 }} />
<Carousel.Root autoplay={{ mode: "page", interval: 5000 }} />
<Carousel.Root autoplay={{ mode: "continuous", atEnd: "reverse", pauseAtEnd: 1500 }} />
<Carousel.Root autoplay={{ mode: "item", pauseOnInteraction: 5000 }} />
缠绕并聚焦描述鼠标和键盘. 触摸也没有,所以 pauseOnInteraction 何等为止
旋转木马从电话里读到的东西拿走了 卷起或拖住它,等待开始
一旦旋转木马休息了: 动力、快感和循环本身的改正都算数,所以它运行
从旋转木马的位置 而不是从手离开的时候开始.
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
mode | "item" | "page" | "viewport" | "continuous" | "item" | 每一步走多远,前出后出的三个按钮相同(见 动作有多快),加 (中文(简体) ) continuous,它稳步地滚动,而不停止项目. |
direction | "forwards" | "backwards" | "forwards" | 何处去. |
interval | number | 3000 | 台阶之间的毫秒. item 财务报告和审定财务报表 page 只有这个. |
speed | number | 60 | 以像素为每秒. continuous 只有这个. |
atEnd | "rewind" | "reverse" | "stop" | "rewind" | 内容耗尽后怎么办:回到它从头开始的终点,转身回放,或者停止. 不可用字词 loop。 。 。 . |
pauseAtEnd | number | 0 | 在每一端都坐着的米秒 atEnd 接管权. continuous 只有,没有字面 loop。 。 。 . |
pauseOnHover | boolean | true | 在指针在旋转木马上时暂停. |
pauseOnFocus | boolean | true | 在焦点位于旋转木马内部任何地方时暂停,包括物品. |
pauseOnInteraction | number | false | 1500 | 等待卷轴或拖曳的米秒已解决后再接起 . false 随你怎么说. |
不适用于给定配置的选项是编译出错而不是静静无所事事的设置,
而类型带有: 徘徊 atEnd 在旋转木马上说它不适用 因为循环
旋转木马从不耗尽内容. 混合起来 speed 财务报告和审定财务报表 interval 把这个解释放在错误本身.
超越 pauseOnHover 财务报告和审定财务报表 pauseOnFocus,自动播放也会在拖动时自行离开,而a
车轮手势的动力仍在运行,而标签则被隐藏. 当用户要求时它根本不运行
prefers-reduced-motion: reduce并且它能活捉改变 见 减少动议。 。 。 .
减少动议
旋转木马在屏幕的侧面 扫荡了一部分 prefers-reduced-motion: reduce
所以木马在自行移动的两地默认尊重它:
- 自动播放不运行 . 不只是暂停: 暂停的自动播放仍然是当 指针叶. 偏好是现场阅读,所以在会中打开它 停止旋转木马的位置.
- 动画的卷轴马上到. 前一和后一,对一个关闭屏幕的项目,倒带在
自动播放的结尾,当一个环形包装扰动了浏览器时,将旋转木马的快取完成. 这个
目的地是人们要求的,旅程是装饰
behavior: "smooth"时间没有缩短, 所以,即刻是这里唯一"少"的意思.
拖拽不动,由此而来的势头也是如此。 这个运动是用户自己的手,停止 手指下被活活活活活活活活活活的木马 控制力比运动力低 橡皮筋也一样 和循环,其副本是结构而不是移动,其电信端口是看不见的 建筑业.
过 reducedMotion="ignore" 选择退出它的所有, 对于一个已经做出这个决定的应用程序 在别的地方.
根上的数据属性集
| 属性 | 数值 | 说明 |
|---|---|---|
data-carousel-autoplay | "playing" | "paused" | 仅在 autoplay 正在运行,所以它双倍地作为样式或断言当前自动播放状态的方法. |
Carousel.Viewport
可滚动容器。 处理指针/拖动器、动力、橡胶带、卷轴抽取和键盘聚焦
卷行会. 显示 a <div> 与 overflow: scroll 和隐藏的滚动条.
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
scrollSnapType | CSSProperties["scrollSnapType"] | 无 | 支助科 scroll-snap-type 适用于容器的值(例如). "x mandatory") (中文(简体) ). Snaping与动力动画相协调,所以旋转木马总是会降落在快取点上. |
contentFade | boolean | true | 何时 true,将遮罩-图像淡出应用到景点的两边. 只有在有可滚动的内容时才会出现这种淡出. |
contentFadeSize | string | number | "clamp(16px, 10vw, 64px)" | 内容的宽度已淡出. 接受任何 CSS 长度字符串或一个 number (译为: px) (中文(简体) ). 只在 contentFade 实值 true (或省略). |
ref | Ref<HTMLDivElement> | 无 | 转发到取景口 <div>。 。 。 . |
...props | ComponentPropsWithoutRef<"div"> | 无 | 所有标准 <div> 道具来. 事件处理器 onPointerDown, (中文(简体) ), onPointerMove, (中文(简体) ), onPointerUp, (中文(简体) ), onClickCapture,以及 onWheel 与内部管理人员合并. |
视图端口上的数据属性集
| 属性 | 数值 | 说明 |
|---|---|---|
data-carousel-viewport | "" | 总是在场。 内部用于边界抵消计算. |
data-can-scroll | "forwards" | "backwards" | "both" | "none" | 反映当前可滚动性。 用于带有 CSS 属性选择器的样式按钮或指示器. |
Carousel.Content
薄薄的包装纸 width: fit-content 因此,物品排成一行。 显示 a <div>。 。 。 .
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
ref | Ref<HTMLDivElement> | 无 | 转发到内容 <div>。 。 。 . |
...props | ComponentPropsWithoutRef<"div"> | 无 | 所有标准 <div> 道具来. 样式与 width: fit-content。 。 。 . |
Carousel.Item
单自旋滑行. 默认生成 <div> 与 will-change: transform (橡胶带需要)
动画). 使用 asChild 合并到您的元素中.
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
asChild | boolean | false | 何时 true,合并所有道具(包括 data-carousel-item 财务报告和审定财务报表 style单子元素通过 cloneElement 而不是渲染包装 <div>。孩子必须是单一有效的反应要素. |
ref | Ref<HTMLElement> | 无 | 前任裁判 何时 asChild 实值 true,转至儿童部分. |
...props | ComponentPropsWithoutRef<"div"> | 无 | 所有标准 <div> 道具来. style 与 will-change: transform。 。 。 . |
Carousel.NextPage
旋转木马向前滚动的按钮 。 到底有多远 mode自动禁用
内容可以向前滚动。 显示 a <button>。 。 。 .
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
mode | "page" | "item" | "viewport" | "page" | 点击多远。 见 动作有多快。 。 。 . |
disabled | boolean | !scrollsForwards | 覆盖自动禁用状态。 过 false 无论滚动位置如何,总是保留按钮. |
onClick | MouseEventHandler<HTMLButtonElement> | 无 | 在滚动动作被触发后调用 . |
ref | Ref<HTMLButtonElement> | 无 | 已转交 <button>。 。 。 . |
...props | ComponentPropsWithoutRef<"button"> | 无 | 所有标准 <button> 道具来. |
动作有多快
mode 按钮和按钮上的答案是相同的 autoplay因此,一个旋转木马的自动播放步骤
的按钮.
| 模式 | 一个动作会怎样 |
|---|---|
"page" | 将下一个未完全视图的项目带入到全视图中。 缺省, 以及是什么使部分可见的物品 不被部分看见. |
"item" | 对下一个项目采取的步骤,不论是否完全考虑到目前的项目。 一个实际上已经到达的东西 被传递给它背后的一个. |
"viewport" | 移动精确的视图端口可以显示什么,而忽略了项目掉落的地方. 随便啦 scroll-snap-type 等它落地后,你要求继续适用. |
三个尊重 boundaryOffset,所以内容后面没有东西会淡出,所有三个动画,除非用户有
请求 减少动议。 。 。 .
<Carousel.NextPage mode="item">next</Carousel.NextPage>
<Carousel.Root autoplay={{ mode: "item", interval: 4000 }} />
Carousel.PrevPage
向后滚动旋转木马的按钮,直到 mode 说 当旋转木马在
开始 显示 a <button>。 。 。 .
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
mode | "page" | "item" | "viewport" | "page" | 点击多远。 见 动作有多快。 。 。 . |
disabled | boolean | !scrollsBackwards | 覆盖自动禁用状态. |
onClick | MouseEventHandler<HTMLButtonElement> | 无 | 在滚动动作被触发后调用 . |
ref | Ref<HTMLButtonElement> | 无 | 已转交 <button>。 。 。 . |
...props | ComponentPropsWithoutRef<"button"> | 无 | 所有标准 <button> 道具来. |
Carousel.useCarouselContext
提供进入旋转木马内部状态和动作的钩子. 必须在里面使用 Carousel.Root。 。 。 .
const {
scrollsForwards,
scrollsBackwards,
handleScrollToNext,
handleScrollToPrev,
scrollIntoView,
remainingForwards,
remainingBackwards,
clearAnimation,
} = Carousel.useCarouselContext();
| 财产 | 类型 | 说明 |
|---|---|---|
scrollsForwards | boolean | true 当旋转木马的前面有可滚动的内容的时候. |
scrollsBackwards | boolean | true 当旋转木马的尾部有可滚动的内容的时候. |
remainingForwards | React.RefObject<number> | 包含剩余向上滚动的像素数量的参考文件。 每一次滚动事件更新. |
remainingBackwards | React.RefObject<number> | 包含剩余向后滚动的像素数的 Ref . |
handleScrollToNext() | () => void | 程序上滚动到下个项目/页面,与点击相同 Carousel.NextPage。 。 。 . |
handleScrollToPrev() | () => void | 程序上滚动到上个项目/页,与点击相同 Carousel.PrevPage。 。 。 . |
scrollIntoView(target, container, direction) | (target: HTMLElement, container: HTMLElement, direction: "forwards" | "backwards" | "nearest") => void | 滚动 target 内部的观察 container。 。 。 . "nearest" 滚动所需最低数额; "forwards" 编号 : "backwards" 将项目调整到前端或后端边缘,同时尊重 scroll-snap-align: center。 。 。 . |
clearAnimation() | () => void | 取消任何在建动力动画. |
CSS 自定义属性
以下 CSS 自定义属性被设置在根元素上,可用于自定义样式.
| 财产 | 说明 |
|---|---|
--carousel-fade-size | 当前已解析的淡出大小 contentFadeSize。 。 。 . |
--carousel-remaining-forwards | 剩余像素可以向前滚动(例如. 312px) (中文(简体) ). 每一次滚动事件更新. |
--carousel-remaining-backwards | 剩余像素向后滚动 . |
--carousel-fade-offset-forwards | 在前缘被淡出相抵消(内部被口罩梯度所使用). |
--carousel-fade-offset-backwards | 向后边缘折射. |
--carousel-scroll-margin-inline | 旋转木马项目的内置滚动边距 |
公用事业
Carousel.defaultBoundaryOffset
默认 boundaryOffset 使用的函数 Carousel.Root阅读 --carousel-fade-size 从视图元素
返回时 { x: fadeSize, y: 0 } 这样,下一次/预览导航就不会在内容后滚动项目。 导出
用于构建自定义 boundaryOffset 在默认行为之上.
type DefaultBoundaryOffset = (root: HTMLElement) => { x: number; y: number };
Carousel.CSS_VARS
包含内部使用的所有 CSS 自定义属性名称的被冻结对象, 用于读取或设置 没有硬编码字符串.
Carousel.CSS_VARS.fadeSize; // "--carousel-fade-size"
Carousel.CSS_VARS.remainingForwards; // "--carousel-remaining-forwards"
Carousel.CSS_VARS.remainingBackwards; // "--carousel-remaining-backwards"
Carousel.CSS_VARS.fadeOffsetForwards; // "--carousel-fade-offset-forwards"
Carousel.CSS_VARS.fadeOffsetBackwards; // "--carousel-fade-offset-backwards"
Carousel.CSS_VARS.overscrollTranslateX; // "--carousel-overscroll-translate-x"
Carousel.CSS_VARS.scrollMarginInline; // "--carousel-scroll-margin-inline"
类型
每一种公共类型都会导出两次, 在同一定义下, 所以选择哪个字读得更好。 平面名称 输出 :
import type {
CarouselAutoplayOptions,
CarouselRootProps,
} from "@daformat/react-headless-carousel";
或分组于 Carousel 对象,其所属组件旁边:
import { Carousel } from "@daformat/react-headless-carousel";
const [mode, setMode] = useState<Carousel.AutoplayMode>("item");
| 平面名称 | 打开 Carousel | 说明 |
|---|---|---|
CarouselRootProps<Loop> | Carousel.RootProps<Loop> | 主张 Carousel.Root。 。 。 . Loop 沿着 loop 道具和决定哪些自动播放选项随它而来,见下文. |
CarouselViewportProps | Carousel.ViewportProps | 主张 Carousel.Viewport。 。 。 . |
CarouselContentProps | Carousel.ContentProps | 主张 Carousel.Content。 。 。 . |
CarouselItemProps | Carousel.ItemProps | 主张 Carousel.Item。 。 。 . |
CarouselNextPageProps | Carousel.NextPageProps | 主张 Carousel.NextPage。 。 。 . |
CarouselPrevPageProps | Carousel.PrevPageProps | 主张 Carousel.PrevPage。 。 。 . |
CarouselAutoplayOptions<CanEnd> | Carousel.AutoplayOptions<CanEnd> | 对象形式 autoplay 道具 (英语). 见附注 CanEnd 见下文. |
CarouselAutoplayMode | Carousel.AutoplayMode | CarouselScrollMode | "continuous"。 。 。 . |
CarouselAutoplayStepMode | Carousel.AutoplayStepMode | 台阶模式,需要 interval。与 CarouselScrollMode。 。 。 . |
CarouselScrollMode | Carousel.ScrollMode | 预告/下一步的动作有多远: "page" | "item" | "viewport"。 。 。 . |
CarouselAutoplayDirection | Carousel.AutoplayDirection | "forwards" | "backwards"。 。 。 . |
CarouselAutoplayAtEnd | Carousel.AutoplayAtEnd | "rewind" | "reverse" | "stop"。 。 。 . |
CarouselBoundaryOffset | Carousel.BoundaryOffset | 这个 boundaryOffset 道具:一个点,或函数返回一个. |
CarouselReducedMotion | Carousel.ReducedMotion | 这个 reducedMotion 道具 : "respect" | "ignore"。 。 。 . |
CarouselContext | Carousel.Context | 返回的值 Carousel.useCarouselContext。 。 。 . |
两者 RootProps 财务报告和审定财务报表 AutoplayOptions 使用关于循环的布尔类型参数, 和相反的两个默认值
故意的指令,在您给自己起名之前,应该先知道:
| 写入为 | 参数为 | 哪些自动播放选项 |
|---|---|---|
<Carousel.Root> 没有道具 | false | 因为旋转木马可以到达终点 |
CarouselRootProps | boolean | 两个形状,一个 loop 只在运行时知道 |
CarouselAutoplayOptions | false | 没有结束选项, 对于旋转的旋转木马 |
这么说吧 Carousel.Root 自己给你 atEnd,同时赤裸裸 CarouselRootProps 描述可能或可能
不是循环,是赤裸的 CarouselAutoplayOptions 是三个中最窄的.
AutoplayOptions 编辑 CanEnd 参数
AutoplayOptions 使用布尔类型参数来表示旋转木马是否是可以耗尽内容的。 A 类
旋转木马从未到尽头 所以 atEnd 财务报告和审定财务报表 pauseAtEnd 只有当 CanEnd 实值 true。 。 。 .
写道具内线不需要这些 因为 Carousel.Root 选择正确的一个从 loop只有当你
分别声明选项 :
// the bare form is the narrow one: no end options, for a carousel that loops
const looping: CarouselAutoplayOptions = { mode: "item", interval: 2000 };
// a carousel that does not loop can reach an end, so pass true to get at them
const finite: CarouselAutoplayOptions<true> = {
mode: "continuous",
speed: 60,
pauseAtEnd: 1000,
atEnd: "reverse",
};
请注意: CanEnd 默认为 false 时 loop 默认为 false 也一样,所以一个可变的键入为赤色
CarouselAutoplayOptions 以木马盟誓 atEnd 这是
权利。 默认故意是限制性的 <true> 任何时候 loop 关闭.
何时 loop 只有运行时才知道,通过 boolean 并同时获得两种形状. 这就是包装组件
想要: 它需要一个 loop 把它交给 Carousel.Root 与自动播放选项并列,无需
拆分成环形树枝和无螺纹树枝,或伸展到铸件:
const Gallery = ({
loop,
autoplay,
}: {
loop: boolean;
autoplay?: boolean | CarouselAutoplayOptions<boolean>;
}) => (
<Carousel.Root loop={loop} autoplay={autoplay}>
...
</Carousel.Root>
);
无法使用的选项被打成无法使用的原因, 因此编译器引用它时会重击您 表示“ 无法指定“ 未定义” :
<Carousel.Root loop autoplay={{ mode: "item", atEnd: "rewind" }} />
// ^ Type '"rewind"' is not assignable to type
// '"`atEnd` does not apply with loop: a looping
// carousel never runs out of content"'
同样的把戏 speed 在阶梯模式下, interval 连续的,和 pauseAtEnd 外部
mode: "continuous"。 。 。 .
这个裁决需要知道旋转木马环是否存在,所以它只适用于 loop 是一个字面意思。 鉴于a loop 那个
在运行时解决, atEnd 财务报告和审定财务报表 pauseAtEnd 保持可用性:他们做他们的工作 跑出来的非洗手,
并坐以待毙.