跳转到内容

Approval 审批 alpha

危险操作执行前的人工闸门:批准或拒绝,超时按拒绝处理,可附带勾选式的授权范围。

用法

勾选与判定是原子的:批准的载荷带着批准的项,不存在已批准但范围尚未同步的窗口

要动你的工作区

它想读一遍 src/ 并写回改动。

读取 src/ 下的文件
写回改动
Waiting for your decision

组件结构

加粗的是必需部件。

data-scope="approval"root · title · description · live-region · group · item · item-indicator · item-text · note · timer · result · footer · approve-trigger · deny-trigger

示例

超时按拒绝收口

默认不提供超时值:替宿主制定安全策略比不制定更危险。到期落为拒绝,expired 只是显示态

要执行一条删除命令

没人答的话,到点按拒绝处理。

附加备注

备注与勾选同批取快照,随判定载荷一起发出;留空时不带该字段,它不参与必选项是否勾满的判断

要把这批改动推上去

推之前可以留一句话,随判定一起交给宿主。

形态与尺寸

variant 改变该闸门与正文分开的方式,size 改变标题、条目与按钮的几何档;判定链不变

描边(缺省)

写回改动

弱底分区

写回改动

无壳内联

写回改动

小档

写回改动

大档

写回改动

设计指引

何时使用

  • Agent 执行写文件、发请求、付费等实际操作前需要用户确认。
  • 授权带范围:批准的同时需要说明批准了哪些项。

何时不用

  • 只需要一句确认时,使用弹出确认
  • 判定结果不影响任何执行时,它不是闸门,应使用提示。

特性

  • 超时一律按拒绝处理,由状态机结构保证,不依赖调用方遵守约定:判定的取值只有批准与拒绝,expired 只是显示状态;通往批准的转移只有一条;到期事件只在待决状态有转移,迟到的定时事件静默丢弃。
  • 不提供默认超时值,由宿主决定安全策略。时长非有限数或非正数时不启动计时器,停留在待决状态;既不按 0ms 立即到期,也不视为无限期放行。
  • 拒绝路径始终可达:状态机层的拒绝不受必选项和任何闸门限制,超时、卸载兜底与宿主的 deny() 入口都能落地。拒绝按钮与 Escape 另有一道挂起闸门:判定在途时与批准按钮一起锁定,避免等待宿主响应期间产生第二条判定。
  • 勾选与判定是原子的:批准的载荷携带已勾选的授权项,不存在已批准但范围未同步的窗口。
  • 备注(note)与勾选同批快照,随判定载荷一起发出;为空时不携带该字段。备注不参与必选项是否勾满的判断。
  • requestId 变化即重新进入待决并按新时长重启计时;不为上一轮补发拒绝,旧结果由宿主自行作废。重入时勾选与备注回到各自默认值。
  • 判定落定后 result 部件才显示,语气随判定变化:批准取成功档,拒绝与超时取危险档。它对读屏隐藏,同一句话由播报区读出一次。
  • 两个按钮位于 actions 行内,间距与对齐由库统一处理,使用者不需要另写容器。

组合

  • 放入工具调用approval 部件位:该位置常驻于开关与详情之间,不会被折叠隐藏。
  • 需要弹窗时每个闸门一个对话框role="alertdialog"、关闭 closeOnEscape,并把 initialFocus 设为本组件导出的 APPROVAL_DENY_SELECTOR。浮层只保留批准与拒绝两个出口,Escape 仍冒泡到闸门并判为拒绝。
  • 剩余时间的显示交给计时器,判定权仍由本组件持有。不要把倒计时直接渲染为 timer 节点:两套解剖打在同一节点上会互相覆盖,应让 timer 作为外层容器。
  • 需要连续询问多件事时,使用步骤条走马灯串联多个闸门。本组件是单发闸门,data-state 的四个值互斥,不表达序号。
  • 需要提供“稍后再说”入口时,该入口由宿主实现,不属于闸门。常见做法是在 onDecision 之外另留延后路径,或按上一条把闸门放进对话框;浮层内仍只有批准与拒绝两个出口。

