FAB | CoUI

FAB

화면의 주요 액션을 강조하는 플로팅 액션 버튼 컴포넌트

FAB#

화면의 주요 액션을 강조하는 플로팅 액션 버튼(Floating Action Button)입니다. Fab은 단독 버튼으로도, 탭하면 펼쳐지는 speed-dial 액션 묶음으로도 사용할 수 있습니다. Flutter와 Web이 동일한 Fab API를 공유합니다.

Live Preview#

Web
Flutter
Loading Flutter...
class FabDefaultExample extends StatelessComponent {
  const FabDefaultExample({super.key});

  @override
  Component build(BuildContext context) {
    return Fab(
      trigger: const Icon(LucideIcons.plus),
      onPressed: () {},
      expandDirection: CoreFabExpandDirection.down,
      actions: [
        FabAction(
          icon: const Icon(LucideIcons.pencil),
          label: Component.text('Edit'),
        ),
        FabAction(
          icon: const Icon(LucideIcons.share2),
          label: Component.text('Share'),
        ),
      ],
    );
  }
}
class FabDefaultExample extends StatelessWidget {
  const FabDefaultExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Fab(
      trigger: const Icon(LucideIcons.plus),
      onPressed: () {},
      expandDirection: CoreFabExpandDirection.down,
      actions: [
        FabAction(
          icon: const Icon(LucideIcons.pencil),
          label: const Text('Edit'),
        ),
        FabAction(
          icon: const Icon(LucideIcons.share2),
          label: const Text('Share'),
        ),
      ],
    );
  }
}

사용 시기 (When to Use)#

이 컴포넌트를 사용하세요:

  • 화면 내에서 가장 중요한 단일 액션을 명확히 강조하고 싶을 때 (새 항목 만들기, 작성, 공유)
  • 스크롤해도 항상 접근 가능해야 하는 주요 CTA(Call to Action)가 필요할 때
  • 하나의 트리거에서 여러 관련 액션을 speed-dial로 펼쳐 보여주고 싶을 때

대신 다른 컴포넌트를 사용하세요:

  • Button: 여러 동등한 액션을 나란히 제공할 때, 또는 인라인 액션이 필요할 때
  • Tooltip: 아이콘 전용 FAB에 레이블 설명을 추가할 때 함께 사용

기본 사용법 (Basic Usage)#

// 기본 FAB
Fab(
  trigger: const Icon(LucideIcons.plus),
  onPressed: handleCreate,
)

// 소형 FAB
Fab(
  trigger: const Icon(LucideIcons.plus),
  size: CoreFabSize.mini,
  onPressed: handleCreate,
)

// Speed-dial FAB (탭하면 액션 펼침)
Fab(
  trigger: const Icon(LucideIcons.plus),
  actions: [
    FabAction(
      icon: const Icon(LucideIcons.pencil),
      label: const Text('Edit'),
      onPressed: handleEdit,
    ),
    FabAction(
      icon: const Icon(LucideIcons.share2),
      label: const Text('Share'),
      onPressed: handleShare,
    ),
  ],
)
// 기본 FAB
Fab(
  trigger: const Icon(LucideIcons.plus),
  onPressed: handleCreate,
)

// 소형 FAB
Fab(
  trigger: const Icon(LucideIcons.plus),
  size: CoreFabSize.mini,
  onPressed: handleCreate,
)

// Speed-dial FAB
Fab(
  trigger: const Icon(LucideIcons.plus),
  actions: [
    FabAction(
      icon: const Icon(LucideIcons.pencil),
      label: Component.text('Edit'),
      onPressed: handleEdit,
    ),
    FabAction(
      icon: const Icon(LucideIcons.share2),
      label: Component.text('Share'),
      onPressed: handleShare,
    ),
  ],
)

Props / Parameters#

속성타입기본값설명
trigger Widget / Component 필수 메인 FAB 내부에 표시할 콘텐츠 (보통 아이콘)
onPressed VoidCallback? null 메인 FAB 클릭 핸들러. actions가 있으면 speed-dial 토글로 동작
actions List<FabAction>? null speed-dial 액션 목록
open bool false speed-dial 열림 상태 (controlled 모드)
onOpenChanged void Function(bool)? null speed-dial 열림 상태 변경 콜백
size CoreFabSize regular FAB 크기 (mini / regular / large)
expandDirection CoreFabExpandDirection up speed-dial 펼침 방향 ( up / down / left / right / fan )
closeIcon Widget? / Component? null speed-dial 열림 시 표시할 아이콘 (기본값: X 아이콘)
tooltip String? null 메인 FAB 툴팁 텍스트
fabStyle CoreFabStyle? null 색상 / 그림자 / 간격 등 chrome 오버라이드

