Skip to content

Effects

Opacity

A widget that makes its child partially transparent.

1.0
0.5
0.1
vue
<template>
  <Row :gap="20">
    <Opacity :opacity="1.0">
      <Container :width="60" :height="60" color="blue" alignment="center">
        <Text data="1.0" :style="TextStyle({ color: 'white' })" />
      </Container>
    </Opacity>
    <Opacity :opacity="0.5">
      <Container :width="60" :height="60" color="blue" alignment="center">
        <Text data="0.5" :style="TextStyle({ color: 'white' })" />
      </Container>
    </Opacity>
    <Opacity :opacity="0.1">
      <Container :width="60" :height="60" color="blue" alignment="center">
        <Text data="0.1" :style="TextStyle({ color: 'white' })" />
      </Container>
    </Opacity>
  </Row>
</template>

<script setup lang="ts">
import { Opacity, Row, Container, Text, TextStyle } from "fluekit";
</script>

Transform

A widget that applies a transformation before painting its child.

Rotation
45°
90°
Scale
0.5x
1.5x
Translate
Offset
Skew
Skew X
Skew Y
3D Rotation
Rot X
Rot Y
Stack & Positioned
Back
Front
vue
<template>
  <div class="demo-box">
    <Column :gap="30" alignment="center">
      <!-- Rotation -->
      <Column :gap="10" alignment="center">
        <Text data="Rotation" :style="labelStyle" />
        <Row :gap="20">
          <Transform :transform="Matrix4.rotationZ(Math.PI / 4)" alignment="center">
            <Container :width="80" :height="80" color="purple" alignment="center">
              <Text data="45°" :style="textStyle" />
            </Container>
          </Transform>
          <Transform :transform="Matrix4.rotationZ(Math.PI / 2)" alignment="center">
            <Container :width="80" :height="80" color="indigo" alignment="center">
              <Text data="90°" :style="textStyle" />
            </Container>
          </Transform>
        </Row>
      </Column>

      <!-- Scale -->
      <Column :gap="10" alignment="center">
        <Text data="Scale" :style="labelStyle" />
        <Row :gap="40">
          <Transform :transform="Matrix4.scaling(0.5, 0.5)" alignment="center">
            <Container :width="80" :height="80" color="blue" alignment="center">
              <Text data="0.5x" :style="textStyle" />
            </Container>
          </Transform>
          <Transform :transform="Matrix4.scaling(1.5, 1.5)" alignment="center">
            <Container :width="80" :height="80" color="blue" alignment="center">
              <Text data="1.5x" :style="textStyle" />
            </Container>
          </Transform>
        </Row>
      </Column>

      <!-- Translate -->
      <Column :gap="10" alignment="center">
        <Text data="Translate" :style="labelStyle" />
        <Container :width="200" :height="100" color="#eeeeee" alignment="center">
          <Transform :transform="Matrix4.translation(20, -20)" alignment="center">
            <Container :width="60" :height="60" color="green" alignment="center">
              <Text data="Offset" :style="textStyle" />
            </Container>
          </Transform>
        </Container>
      </Column>

      <!-- Skew -->
      <Column :gap="10" alignment="center">
        <Text data="Skew" :style="labelStyle" />
        <Row :gap="20">
          <Transform :transform="Matrix4.skewX(0.3)" alignment="center">
            <Container :width="80" :height="80" color="orange" alignment="center">
              <Text data="Skew X" :style="textStyle" />
            </Container>
          </Transform>
          <Transform :transform="Matrix4.skewY(0.3)" alignment="center">
            <Container :width="80" :height="80" color="deepOrange" alignment="center">
              <Text data="Skew Y" :style="textStyle" />
            </Container>
          </Transform>
        </Row>
      </Column>

      <!-- 3D Rotation -->
      <Column :gap="10" alignment="center">
        <Text data="3D Rotation" :style="labelStyle" />
        <Row :gap="20">
          <Transform :transform="Matrix4.rotationX(Math.PI / 4)" alignment="center">
            <Container :width="80" :height="80" color="teal" alignment="center">
              <Text data="Rot X" :style="textStyle" />
            </Container>
          </Transform>
          <Transform :transform="Matrix4.rotationY(Math.PI / 4)" alignment="center">
            <Container :width="80" :height="80" color="cyan" alignment="center">
              <Text data="Rot Y" :style="textStyle" />
            </Container>
          </Transform>
        </Row>
      </Column>

      <!-- Stack & Positioned -->
      <Column :gap="10" alignment="center">
        <Text data="Stack & Positioned" :style="labelStyle" />
        <Container :width="200" :height="200" color="#f0f0f0">
          <Stack>
            <Positioned :top="40" :left="40">
              <Transform :transform="Matrix4.rotationZ(-0.2)" alignment="center">
                <Container
                  :width="120"
                  :height="120"
                  color="rgba(255, 0, 0, 0.5)"
                  alignment="center"
                >
                  <Text data="Back" :style="textStyle" />
                </Container>
              </Transform>
            </Positioned>
            <Positioned :top="40" :left="40">
              <Transform :transform="Matrix4.rotationZ(0.2)" alignment="center">
                <Container
                  :width="120"
                  :height="120"
                  color="rgba(0, 0, 255, 0.5)"
                  alignment="center"
                >
                  <Text data="Front" :style="textStyle" />
                </Container>
              </Transform>
            </Positioned>
          </Stack>
        </Container>
      </Column>
    </Column>
  </div>