最佳实践

  • 判定落定后两个按钮都会禁用,浮层不再有出口,宿主必须在判定回调中关闭浮层。
  • 卸载即拒绝(denyOnUnmount)默认关闭。启用前确认列表换 key、路由切换、热更新等任何一次重新挂载都会替用户发出判定。

反模式

  • 把超时做成到点自动放行。
  • 用可关闭的浮层承载闸门:关闭窗口既不是批准也不是拒绝,闸门会悬空。

API 参考

产物

自定义元素<xh-approval>
Vue 组件XhApprovalApproveTrigger XhApprovalDenyTrigger XhApprovalDescription XhApprovalFooter XhApprovalGroup XhApprovalItem XhApprovalItemIndicator XhApprovalItemText XhApprovalLiveRegion XhApprovalNote XhApprovalResult XhApprovalRoot XhApprovalTimer XhApprovalTitle
组合式函数useApproval
状态机approvalMachine
皮肤@xihan-ui/styles/approval.css

Props

属性类型必填说明
requestIdstring本轮请求的身份。变化即重新进入待决,并按新时长重新计时。
statusApprovalStatus提供即受控。
defaultStatusApprovalStatus
timeoutMsnumber超时无人应答时按拒绝收口。默认不提供默认值:替宿主决定安全策略比不决定更危险。 非有限值或非正数同样不启动计时器,既不按 0ms 立即到期,也不视为无限期放行。
scopesreadonly ApprovalScope[]
grantedScopesreadonly string[]
defaultGrantedScopesreadonly string[]
notestring附在判定上的一段自由文本。提供即受控。 它只随判定载荷发出,不参与必选项是否全部勾选的判断。
defaultNotestring
loadingboolean判定在途:只阻止重复批准,不阻止拒绝。
denyOnEscapebooleanEscape 判为拒绝,默认开启。
denyOnUnmountboolean卸载时若仍待决则按拒绝派发一次,默认关闭。 机制成立不等于默认值成立:列表更换 key、路由切换、热更新的任何一次重挂, 都会替用户发出未做过的判定。
live'polite' | 'assertive'播报档位,默认 polite。
variantControlVariant形态:outline 描边、subtle 底色分区、ghost 无壳内联。默认 outline。
toneTone
sizeSize
translationsPartial<ApprovalTranslations>
onDecision(details: ApprovalDecisionDetails) => void
onGrantedScopesChange(details: ApprovalScopesChangeDetails) => void
onNoteChange(details: ApprovalNoteChangeDetails) => void

事件

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
decisionApprovalDecisionDetails判定落定;detail 为 { requestId, decision, source, scopes }
granted-scopes-changeApprovalScopesChangeDetails勾选的授权项变化;detail 为 { value: string[] }
note-changeApprovalNoteChangeDetails备注变化;detail 为 { value: string }

插槽

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhApprovalItemdefaultApprovalScopeSlotProps
XhApprovalRootdefaultApprovalRootSlotProps

状态

公开状态写入 data-state

部件取值
root'pending' | 'approved' | 'denied' | 'expired'
item'checked' | 'unchecked'
item-indicator'checked' | 'unchecked'
note'pending' | 'approved' | 'denied' | 'expired'
timer'pending' | 'approved' | 'denied' | 'expired'
result'pending' | 'approved' | 'denied' | 'expired'
approve-trigger'pending' | 'approved' | 'denied' | 'expired'
deny-trigger'pending' | 'approved' | 'denied' | 'expired'

以下名称仅用于内部状态机。

状态pending · approved · denied · expired

事件APPROVE · DENY · SCOPE.TOGGLE · SCOPE.SET · NOTE.SET · after.timeout · CONTROLLED.PENDING · CONTROLLED.APPROVE · CONTROLLED.DENY · CONTROLLED.EXPIRE · REQUEST.RESET · PRESS.START · PRESS.END

判据isStatusControlled · canApprove · isEditable · canApproveControlled · canPress

