Preview Updated 2026-05-10

BottomSheet 底部弹层

移动端底部弹起的模态面板,支持多停靠点(snap points)、grabber 拖动、下滑关闭、iOS 安全区适配。

English translation pending This page hasn't been translated yet — falling back to Chinese. PRs welcome on GitHub.

基础用法

CfBottomSheet 是移动端原生模式:从屏幕底部弹起的模态面板,圆角朝上、底部贴住视口(iOS 上自动 padding-bottom: env(safe-area-inset-bottom))。顶部默认有 grabber 拖动条,下滑超过 panel 高度 1/3 或快速向下滑动即关闭。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfBottomSheet, CfButton } from '@chufix-design/vue';

const open = ref(false);
</script>
<template>
  <div class="demo-stack">
    <CfButton @click="open = true">打开底部 Sheet</CfButton>
    <CfBottomSheet v-model:open="open" title="选择操作" :snap-points="['40%', '90%']">
      <ul class="demo-list">
        <li>编辑</li>
        <li>分享</li>
        <li>归档</li>
        <li>静音通知</li>
        <li style="color: var(--status-error);">删除</li>
      </ul>
    </CfBottomSheet>
  </div>
</template>
<style scoped>
.demo-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.demo-list li { padding: 12px; background: var(--bg-2); border-radius: var(--r-4); }
</style>
<script setup>
import { ref } from 'vue';
import { CfBottomSheet, CfButton } from '@chufix-design/vue';

const open = ref(false);
</script>
<template>
  <div class="demo-stack">
    <CfButton @click="open = true">打开底部 Sheet</CfButton>
    <CfBottomSheet v-model:open="open" title="选择操作" :snap-points="['40%', '90%']">
      <ul class="demo-list">
        <li>编辑</li>
        <li>分享</li>
        <li>归档</li>
        <li>静音通知</li>
        <li style="color: var(--status-error);">删除</li>
      </ul>
    </CfBottomSheet>
  </div>
</template>
<style scoped>
.demo-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.demo-list li { padding: 12px; background: var(--bg-2); border-radius: var(--r-4); }
</style>
import { useState } from 'react';
import { CfBottomSheet } from '@chufix-design/react';

export default function Demo() {
  const [open, setOpen] = useState(false);
  const [open, setOpen] = useState(false);
  return (
    <>
      <CfBottomSheet open={open} onOpenChange={setOpen} title="选择操作" snapPoints={['40%', '90%']}>
      <ul>
        <li>编辑</li>
        <li>分享</li>
        <li style={{ color: 'var(--status-error)' }}>删除</li>
      </ul>
      </CfBottomSheet>
    </>
  );
}
import { useState } from 'react';
import { CfBottomSheet } from '@chufix-design/react';

export default function Demo() {
  const [open, setOpen] = useState(false);
  const [open, setOpen] = useState(false);
  return (
    <>
      <CfBottomSheet open={open} onOpenChange={setOpen} title="选择操作" snapPoints={['40%', '90%']}>
      <ul>
        <li>编辑</li>
        <li>分享</li>
        <li style={{ color: 'var(--status-error)' }}>删除</li>
      </ul>
      </CfBottomSheet>
    </>
  );
}

多停靠点(snap points)

snapPoints 接受 number(px)/ '40%'(视口高度百分比)/ 'auto'(按内容自适应,最高 90vh)。拖动 grabber 时面板高度跟手移动,释放后吸附到最近的 snap point;拖到最低 snap point 之下 1/2 或快速下拉则关闭。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfBottomSheet, CfButton } from '@chufix-design/vue';

const open = ref(false);
const snap = ref(0);
</script>
<template>
  <div class="demo-stack">
    <CfButton @click="open = true">打开多停靠点 Sheet</CfButton>
    <CfBottomSheet
      v-model:open="open"
      title="详情"
      :snap-points="[180, '50%', '90%']"
      :initial-snap="1"
      @snap-change="snap = $event"
    >
      <p>当前停靠点:<code>{{ snap }}</code> — 拖动顶部 grabber 在三档之间切换。</p>
      <p>支持下拉关闭:拖到最低停靠点以下 1/3 panel 高度,或快速下拉(速度 &gt; 0.5 px/ms)即关闭。</p>
      <p v-for="i in 20" :key="i">演示内容行 #{{ i }}</p>
    </CfBottomSheet>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfBottomSheet, CfButton } from '@chufix-design/vue';

