跳转到正文

快速入门

GitHub

你可以使用我们的 AI 辅助设置来安装插件。使用以下命令将 Capgo skills 添加到你的 AI 工具中:

终端窗口
npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins

然后使用以下 prompt:

Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-sheets` plugin in my project.

如果你更想手动设置,请运行以下命令安装插件,并按照下方各平台的说明操作:

  1. 安装软件包

    终端窗口
    bun add @capgo/capacitor-sheets
  2. 注册 Web 组件

    import '@capgo/capacitor-sheets';
  3. 添加安全区域的 viewport 设置

    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
  4. 渲染 Sheet

    <cap-sheet-trigger for="booking-sheet" action="present">Open route</cap-sheet-trigger>
    <cap-sheet id="booking-sheet" detents="18em 32em" content-placement="bottom">
    <cap-sheet-portal>
    <cap-sheet-view>
    <cap-sheet-backdrop></cap-sheet-backdrop>
    <cap-sheet-content class="route-sheet">
    <cap-sheet-bleeding-background></cap-sheet-bleeding-background>
    <cap-sheet-handle></cap-sheet-handle>
    <cap-sheet-title>Evening route</cap-sheet-title>
    <cap-sheet-description>Choose a route and confirm pickup.</cap-sheet-description>
    <cap-sheet-trigger action="dismiss">Done</cap-sheet-trigger>
    </cap-sheet-content>
    </cap-sheet-view>
    </cap-sheet-portal>
    </cap-sheet>
    .route-sheet {
    width: min(100%, 34em);
    padding: 0 1.25em 1.25em;
    }
  • 注册组件:导入 @capgo/capacitor-sheets 一次,在引导阶段完成,否则元素将无法升级。
  • 视口适配:缺失 viewport-fit=cover 会导致刘海屏手机的安全区域内边距失效。
  • 键盘:当输入框位于底部弹出层内时,请启用文档中说明的焦点滚动防止功能。

安全区域默认通过 safe-area="auto"启用。Sheet 视口会读取浏览器环境值和 Capacitor 回退变量:

env(safe-area-inset-top)
env(safe-area-inset-bottom)
env(safe-area-inset-left)
env(safe-area-inset-right)
var(--safe-area-inset-top)
var(--safe-area-inset-bottom)
var(--safe-area-inset-left)
var(--safe-area-inset-right)

为每个 Sheet 选择受保护的边缘:

<cap-sheet safe-area="auto"></cap-sheet>
<cap-sheet safe-area="bottom left right"></cap-sheet>
<cap-sheet safe-area="none"></cap-sheet>

对于带有覆盖状态栏或系统栏的应用,请保留负责暴露正确 inset 值的原生插件:

import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
StatusBar: {
overlaysWebView: true,
},
Keyboard: {
resize: 'body',
resizeOnFullScreen: true,
},
SystemBars: {
insetsHandling: 'css',
},
},
};
export default config;

键盘处理由 native-focus-scroll-prevention控制,其默认值为 true。仅当您的应用已自行处理键盘避让时,才禁用它:

<cap-sheet native-focus-scroll-prevention="false"></cap-sheet>

所有框架辅助函数都配置同一个底层自定义元素。您也可以直接控制 sheet:

const sheet = document.querySelector('cap-sheet');
await sheet?.present();
await sheet?.stepTo(2);
await sheet?.step('down');
await sheet?.dismiss();

监听事件以进行受控状态管理、分析或协调动画:

sheet?.addEventListener('cap-sheet-presented-change', (event) => {
console.log(event.detail.presented);
});
sheet?.addEventListener('cap-sheet-active-detent-change', (event) => {
console.log(event.detail.activeDetent);
});
sheet?.addEventListener('cap-sheet-travel', (event) => {
console.log(event.detail.progress);
});
import { useEffect, useRef } from 'react';
import { setupSheet } from '@capgo/capacitor-sheets/react';
import '@capgo/capacitor-sheets';
export function BookingSheet() {
const sheetRef = useRef<HTMLElement>(null);
useEffect(() => {
if (!sheetRef.current) return;
return setupSheet(sheetRef.current, {
detents: ['18em', '32em'],
contentPlacement: 'bottom',
onPresentedChange: ({ presented }) => console.log({ presented }),
});
}, []);
return (
<cap-sheet id="booking-sheet" ref={sheetRef}>
<cap-sheet-trigger action="present">Open</cap-sheet-trigger>
<cap-sheet-view>
<cap-sheet-backdrop />
<cap-sheet-content>
<cap-sheet-handle />
<cap-sheet-title>React sheet</cap-sheet-title>
</cap-sheet-content>
</cap-sheet-view>
</cap-sheet>
);
}

从以下位置导入 @capgo/capacitor-sheets/react 同时为自定义元素注册 JSX 类型定义。如果 TypeScript 仍报告未知标签,请在源代码树中添加一个声明文件:

src/capgo-sheets.d.ts
import '@capgo/capacitor-sheets/react';
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { setupSheet } from '@capgo/capacitor-sheets/vue';
import '@capgo/capacitor-sheets';
const sheetRef = ref<HTMLElement | null>(null);
let cleanup: (() => void) | undefined;
onMounted(() => {
if (sheetRef.value) {
cleanup = setupSheet(sheetRef.value, {
detents: ['18em', '32em'],
contentPlacement: 'bottom',
});
}
});
onUnmounted(() => cleanup?.());
</script>
<template>
<cap-sheet id="booking-sheet" ref="sheetRef">
<cap-sheet-trigger action="present">Open</cap-sheet-trigger>
<cap-sheet-view>
<cap-sheet-backdrop />
<cap-sheet-content>
<cap-sheet-handle />
<cap-sheet-title>Vue sheet</cap-sheet-title>
</cap-sheet-content>
</cap-sheet-view>
</cap-sheet>
</template>
import { AfterViewInit, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild } from '@angular/core';
import { setupSheet } from '@capgo/capacitor-sheets/angular';
import '@capgo/capacitor-sheets';
@Component({
selector: 'app-root',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cap-sheet id="booking-sheet" #sheet>
<cap-sheet-trigger action="present">Open</cap-sheet-trigger>
<cap-sheet-view>
<cap-sheet-backdrop></cap-sheet-backdrop>
<cap-sheet-content>
<cap-sheet-handle></cap-sheet-handle>
<cap-sheet-title>Angular sheet</cap-sheet-title>
</cap-sheet-content>
</cap-sheet-view>
</cap-sheet>
`,
})
export class AppComponent implements AfterViewInit {
@ViewChild('sheet', { static: true }) sheet?: ElementRef<HTMLElement>;
ngAfterViewInit(): void {
if (this.sheet?.nativeElement) {
setupSheet(this.sheet.nativeElement, {
detents: ['18em', '32em'],
contentPlacement: 'bottom',
});
}
}
}
<script lang="ts">
import { sheet } from '@capgo/capacitor-sheets/svelte';
import '@capgo/capacitor-sheets';
</script>
<cap-sheet id="booking-sheet" use:sheet={{ detents: ['18em', '32em'], contentPlacement: 'bottom' }}>
<cap-sheet-trigger action="present">Open</cap-sheet-trigger>
<cap-sheet-view>
<cap-sheet-backdrop />
<cap-sheet-content>
<cap-sheet-handle />
<cap-sheet-title>Svelte sheet</cap-sheet-title>
</cap-sheet-content>
</cap-sheet-view>
</cap-sheet>
import { onCleanup, onMount } from 'solid-js';
import { setupSheet } from '@capgo/capacitor-sheets/solid';
import '@capgo/capacitor-sheets';
export function BookingSheet() {
let sheetEl!: HTMLElement;
onMount(() => {
const cleanup = setupSheet(sheetEl, {
detents: ['18em', '32em'],
contentPlacement: 'bottom',
});
onCleanup(cleanup);
});
return (
<cap-sheet id="booking-sheet" ref={sheetEl}>
<cap-sheet-trigger action="present">Open</cap-sheet-trigger>
<cap-sheet-view>
<cap-sheet-backdrop />
<cap-sheet-content>
<cap-sheet-handle />
<cap-sheet-title>Solid sheet</cap-sheet-title>
</cap-sheet-content>
</cap-sheet-view>
</cap-sheet>
);
}
元素用途
cap-sheetSheet 状态、detents、手势、模态行为及事件
cap-sheet-trigger声明式的 present、dismiss、toggle 和 step 操作
cap-sheet-portal用于叠加层分层的可选 body portal
cap-sheet-view固定视口宿主,支持安全区域和键盘内边距
cap-sheet-backdrop进度同步背景
cap-sheet-content可访问的 Sheet 表面
cap-sheet-bleeding-background圆角 Sheet 的背景延伸
cap-sheet-handle可拖拽且支持键盘访问的 Detent 手柄
cap-sheet-title可访问的标题
cap-sheet-description可访问的描述
cap-sheet-special-wrapper用于分离式 Sheet、卡片和灯箱的组合 Hook
cap-sheet-stack堆叠 Sheet 分组
cap-sheet-outlet用于深度、视差和页面效果的进度出口
cap-scroll滚动进度辅助
cap-fixed固定层辅助
cap-island相关浮动岛内容
cap-external-overlay在 sheet 树外部管理的覆盖层内容
选项属性默认描述
contentPlacementcontent-placementbottomtop, bottom, left, right,或 center
detentsdetents无空格分隔的 CSS 长度,例如 18em 32em
safeAreasafe-areaauto受保护的安全区域边缘
swipeswipetrue启用指针、触摸、触控板及滚轮手势
swipeDismissalswipe-dismissaltrue允许通过手势收起到 detent 0
inertOutsideinert-outsidetrue阻止与模态 Sheet 后方内容交互
focusTrapfocus-traptrue让键盘焦点保持在 Sheet 内
closeOnOutsideClickclose-on-outside-clicktrue点击背景或视图时关闭
closeOnEscapeclose-on-escapetrue按下 Escape 键时关闭
nativeFocusScrollPreventionnative-focus-scroll-preventiontrue保持聚焦的输入框在键盘上方可见
themeColorDimmingtheme-color-dimmingauto模态显示时调暗 WebView 主题色
  • @capgo/capacitor-sheets
  • @capgo/capacitor-sheets/react
  • @capgo/capacitor-sheets/vue
  • @capgo/capacitor-sheets/angular
  • @capgo/capacitor-sheets/svelte
  • @capgo/capacitor-sheets/solid

如果你正在使用 快速入门 要规划原生插件工作,请将其与 Capgo 插件目录 查看 Capgo 插件目录中的产品工作流, Capgo 提供的 Capacitor 插件 查看由 Capgo 提供的 Capacitor 插件中的实现细节, 添加或更新插件 查看添加或更新插件中的实现细节, Ionic Enterprise 插件替代方案 查看 Ionic Enterprise 插件替代方案中的产品工作流,以及 Capgo Native Build 查看 Capgo Native Builds 中的产品工作流。