connect API

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
statusApprovalStatus
settledboolean已判定:两个按钮都收起出口。
loadingboolean
grantedScopesstring[]
notestring备注中的文字;未填写时为空串。
canApproveboolean必选项是否全部勾选。
announcementstring按 status 选出的播报文本;关闭 announce 时作者不渲染该部件即可。
approve() => void
deny() => void
setGrantedScopes(next: string[]) => void
setNote(next: string) => void
isScopeGranted(value: string) => boolean
getRootProps() => T['element']
getTitleProps() => T['element']
getDescriptionProps() => T['element']
getLiveRegionProps() => T['element']
getGroupProps() => T['element']
getItemProps(scope: ApprovalScope) => T['element']
getItemIndicatorProps(scope: ApprovalScope) => T['element']
getItemTextProps(scope: ApprovalScope) => T['element']
getNoteProps() => T['input']
getTimerProps() => T['element']
getResultProps() => T['element']
getFooterProps() => T['element']
getApproveTriggerProps() => T['button']
getDenyTriggerProps() => T['button']

无障碍

键盘

规格出处:W3C APG

按键生效条件行为
Enter / Space焦点在批准按钮上,待决、必选项已勾满、且不在挂起中判为批准,载荷带上已勾选的授权项
Enter / Space焦点在拒绝按钮上,待决且不在挂起中判为拒绝
Space焦点在授权项上,待决且该项未禁用勾选或取消该项。Enter 刻意不参与,与原生复选框一致
Enter / Space按住批准或拒绝按钮,待决且不在挂起中;批准还要必选项已勾满按住期间该钮投影 data-pressed,与指针 :active 同一副按压面(text 档定尺按钮,按下缩放并换底);抬起、失焦、判定落定或转入挂起撤下
Space按住授权项,待决、不在挂起中且该项未禁用按住期间该行投影 data-pressed,与指针 :active 同一副按压面(row 档只换面不缩放);抬起或失焦撤下。Enter 不是复选框的激活键,不进按压面
Escape焦点在闸门内,待决、未挂起、且开启 denyOnEscape判为拒绝。它不是关闭:本组件不提供不作答的出口

ARIA

以下属性由 connect 生成。

部件属性
rootaria-describedbydescription 部件的 id
rootaria-labelledbytitle 部件的 id
rootrole'group'
live-regionaria-atomic'true'
live-regionaria-liveprops.live
grouparia-labeltranslations?.scopes
grouprole'group'
itemaria-checked'true' | 'false'
itemaria-disabled'true' | 'false'
itemaria-required'true' | 'false'
itemrole'checkbox'
item-indicatoraria-hidden'true'
notearia-labeltranslations?.note
timeraria-hidden'true'
resultaria-hidden'true'
approve-triggeraria-busy'true' | undefined
approve-triggeraria-disabled'true' | 'false'
approve-triggeraria-labeltranslations?.approve
deny-triggeraria-busy'true' | undefined
deny-triggeraria-disabled'true' | 'false'
deny-triggeraria-labeltranslations?.deny
  • 闸门是 role=group,由标题命名、由说明描述。
  • 待决时批准键使用 aria-disabled 而不是原生 disabled:保持可聚焦,读屏可以读出不可用的原因。
  • 授权项是 role=checkbox,各占一个 Tab 停靠点,只响应 Space,与原生复选框一致。
  • 剩余时间与结果条都对读屏隐藏:逐秒变化的数字进入活动区域会持续打断,判定结果与截止事件由播报区各读出一次。
  • 备注取 translations.note 作为可访问名称(默认 Note),占位文字取 translations.notePlaceholder

样式参考

皮肤

@xihan-ui/styles/approval.css 使用 [data-scope="approval"][data-part="root"] 部件选择器,位于 xihan.componentsxihan.motion 层。覆盖样式使用 xihan.overrides

数据属性

connect 生成;条件不成立时不输出无值属性。

