Skip to content

Button

A Flutter-style button widget that separates behavior from appearance.

By default, Button is an unstyled transparent container (similar to a GestureDetector wrapping content). You can define its appearance using the style prop with a ButtonStyle object, or use the variant prop for predefined styles.

iOS Button (Cupertino)

Use variant="ios" to create an iOS-style button with default padding, rounded corners, and opacity feedback on press.

Default (iOS)
Filled (iOS)
Count: 0
vue
<template>
  <Column :gap="20">
    <Text :style="{ fontWeight: FontWeight.bold }">Default (iOS)</Text>
    <Row :gap="20">
      <Button variant="ios" @pressed="onPressed">
        <Text :style="{ color: '#007AFF' }">Button</Text>
      </Button>
      <Button variant="ios" @pressed="onPressed" disabled>
        <Text :style="{ color: '#007AFF' }">Disabled</Text>
      </Button>
    </Row>

    <Text :style="{ fontWeight: FontWeight.bold }">Filled (iOS)</Text>
    <Row :gap="20">
      <Button variant="ios" color="#007AFF" @pressed="onPressed">
        <Text :style="{ color: 'white' }">Button</Text>
      </Button>
      <Button variant="ios" color="#007AFF" @pressed="onPressed" disabled>
        <Text :style="{ color: 'white' }">Disabled</Text>
      </Button>
    </Row>

    <Text>Count: {{ count }}</Text>
  </Column>
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Column, Row, Text, Button, FontWeight } from "fluekit";

const count = ref(0);
const onPressed = () => {
  count.value++;
};
</script>

Props (iOS Variant)

When variant="ios" is set, the following props are available to customize the button:

NameTypeDefaultDescription
colorstringtransparentThe background color of the button.
disabledColorstringrgba(0,0,0,0.2)The color when disabled.
paddingEdgeInsets(14, 16)Padding inside the button.
borderRadiusBorderRadius8Border radius of the button.
pressedOpacitynumber0.4Opacity when the button is pressed.

Styled Button (Material-like)

You can create various button styles (like TextButton, ElevatedButton, OutlinedButton) by passing a ButtonStyle object to the style prop.

vue
<template>
  <Wrap :spacing="20" :run-spacing="20">
    <!-- 类似 TextButton -->
    <Button :style="textButtonStyle" @pressed="handleClick('Text Button')">
      <Text>Text Button</Text>
    </Button>

    <!-- 类似 ElevatedButton -->
    <Button :style="elevatedButtonStyle" @pressed="handleClick('Elevated Button')">
      <Text>Elevated Button</Text>
    </Button>

    <!-- 类似 OutlinedButton -->
    <Button :style="outlinedButtonStyle" @pressed="handleClick('Outlined Button')">
      <Text>Outlined Button</Text>
    </Button>

    <!-- 圆形按钮 -->
    <Button :style="circleButtonStyle" @pressed="handleClick('Circle Button')">
      <Text>+</Text>
    </Button>
  </Wrap>
</template>

<script setup lang="ts">
import { BorderRadius, BorderSide, Button, ButtonStyle, EdgeInsets, Text, Wrap } from "fluekit";

const handleClick = (msg: string) => {
  console.log("Clicked:", msg);
  alert(`Clicked: ${msg}`);
};

// 文本按钮样式
const textButtonStyle = ButtonStyle({
  foregroundColor: "#1976D2", // Primary Blue
  padding: EdgeInsets.symmetric({ horizontal: 16, vertical: 8 }),
  shape: BorderRadius.circular(4),
});

// 凸起按钮样式
const elevatedButtonStyle = ButtonStyle({
  backgroundColor: "#1976D2",
  foregroundColor: "white",
  padding: EdgeInsets.symmetric({ horizontal: 24, vertical: 12 }),
  elevation: 2,
  shadowColor: "rgba(0,0,0,0.3)",
  shape: BorderRadius.circular(4),
});

// 轮廓按钮样式
const outlinedButtonStyle = ButtonStyle({
  foregroundColor: "#1976D2",
  padding: EdgeInsets.symmetric({ horizontal: 24, vertical: 12 }),
  side: BorderSide({ color: "#1976D2", width: 1 }),
  shape: BorderRadius.circular(4),
});

// 圆形按钮样式
const circleButtonStyle = ButtonStyle({
  backgroundColor: "#4CAF50",
  foregroundColor: "white",
  fixedSize: { width: 56, height: 56 }, // 固定尺寸
  shape: BorderRadius.circular(28), // 半径为尺寸的一半
  elevation: 6,
  alignment: "center", // 内容居中
});
</script>

Raw Button (Default)

If no variant or style is provided, Button acts as a raw container that detects gestures. This is useful for creating completely custom interactive elements.

Count: 0
vue
<template>
  <Column :spacing="20" cross-axis-alignment="start">
    <Text>Count: {{ count }}</Text>

    <Row :spacing="20">
      <!-- 默认无样式按钮 -->
      <Button @pressed="count++">
        <Text>Click Me (Unstyled)</Text>
      </Button>

      <!-- 禁用状态 -->
      <Button disabled @pressed="count++">
        <Text style="color: grey">Disabled</Text>
      </Button>
    </Row>
  </Column>
</template>

<script setup lang="ts">
import { Button, Column, Row, Text } from "fluekit";
import { ref } from "vue";

const count = ref(0);
</script>

API

Props

NameTypeDefaultDescription
disabledbooleanfalseWhether the button is disabled. When disabled, events are not triggered.
textstring-The text content of the button. Shorthand for default slot.
behaviorBehavior'opaque'How this gesture detector should behave during hit testing.
variant'raw' | 'ios''raw'The style variant of the button.
styleButtonStyle-The style configuration object for the button.

Events

NameDescriptionParameters
pressedTriggered when the button is tapped/clicked.-
long-pressTriggered when the button is long-pressed.-
tap-downTriggered when the pointer touches the button.event
tap-upTriggered when the pointer is released.event
tap-cancelTriggered when the pointer cancels the gesture.event

ButtonStyle

Object used to configure the button's appearance.

PropertyTypeDescription
backgroundColorstringBackground color.
foregroundColorstringForeground color (text/icon color).
textStyleTextStyleStyle to apply to text content.
paddingEdgeInsetsPadding inside the button.
sideBorderSideBorder style.
shapeBorderRadiusShape of the button (currently supports radius).
elevationnumberHeight of the shadow.
shadowColorstringColor of the shadow.
minimumSizeSizeMinimum size constraints.
maximumSizeSizeMaximum size constraints.
fixedSizeSizeFixed size constraints.
alignmentAlignmentAlignment of the content.