FabAction#

속성타입기본값설명
icon Widget / Component 필수 액션 버튼 내부 아이콘
label Widget? / Component? null 액션 버튼 옆 라벨
onPressed VoidCallback? null 액션 클릭 핸들러
tooltip String? null 액션 툴팁 텍스트

크기 (Sizes)#

크기지름
MiniCoreFabSize.mini40px
RegularCoreFabSize.regular56px
LargeCoreFabSize.large72px

동작 스펙 (Behavior)#

인터랙션#

  • 클릭/탭: actions가 없으면 onPressed 콜백 실행. actions가 있으면 speed-dial을 펼치거나 접음
  • speed-dial 액션 클릭: 해당 액션의 onPressed 실행 후 speed-dial 자동 닫힘
  • 호버: 커서가 포인터로 전환
  • 포커스: 포커스 링 표시로 키보드 탐색 가능 상태 표시

Controlled / Uncontrolled#

  • onOpenChanged를 제공하지 않으면 Fab이 내부 상태로 speed-dial 열림/닫힘을 관리합니다 (uncontrolled)
  • onOpenChanged를 제공하면 open 값으로 외부에서 상태를 제어합니다 (controlled)

애니메이션#

  • speed-dial 펼침/접힘: 200ms ease-in-out, 액션별 stagger 적용
  • 펼침 방향(expandDirection)에 따라 액션이 동일한 계산식으로 배치됨

사용 가이드라인 (Usage Guidelines)#

✅ Do#

한 화면에 하나의 FAB만 사용

Fab(
  trigger: const Icon(LucideIcons.plus),
  tooltip: '새 노트 작성',
  onPressed: handleCreateNote,
)

FAB은 화면에서 가장 중요한 단일 액션을 나타내야 합니다. 여러 개를 사용하면 사용자가 어느 것이 주요 액션인지 혼란스러워집니다.


❌ Don't#

파괴적인 액션에 FAB 사용 금지

// ❌ 삭제(파괴적) 액션에 FAB 사용
Fab(
  trigger: const Icon(LucideIcons.trash2),
  onPressed: handleDeleteAll,
)

FAB은 눈에 잘 띄기 때문에 실수로 클릭하기 쉽습니다. 삭제 같은 파괴적인 액션에는 확인 다이얼로그가 있는 일반 버튼을 사용하세요.

✅ Do#

speed-dial로 관련 액션을 묶어 제공

Fab(
  trigger: const Icon(LucideIcons.plus),
  actions: [
    FabAction(
      icon: const Icon(LucideIcons.pencil),
      label: const Text('Edit'),
      onPressed: handleEdit,
    ),
    FabAction(
      icon: const Icon(LucideIcons.share2),
      label: const Text('Share'),
      onPressed: handleShare,
    ),
  ],
)

하나의 트리거에서 관련된 보조 액션을 펼쳐 보여주면 화면을 깔끔하게 유지할 수 있습니다.

접근성 (Accessibility)#

키보드 인터랙션#

동작
Enter / SpaceFAB 액션 실행 또는 speed-dial 토글
Tab다음 포커스 가능 요소로 이동

스크린 리더#

  • Flutter: Tooltip 위젯으로 버튼 레이블 전달. tooltip 속성 설정 권장
  • Web: role="button", aria-label, aria-expanded가 자동 적용

터치 타겟#

  • Mini: 40px (중요도 낮은 보조 액션에만 사용)
  • Regular: 56px (기본, 권장)
  • Large: 72px (특별히 강조가 필요한 경우)

크로스 플랫폼 차이점 (Platform Differences)#

항목FlutterWeb
클래스명FabFab
클릭 핸들러onPressedonPressed
elevation CoreShadow 토큰 → BoxShadow CoreShadow 토큰 → CSS box-shadow
speed-dial 토글 controlled open 상태 + 애니메이션 controlled open 상태 + CSS transition
  • Button: 인라인 또는 덜 중요한 액션에 사용
  • Tooltip: 아이콘 전용 FAB에 레이블 설명 추가 시 함께 사용