部件属性
rootdata-loading''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-state'pending' | 'approved' | 'denied' | 'expired'
rootdata-toneprops.tone
rootdata-variantprops.variant
itemdata-disabled''(条件成立时才出现)
itemdata-pressed''(条件成立时才出现)
itemdata-state'checked' | 'unchecked'
itemdata-valueitem.value
itemdata-xh-action-control''
itemdata-xh-action-display'always'
itemdata-xh-action-profile'row'
itemdata-xh-action-sizeprops.size
itemdata-xh-action-variant'ghost'
item-indicatordata-state'checked' | 'unchecked'
item-textdata-valueitem.value
notedata-state'pending' | 'approved' | 'denied' | 'expired'
timerdata-state'pending' | 'approved' | 'denied' | 'expired'
resultdata-state'pending' | 'approved' | 'denied' | 'expired'
approve-triggerdata-disabled''(条件成立时才出现)
approve-triggerdata-loading''(条件成立时才出现)
approve-triggerdata-pressed''(条件成立时才出现)
approve-triggerdata-state'pending' | 'approved' | 'denied' | 'expired'
approve-triggerdata-toneprops.tone
approve-triggerdata-xh-action-control''
approve-triggerdata-xh-action-display'always'
approve-triggerdata-xh-action-profile'text'
approve-triggerdata-xh-action-sizeprops.size
approve-triggerdata-xh-action-variant'solid'
deny-triggerdata-disabled''(条件成立时才出现)
deny-triggerdata-loading''(条件成立时才出现)
deny-triggerdata-pressed''(条件成立时才出现)
deny-triggerdata-state'pending' | 'approved' | 'denied' | 'expired'
deny-triggerdata-xh-action-control''
deny-triggerdata-xh-action-display'always'
deny-triggerdata-xh-action-profile'text'
deny-triggerdata-xh-action-sizeprops.size
deny-triggerdata-xh-action-variant'outline'