const open = ref(false);
const snap = ref(0);
</script>
<template>
  <div class="demo-stack">
    <CfButton @click="open = true">打开多停靠点 Sheet</CfButton>
    <CfBottomSheet
      v-model:open="open"
      title="详情"
      :snap-points="[180, '50%', '90%']"
      :initial-snap="1"
      @snap-change="snap = $event"
    >
      <p>当前停靠点:<code>{{ snap }}</code> — 拖动顶部 grabber 在三档之间切换。</p>
      <p>支持下拉关闭:拖到最低停靠点以下 1/3 panel 高度,或快速下拉(速度 &gt; 0.5 px/ms)即关闭。</p>
      <p v-for="i in 20" :key="i">演示内容行 #{{ i }}</p>
    </CfBottomSheet>
  </div>
</template>
import { useState } from 'react';
import { CfBottomSheet, CfButton } from '@chufix-design/react';

export default function Demo() {
  const [open, setOpen] = useState(false);
  const [snap, setSnap] = useState(0);
  return (
    <>
      <div className="demo-stack">
          <CfButton onClick={() => setOpen(true)}>打开多停靠点 Sheet</CfButton>
          <CfBottomSheet open={open} onOpenChange={setOpen} title="详情" snapPoints={[180, '50%', '90%']} initialSnap={1} onSnapChange={() => setSnap($event)}
          >
            <p>当前停靠点:<code>{snap}</code> — 拖动顶部 grabber 在三档之间切换。</p>
            <p>支持下拉关闭:拖到最低停靠点以下 1/3 panel 高度,或快速下拉(速度 &gt; 0.5 px/ms)即关闭。</p>
            <p v-for="i in 20" key={i}>演示内容行 #{i}</p>
          </CfBottomSheet>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfBottomSheet, CfButton } from '@chufix-design/react';

export default function Demo() {
  const [open, setOpen] = useState(false);
  const [snap, setSnap] = useState(0);
  return (
    <>
      <div className="demo-stack">
          <CfButton onClick={() => setOpen(true)}>打开多停靠点 Sheet</CfButton>
          <CfBottomSheet open={open} onOpenChange={setOpen} title="详情" snapPoints={[180, '50%', '90%']} initialSnap={1} onSnapChange={() => setSnap($event)}
          >
            <p>当前停靠点:<code>{snap}</code> — 拖动顶部 grabber 在三档之间切换。</p>
            <p>支持下拉关闭:拖到最低停靠点以下 1/3 panel 高度,或快速下拉(速度 &gt; 0.5 px/ms)即关闭。</p>
            <p v-for="i in 20" key={i}>演示内容行 #{i}</p>
          </CfBottomSheet>
        </div>
    </>
  );
}

与 Drawer 的关系

CfDrawer placement="bottom" 是更通用的”贴底抽屉”,可用于桌面端尺寸调整、tone 状态、自定义 footer、resizable 等场景。CfBottomSheet 专为移动端模态体验设计:内置 snap points、grabber、swipe-to-dismiss、safe-area,没有 footer / resize 等桌面端 props。

选哪个场景
CfBottomSheet移动端模态、列表选择、操作面板、半屏详情
CfDrawer placement="bottom"桌面端弹起、可调高度、需要 OK/Cancel footer 时

API

属性类型默认值说明
open / modelValuebooleanfalse开关状态
snapPoints(number | string)[]['40%', '90%']停靠高度数组;数字=px,'N%'=视口高度百分比,'auto'=内容高
initialSnapnumber0初始 snap 索引
showGrabberbooleantrue顶部拖动条
dismissiblebooleantrue拖到最低 snap point 之下时关闭
maskClosablebooleantrue点遮罩关闭
closeOnEscbooleantrueEsc 关闭
maskbooleantrue渲染遮罩
titlestring标题文本
tostring'body'Vue Teleport 目标
containerHTMLElement | nullnullReact portal 容器(默认 body)
zIndexnumbervar(--z-bottomsheet)自定义 z-index

Events

VueReactpayload
update:openonOpenChangeboolean
snap-changeonSnapChangeindex: number
close

反馈与讨论

BottomSheet 底部弹层 · Discussion

0
0 / 600
正在加载评论...