ProComponents, templates & AI tooling
2.3k

Accordion 手风琴

可折叠内容面板,在紧凑空间内组织信息

导入

import { Accordion } from 'heroui-native';

结构

<Accordion>
  <Accordion.Item>
    <Accordion.Trigger>
      ...
      <Accordion.Indicator>...</Accordion.Indicator>
    </Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>
  • Accordion:主容器,管理手风琴状态与行为;控制各条目的展开/收起,支持单选或多选展开模式,并提供 defaultsurface 等视觉变体。
  • Accordion.Item:单个条目的容器,包裹触发器与内容,并管理该条目的展开状态。
  • Accordion.Trigger:用于切换条目展开的可交互区域,基于 Header 与 Trigger 原语构建。
  • Accordion.Indicator:可选的视觉指示器,展示展开状态;默认使用随状态旋转的动画 chevron 图标。
  • Accordion.Content:可展开内容的容器,配合布局过渡动画实现平滑展开/收起。

用法

基础用法

Accordion 通过复合子组件创建可展开的内容区块。

<Accordion selectionMode="single">
  <Accordion.Item value="1">
    <Accordion.Trigger>
      ...
      <Accordion.Indicator />
    </Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

单选模式

同一时间只允许展开一个条目。

<Accordion selectionMode="single" defaultValue="2">
  <Accordion.Item value="1">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
  <Accordion.Item value="2">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

多选模式

允许多个条目同时展开。

<Accordion selectionMode="multiple" defaultValue={['1', '3']}>
  <Accordion.Item value="1">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
  <Accordion.Item value="2">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
  <Accordion.Item value="3">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

Surface 变体

为手风琴应用表面容器样式。

<Accordion selectionMode="single" variant="surface">
  <Accordion.Item value="1">
    <Accordion.Trigger>
      ...
      <Accordion.Indicator />
    </Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

自定义指示器

用自定义内容替换默认 chevron 指示器。

<Accordion selectionMode="single">
  <Accordion.Item value="1">
    <Accordion.Trigger>
      ...
      <Accordion.Indicator>
        <CustomIndicator />
      </Accordion.Indicator>
    </Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

无分隔线

隐藏条目之间的分隔线。

<Accordion selectionMode="single" hideSeparator>
  <Accordion.Item value="1">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
  <Accordion.Item value="2">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

自定义样式

通过 classNameclassNamesstyles 传入自定义样式。

<Accordion
  className="rounded-lg"
  classNames={{
    container: 'bg-surface',
    separator: 'bg-separator/50',
  }}
  styles={{
    container: { padding: 16 },
    separator: { height: 2 },
  }}
>
  <Accordion.Item value="1">
    <Accordion.Trigger>...</Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>

配合 PressableFeedback

Accordion.Trigger 使用 asChild,并用 PressableFeedback 包裹内容以添加按压反馈动画。

import { Accordion, PressableFeedback } from 'heroui-native';
import { View } from 'react-native';

<Accordion>
  <Accordion.Item value="1">
    <Accordion.Trigger asChild>
      <PressableFeedback animation={{ scale: false }}>
        <PressableFeedback.Scale className="flex-row items-center flex-1 gap-3">
          <Text>条目标题</Text>
        </PressableFeedback.Scale>
        <Accordion.Indicator />
        <PressableFeedback.Highlight
          animation={{ opacity: { value: [0, 0.05] } }}
        />
      </PressableFeedback>
    </Accordion.Trigger>
    <Accordion.Content>...</Accordion.Content>
  </Accordion.Item>
</Accordion>;

示例

import { Accordion, useThemeColor } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import { View, Text } from 'react-native';

export default function AccordionExample() {
  const themeColorMuted = useThemeColor('muted');

  const accordionData = [
    {
      id: '1',
      title: '如何下单?',
      icon: <Ionicons name="bag-outline" size={16} color={themeColorMuted} />,
      content:
        '这是一段示例说明文字,用于演示折叠面板中的正文内容展示效果。',
    },
    {
      id: '2',
      title: '支持哪些支付方式?',
      icon: <Ionicons name="card-outline" size={16} color={themeColorMuted} />,
      content:
        '这是一段示例说明文字,用于演示折叠面板中的正文内容展示效果。',
    },
    {
      id: '3',
      title: '运费如何计算?',
      icon: <Ionicons name="cube-outline" size={16} color={themeColorMuted} />,
      content:
        '这是一段示例说明文字,用于演示折叠面板中的正文内容展示效果。',
    },
  ];

  return (
    <Accordion selectionMode="single" variant="surface" defaultValue="2">
      {accordionData.map((item) => (
        <Accordion.Item key={item.id} value={item.id}>
          <Accordion.Trigger>
            <View className="flex-row items-center flex-1 gap-3">
              {item.icon}
              <Text className="text-foreground text-base flex-1">
                {item.title}
              </Text>
            </View>
            <Accordion.Indicator />
          </Accordion.Trigger>
          <Accordion.Content>
            <Text className="text-muted text-base/relaxed px-[25px]">
              {item.content}
            </Text>
          </Accordion.Content>
        </Accordion.Item>
      ))}
    </Accordion>
  );
}

更多示例见 GitHub 仓库

API 参考

Accordion