CSS 变量

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-approval-action-font-sizeapprove-trigger
deny-trigger
footer
root
font-sizedefault
loading
--xh-text-label-sizeapproval 的 approve-trigger、deny-trigger、footer、root 部件 font-size 覆盖槽。
--xh-approval-action-font-weightapprove-trigger
deny-trigger
font-weightdefault--xh-text-label-weightapproval 的 approve-trigger、deny-trigger 部件 font-weight 覆盖槽。
--xh-approval-action-happrove-trigger
deny-trigger
block-size
min-block-size
default
xh-action-profile=row
--xh-_approval-action-happroval 的 approve-trigger、deny-trigger 部件 block-size、min-block-size 覆盖槽。
--xh-approval-action-pxapprove-trigger
deny-trigger
padding-inlinedefault--xh-_approval-action-pxapproval 的 approve-trigger、deny-trigger 部件 padding-inline 覆盖槽。
--xh-approval-action-radiusapprove-trigger
deny-trigger
border-radiusdefault--xh-shape-controlapproval 的 approve-trigger、deny-trigger 部件 border-radius 覆盖槽。
--xh-approval-approve-bgapprove-triggerbackground-colordefault
loading
--xh-_action-variant-bg-loading
--xh-_action-variant-bg-rest
approval 的 approve-trigger 部件 background-color 覆盖槽。
--xh-approval-approve-bg-hoverapprove-triggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverapproval 的 approve-trigger 部件 background-color 覆盖槽。
--xh-approval-approve-bg-offapprove-triggerbackground-colordisabled--xh-_action-variant-bg-disabledapproval 的 approve-trigger 部件 background-color 覆盖槽。
--xh-approval-approve-fgapprove-triggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-loading
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
approval 的 approve-trigger 部件 color 覆盖槽。
--xh-approval-approve-shadowapprove-triggerbox-shadowdefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_highlight-toneapproval 的 approve-trigger 部件 box-shadow 覆盖槽。
--xh-approval-bgrootbackgrounddefault
variant=subtle
--xh-bg-subtle
--xh-bg-surface
approval 的 root 部件 background 覆盖槽。
--xh-approval-borderrootborder
border-color
default
tone
--xh-_tone
--xh-border-default
approval 的 root 部件 border、border-color 覆盖槽。
--xh-approval-border-settledrootborder-colornot([data-state='pending'])
state=pending
--xh-border-defaultapproval 的 root 部件 border-color 覆盖槽。
--xh-approval-deny-bgdeny-triggerbackground-colordefault--xh-_action-variant-bg-restapproval 的 deny-trigger 部件 background-color 覆盖槽。
--xh-approval-deny-bg-hoverdeny-triggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverapproval 的 deny-trigger 部件 background-color 覆盖槽。
--xh-approval-deny-bg-offdeny-triggerbackground-colordisabled--xh-_action-variant-bg-disabledapproval 的 deny-trigger 部件 background-color 覆盖槽。
--xh-approval-deny-borderdeny-triggerborderdefault--xh-_action-variant-border-restapproval 的 deny-trigger 部件 border 覆盖槽。
--xh-approval-deny-border-offdeny-triggerborder-colordisabled--xh-_action-variant-border-disabledapproval 的 deny-trigger 部件 border-color 覆盖槽。
--xh-approval-deny-fgdeny-triggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
approval 的 deny-trigger 部件 color 覆盖槽。
--xh-approval-description-fgdescriptioncolordefault--xh-fg-mutedapproval 的 description 部件 color 覆盖槽。
--xh-approval-description-font-sizedescriptionfont-sizedefault--xh-text-secondary-sizeapproval 的 description 部件 font-size 覆盖槽。
--xh-approval-footer-gapfootergapdefault--xh-space-2approval 的 footer 部件 gap 覆盖槽。
--xh-approval-gaprootgapdefault--xh-_approval-gapapproval 的 root 部件 gap 覆盖槽。
--xh-approval-group-gapgroupgapdefault--xh-space-1approval 的 group 部件 gap 覆盖槽。
--xh-approval-icon-sizeroot--xh-icon-sizedefault--xh-_approval-icon-sizeapproval 的 root 部件 --xh-icon-size 覆盖槽。
--xh-approval-indicator-bg-checkeditem-indicatorbackgroundstate=checked--xh-bg-brandapproval 的 item-indicator 部件 background 覆盖槽。
--xh-approval-indicator-borderitem-indicatorborderdefault--xh-border-controlapproval 的 item-indicator 部件 border 覆盖槽。
--xh-approval-indicator-border-checkeditem-indicatorborder-colorstate=checked--xh-bg-brandapproval 的 item-indicator 部件 border-color 覆盖槽。
--xh-approval-indicator-fgitem-indicatorcolordefault--xh-fg-on-brandapproval 的 item-indicator 部件 color 覆盖槽。
--xh-approval-indicator-icon-sizeitem-indicator--xh-icon-sizedefault--xh-_approval-indicator-glyphapproval 的 item-indicator 部件 --xh-icon-size 覆盖槽。
--xh-approval-indicator-radiusitem-indicatorborder-radiusdefault--xh-shape-insetapproval 的 item-indicator 部件 border-radius 覆盖槽。
--xh-approval-indicator-sizeitem-indicator--xh-icon-size
block-size
inline-size
default--xh-control-indicator-sizeapproval 的 item-indicator 部件 --xh-icon-size、block-size、inline-size 覆盖槽。
--xh-approval-item-bg-hoveritembackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverapproval 的 item 部件 background-color 覆盖槽。
--xh-approval-item-font-sizeitemfont-sizedefault--xh-_approval-item-font-sizeapproval 的 item 部件 font-size 覆盖槽。
--xh-approval-item-gapitemgapdefault--xh-space-1_5approval 的 item 部件 gap 覆盖槽。
--xh-approval-item-pxitempadding-inlinedefault--xh-space-2approval 的 item 部件 padding-inline 覆盖槽。
--xh-approval-item-pyitempadding-blockxh-action-profile=row--xh-space-1approval 的 item 部件 padding-block 覆盖槽。
--xh-approval-item-radiusitemborder-radiusdefault--xh-_action-profile-radiusapproval 的 item 部件 border-radius 覆盖槽。
--xh-approval-item-text-fgitem-textcolordefault--xh-fg-mutedapproval 的 item-text 部件 color 覆盖槽。
--xh-approval-item-text-fg-checkeditem
item-text
colorstate=checked--xh-fg-defaultapproval 的 item、item-text 部件 color 覆盖槽。
--xh-approval-loading-durationfooter
root
animationloading--xh-spin-durationapproval 的 footer、root 部件 animation 覆盖槽。
--xh-approval-note-bgnotebackgrounddefault--xh-bg-surfaceapproval 的 note 部件 background 覆盖槽。
--xh-approval-note-bordernoteborderdefault--xh-border-controlapproval 的 note 部件 border 覆盖槽。
--xh-approval-note-fgnotecolordefault--xh-fg-defaultapproval 的 note 部件 color 覆盖槽。
--xh-approval-note-font-sizenotefont-sizedefault--xh-_approval-note-font-sizeapproval 的 note 部件 font-size 覆盖槽。
--xh-approval-note-pxnotepadding-inlinedefault--xh-space-2approval 的 note 部件 padding-inline 覆盖槽。
--xh-approval-note-pynotepadding-blockdefault--xh-space-1_5approval 的 note 部件 padding-block 覆盖槽。
--xh-approval-note-radiusnoteborder-radiusdefault--xh-shape-controlapproval 的 note 部件 border-radius 覆盖槽。
--xh-approval-prootpaddingdefault--xh-_approval-papproval 的 root 部件 padding 覆盖槽。
--xh-approval-radiusrootborder-radiusdefault--xh-shape-surfaceapproval 的 root 部件 border-radius 覆盖槽。
--xh-approval-result-bgresultbackgrounddefault--xh-fg-successapproval 的 result 部件 background 覆盖槽。
--xh-approval-result-bg-deniedresultbackgroundis([data-state='denied'], [data-state='expired'])
state=denied
state=expired
--xh-fg-dangerapproval 的 result 部件 background 覆盖槽。
--xh-approval-result-fgresultcolordefault--xh-fg-successapproval 的 result 部件 color 覆盖槽。
--xh-approval-result-fg-deniedresultcoloris([data-state='denied'], [data-state='expired'])
state=denied
state=expired
--xh-fg-dangerapproval 的 result 部件 color 覆盖槽。
--xh-approval-result-font-sizeresultfont-sizedefault--xh-text-caption-sizeapproval 的 result 部件 font-size 覆盖槽。
--xh-approval-result-font-weightresultfont-weightdefault--xh-text-label-weightapproval 的 result 部件 font-weight 覆盖槽。
--xh-approval-result-gapresultgapdefault--xh-space-1_5approval 的 result 部件 gap 覆盖槽。
--xh-approval-result-pxresultpadding-inlinedefault--xh-space-2approval 的 result 部件 padding-inline 覆盖槽。
--xh-approval-result-pyresultpadding-blockdefault--xh-space-1approval 的 result 部件 padding-block 覆盖槽。
--xh-approval-result-radiusresultborder-radiusdefault--xh-shape-pillapproval 的 result 部件 border-radius 覆盖槽。
--xh-approval-shadowrootbox-shadowdefaultnoneapproval 的 root 部件 box-shadow 覆盖槽。
--xh-approval-timer-fgtimercolordefault--xh-fg-mutedapproval 的 timer 部件 color 覆盖槽。
--xh-approval-timer-font-sizetimerfont-sizedefault--xh-text-caption-sizeapproval 的 timer 部件 font-size 覆盖槽。
--xh-approval-title-fgtitlecolordefault--xh-fg-defaultapproval 的 title 部件 color 覆盖槽。
--xh-approval-title-font-sizetitlefont-sizedefault--xh-text-label-sizeapproval 的 title 部件 font-size 覆盖槽。
--xh-approval-title-font-weighttitlefont-weightdefault--xh-font-weight-semiboldapproval 的 title 部件 font-weight 覆盖槽。

动效

关键帧 xh-approval-in · xh-approval-result-in · xh-approval-rotate 随皮肤自带,不引用别处文件里的名字;background · border-color · colortransition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

prefers-reduced-motion: reduce 下本组件另有降级规则。

RTL

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License