</template>

<script setup lang="ts">
import {
  Transform,
  Container,
  Column,
  Row,
  Text,
  TextStyle,
  Matrix4,
  Stack,
  Positioned,
} from "fluekit";

const textStyle = TextStyle({ color: "white", fontSize: 14 });
const labelStyle = TextStyle({ fontWeight: "bold", fontSize: 16, color: "#333" });
</script>

IgnorePointer

A widget that is invisible during hit testing.

Click Me
Ignored
(Red box ignores clicks)
vue
<template>
  <Row :gap="20">
    <GestureDetector behavior="opaque" @click="$alert('Clicked Normal')">
      <Container :width="100" :height="50" color="green" alignment="center">
        <Text data="Click Me" :style="TextStyle({ color: 'white' })" />
      </Container>
    </GestureDetector>
    <GestureDetector behavior="opaque" @click="$alert('Clicked ignoring ')">
      <IgnorePointer ignoring>
        <Container :width="100" :height="50" color="red" alignment="center">
          <Text data="Ignored" :style="TextStyle({ color: 'white' })" />
        </Container>
      </IgnorePointer>
    </GestureDetector>
  </Row>
  <Text data="(Red box ignores clicks)" :style="TextStyle({ fontSize: 12, color: 'grey' })" />
</template>

<script setup lang="ts">
import { Row, GestureDetector, Container, Text, IgnorePointer, TextStyle } from "fluekit";

const $alert = (msg: string) => {
  window.alert(msg);
};
</script>

SafeArea

A widget that insets its child by sufficient padding to avoid operating system intrusions (e.g. notch).

Safe Content Area
vue
<template>
  <Container color="#333" :width="300" :height="150">
    <SafeArea :minimum="{ top: 20, left: 10, right: 10, bottom: 20 }">
      <Container color="white" :width="300" :height="150" alignment="center">
        <Text data="Safe Content Area" />
      </Container>
    </SafeArea>
  </Container>
</template>

<script setup lang="ts">
import { Container, SafeArea, Text } from "fluekit";
</script>

BackdropFilter

A widget that applies a filter to the existing painted content and then paints the child. This effect is relatively expensive, especially if the filter is non-local, such as a blur.