proptypedefaultdescription
childrenReact.ReactNode-渲染在手风琴内的子节点
selectionMode'single' | 'multiple'-允许单条或多条同时展开
variant'default' | 'surface''default'手风琴视觉变体
hideSeparatorbooleanfalse是否隐藏条目之间的分隔线
defaultValuestring | string[] | undefined-非受控模式下的默认展开项
valuestring | string[] | undefined-受控模式下的当前展开项
isDisabledboolean-是否禁用全部条目
isCollapsiblebooleantrue已展开条目是否可再次收起
animationAccordionRootAnimation-根级动画配置
classNamestring-容器的额外 class
classNamesElementSlots<RootSlots>-各插槽的额外 class
stylesPartial<Record<RootSlots, ViewStyle>>-根组件各部分的样式
onValueChange(value: string | string[] | undefined) => void-展开项变化时的回调
...Animated.ViewPropsAnimated.ViewProps-支持 Reanimated Animated.View 的全部属性

ElementSlots<RootSlots>

proptypedescription
containerstring手风琴容器的自定义 class
separatorstring条目之间分隔线的自定义 class

styles

proptypedescription
containerViewStyle手风琴容器样式
separatorViewStyle条目之间分隔线样式

AccordionRootAnimation

手风琴根组件的动画配置,可为:

  • false"disabled":仅禁用根级动画
  • "disable-all":禁用全部动画(含子级)
  • trueundefined:使用默认动画
  • object:自定义动画配置
proptypedefaultdescription
state'disabled' | 'disable-all' | boolean-在自定义属性时禁用动画
layout.valueLayoutTransitionLinearTransition
.springify()
.damping(140)
.stiffness(1600)
.mass(4)
手风琴过渡的自定义布局动画

Accordion.Item

proptypedefaultdescription
childrenReact.ReactNode | ((props: AccordionItemRenderProps) => React.ReactNode)-条目内的子节点,或渲染函数
valuestring-唯一标识该条目的值
isDisabledboolean-是否禁用该条目
classNamestring-额外的 class
...Animated.ViewPropsAnimated.ViewProps-支持 Reanimated Animated.View 的全部属性

AccordionItemRenderProps

proptypedescription
isExpandedboolean当前条目是否展开
valuestring该条目的唯一值

Accordion.Trigger

proptypedefaultdescription
childrenReact.ReactNode-触发器内的子节点
classNamestring-额外的 class
isDisabledboolean-是否禁用触发器
...PressablePropsPressableProps-支持 React Native Pressable 的属性

Accordion.Indicator

proptypedefaultdescription
childrenReact.ReactNode-自定义指示器内容;未提供时默认为带动画的 chevron
classNamestring-额外的 class
iconPropsAccordionIndicatorIconProps-图标配置
animationAccordionIndicatorAnimation-指示器动画配置
isAnimatedStyleActivebooleantrue是否启用 Reanimated 动画样式
...Animated.ViewPropsAnimated.ViewProps-支持 Reanimated Animated.View 的全部属性

AccordionIndicatorIconProps

proptypedefaultdescription
sizenumber16图标尺寸
colorstringforeground图标颜色

AccordionIndicatorAnimation

指示器动画配置,可为:

  • false"disabled":禁用全部动画
  • trueundefined:使用默认动画
  • object:自定义动画配置
proptypedefaultdescription
state'disabled' | boolean-在自定义属性时禁用动画
rotation.value[number, number][0, -180]旋转角度 [收起, 展开],单位为度
rotation.springConfigWithSpringConfig{ damping: 140, stiffness: 1000, mass: 4 }旋转弹簧动画配置

Accordion.Content

proptypedefaultdescription
childrenReact.ReactNode-内容区域内的子节点
classNamestring-额外的 class
animationAccordionContentAnimation-内容动画配置
...ViewPropsViewProps-支持 React Native View 的属性

AccordionContentAnimation

内容区动画配置,可为:

  • false"disabled":禁用全部动画
  • trueundefined:使用默认动画
  • object:自定义动画配置
proptypedefaultdescription
state'disabled' | boolean-在自定义属性时禁用动画
entering.valueEntryOrExitLayoutTypeFadeIn
.duration(200)
.easing(Easing.out(Easing.ease))
自定义进入动画
exiting.valueEntryOrExitLayoutTypeFadeOut
.duration(200)
.easing(Easing.in(Easing.ease))
自定义退出动画

Hooks

useAccordion

访问手风琴根上下文,必须在 Accordion 内使用。

import { useAccordion } from 'heroui-native';

const { value, onValueChange, selectionMode, isCollapsible, isDisabled } =
  useAccordion();

返回值

propertytypedescription
selectionMode'single' | 'multiple' | undefined单选或多选展开模式
value(string | undefined) | string[]当前展开项:单选为字符串,多选为数组
onValueChange(value: string | undefined) => void | ((value: string[]) => void)更新展开项的回调
isCollapsibleboolean已展开项是否可收起
isDisabledboolean | undefined是否禁用全部条目

useAccordionItem

访问单条条目上下文,必须在 Accordion.Item 内使用。

import { useAccordionItem } from 'heroui-native';

const { value, isExpanded, isDisabled, nativeID } = useAccordionItem();

返回值

propertytypedescription
valuestring该条目的唯一值
isExpandedboolean当前是否展开
isDisabledboolean | undefined该条目是否禁用
nativeIDstring无障碍与 ARIA 使用的原生 ID

特别说明

当 Accordion 与同屏其他组件一起使用时,请为这些组件导入并应用 AccordionLayoutTransition,以保证整屏布局动画一致、顺滑。

import { Accordion, AccordionLayoutTransition } from 'heroui-native';
import Animated from 'react-native-reanimated';

<Animated.ScrollView layout={AccordionLayoutTransition}>
  <Animated.View layout={AccordionLayoutTransition}>
    {/* 其他内容 */}
  </Animated.View>

  <Accordion>{/* 手风琴条目 */}</Accordion>
</Animated.ScrollView>;

这样在展开或收起时,屏幕上各组件会使用相同的时长与缓动,体验更统一。

本页目录