BackdropFilter Demo1. Using BackdropFilter Widget
Frosted Glass
2. Using BoxDecoration.backdropFilter
Blurred Box
vue
<template>
  <Column :gap="30">
    <Text :style="titleStyle" data="BackdropFilter Demo" />

    <Text data="1. Using BackdropFilter Widget" :style="subtitleStyle" />
    <Container
      :width="300"
      :height="200"
      :decoration="
        BoxDecoration({
          image: DecorationImage({
            image: NetworkImage('https://picsum.photos/300/200'),
            fit: 'cover',
          }),
        })
      "
    >
      <Center>
        <BackdropFilter :filter="ImageFilter.blur({ sigmaX: 5, sigmaY: 5 })">
          <Container
            :padding="EdgeInsets.all(20)"
            color="rgba(0, 0, 0, 0.3)"
            :decoration="BoxDecoration({ borderRadius: BorderRadius.circular(10) })"
          >
            <Text
              data="Frosted Glass"
              :style="TextStyle({ color: 'white', fontWeight: FontWeight.bold })"
            />
          </Container>
        </BackdropFilter>
      </Center>
    </Container>

    <Text data="2. Using BoxDecoration.backdropFilter" :style="subtitleStyle" />
    <Container
      :width="300"
      :height="200"
      :decoration="
        BoxDecoration({
          image: DecorationImage({
            image: NetworkImage('https://picsum.photos/300/200?random=2'),
            fit: 'cover',
          }),
        })
      "
    >
      <Center>
        <!-- Directly applying backdropFilter in BoxDecoration of the child container -->
        <Container
          :width="200"
          :height="100"
          alignment="center"
          :decoration="
            BoxDecoration({
              color: 'rgba(255, 255, 255, 0.2)',
              borderRadius: BorderRadius.circular(15),
              border: Border.all({ color: 'rgba(255, 255, 255, 0.3)', width: 1 }),
              backdropFilter: ImageFilter.blur({ sigmaX: 10 }),
            })
          "
        >
          <Text
            data="Blurred Box"
            :style="TextStyle({ color: 'white', fontWeight: FontWeight.bold, fontSize: 20 })"
          />
        </Container>
      </Center>
    </Container>
  </Column>
</template>

<script setup lang="ts">
import {
  BackdropFilter,
  Border,
  BorderRadius,
  BoxDecoration,
  Center,
  Column,
  Container,
  DecorationImage,
  EdgeInsets,
  FontWeight,
  ImageFilter,
  NetworkImage,
  Text,
  TextStyle,
} from "fluekit";

const titleStyle = TextStyle({
  fontSize: 24,
  fontWeight: FontWeight.bold,
  color: "#333",
});

const subtitleStyle = TextStyle({
  fontSize: 18,
  fontWeight: FontWeight.w600,
  color: "#666",
});
</script>

API

Opacity

Props

NameTypeDefaultDescription
opacitynumber1.0The fraction to scale the child's alpha value.

Slots

NameDescription
defaultThe widget below this widget in the tree.

Transform

Props

NameTypeDefaultDescription
transformstring-The transformation matrix to apply (CSS transform).
alignmentAlignment'center'The alignment of the origin of the coordinate system in which the transform takes place.
originstring-The origin of the coordinate system (CSS transform-origin).

Slots

NameDescription
defaultThe widget below this widget in the tree.

IgnorePointer

Props

NameTypeDefaultDescription
ignoringbooleanfalseWhether this widget ignores pointer events.
ignoringSemanticsbooleanfalseWhether this widget is invisible to semantics.

Slots

NameDescription
defaultThe widget below this widget in the tree.

SafeArea

Props

NameTypeDefaultDescription
topbooleantrueWhether to avoid system intrusions at the top.
bottombooleantrueWhether to avoid system intrusions at the bottom.
leftbooleantrueWhether to avoid system intrusions on the left.
rightbooleantrueWhether to avoid system intrusions on the right.
minimumEdgeInsetsEdgeInsets.zeroThe minimum padding to apply.

Slots

NameDescription
defaultThe widget below this widget in the tree.

BackdropFilter

Props

NameTypeDefaultDescription
filterImageFilter | string-The image filter to apply to the existing painted content.

Slots

NameDescription
defaultThe widget below this widget in the tree.