Skip to main content

SpinKit

30 animated loading spinner controls built on Flutter's flutter_spinkit package.

Usage

Add flet-spinkit to your project dependencies:

uv add flet-spinkit

Then import the package in your Flet app:

import flet_spinkit as spins

Examples

SpinKit Showcase

play_arrowTry Online
import flet_spinkit as spins

import flet as ft

SPINNERS = [
("RotatingPlain", spins.RotatingPlain),
("DoubleBounce", spins.DoubleBounce),
("Wave", spins.Wave),
("WanderingCubes", spins.WanderingCubes),
("FadingFour", spins.FadingFour),
("FadingCube", spins.FadingCube),
("Pulse", spins.Pulse),
("ChasingDots", spins.ChasingDots),
("ThreeBounce", spins.ThreeBounce),
("Circle", spins.Circle),
("CubeGrid", spins.CubeGrid),
("FadingCircle", spins.FadingCircle),
("RotatingCircle", spins.RotatingCircle),
("FoldingCube", spins.FoldingCube),
("PumpingHeart", spins.PumpingHeart),
("HourGlass", spins.HourGlass),
("PouringHourGlass", spins.PouringHourGlass),
("PouringHourGlassRefined", spins.PouringHourGlassRefined),
("FadingGrid", spins.FadingGrid),
("Ring", spins.Ring),
("Ripple", spins.Ripple),
("DualRing", spins.DualRing),
("SpinningCircle", spins.SpinningCircle),
("SpinningLines", spins.SpinningLines),
("SquareCircle", spins.SquareCircle),
("ThreeInOut", spins.ThreeInOut),
("DancingSquare", spins.DancingSquare),
("PianoWave", spins.PianoWave),
("PulsingGrid", spins.PulsingGrid),
("WaveSpinner", spins.WaveSpinner),
]


def main(page: ft.Page):
page.title = "SpinKit Showcase"
page.scroll = ft.ScrollMode.AUTO
page.padding = 20

color = ft.Colors.BLUE

page.add(
ft.GridView(
runs_count=4,
max_extent=160,
child_aspect_ratio=0.9,
spacing=12,
run_spacing=12,
controls=[
ft.Container(
content=ft.Column(
[
ft.Container(
content=cls(color=color, size=50),
alignment=ft.Alignment.CENTER,
expand=True,
),
ft.Text(
name,
size=11,
text_align=ft.TextAlign.CENTER,
),
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=8,
),
bgcolor=ft.Colors.SURFACE_CONTAINER_HIGHEST,
border_radius=12,
padding=12,
)
for name, cls in SPINNERS
],
)
)


if __name__ == "__main__":
ft.run(main)

SpinKit Properties

play_arrowTry Online
import flet_spinkit as spins

import flet as ft


def section(title: str, controls: list) -> ft.Column:
return ft.Column(
[
ft.Text(title, size=14, weight=ft.FontWeight.BOLD),
ft.Row(controls, spacing=24, wrap=True),
],
spacing=12,
)


def labeled(spinner, label: str) -> ft.Column:
return ft.Column(
[
ft.Container(
content=spinner,
alignment=ft.Alignment.CENTER,
width=80,
height=80,
),
ft.Text(
label,
size=10,
text_align=ft.TextAlign.CENTER,
),
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
spacing=4,
)


def main(page: ft.Page):
page.title = "SpinKit Properties"
page.scroll = ft.ScrollMode.AUTO
page.padding = 24

page.add(
ft.Text("SpinKit Properties", size=24, weight=ft.FontWeight.BOLD),
ft.Divider(height=16, color=ft.Colors.TRANSPARENT),
# Colors
section(
"color",
[
labeled(spins.RotatingCircle(color=ft.Colors.BLUE, size=50), "BLUE"),
labeled(spins.RotatingCircle(color=ft.Colors.RED, size=50), "RED"),
labeled(spins.RotatingCircle(color=ft.Colors.GREEN, size=50), "GREEN"),
labeled(
spins.RotatingCircle(color=ft.Colors.ORANGE, size=50), "ORANGE"
),
labeled(
spins.RotatingCircle(color=ft.Colors.PURPLE, size=50), "PURPLE"
),
labeled(spins.RotatingCircle(color=ft.Colors.TEAL, size=50), "TEAL"),
],
),
ft.Divider(height=8),
# Sizes
section(
"size",
[
labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=20), "20"),
labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=30), "30"),
labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=40), "40"),
labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=50), "50"),
labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=70), "70"),
],
),
ft.Divider(height=8),
# Durations
section(
"duration",
[
labeled(
spins.Pulse(
color=ft.Colors.BLUE,
size=50,
duration=ft.Duration(milliseconds=400),
),
"400ms",
),
labeled(
spins.Pulse(
color=ft.Colors.BLUE,
size=50,
duration=ft.Duration(milliseconds=700),
),
"700ms",
),
labeled(
spins.Pulse(
color=ft.Colors.BLUE,
size=50,
duration=ft.Duration(milliseconds=1000),
),
"1000ms",
),
labeled(
spins.Pulse(
color=ft.Colors.BLUE,
size=50,
duration=ft.Duration(milliseconds=2000),
),
"2000ms",
),
labeled(
spins.Pulse(
color=ft.Colors.BLUE,
size=50,
duration=ft.Duration(milliseconds=4000),
),
"4000ms",
),
],
),
ft.Divider(height=8),
# Wave — wave_type
section(
"Wave · wave_type",
[
labeled(
spins.Wave(
color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.START
),
"START",
),
labeled(
spins.Wave(
color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.CENTER
),
"CENTER",
),
labeled(
spins.Wave(
color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.END
),
"END",
),
],
),
ft.Divider(height=8),
# Wave — item_count
section(
"Wave · item_count",
[
labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=3), "3"),
labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=5), "5"),
labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=7), "7"),
labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=10), "10"),
],
),
ft.Divider(height=8),
# Ring — line_width
section(
"Ring · line_width",
[
labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=2), "2"),
labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=5), "5"),
labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=8), "8"),
labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=12), "12"),
],
),
ft.Divider(height=8),
# DualRing — line_width
section(
"DualRing · line_width",
[
labeled(
spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=2), "2"
),
labeled(
spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=5), "5"
),
labeled(
spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=8), "8"
),
labeled(
spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=12), "12"
),
],
),
ft.Divider(height=8),
# Ripple — border_width
section(
"Ripple · border_width",
[
labeled(
spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=2), "2"
),
labeled(
spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=4), "4"
),
labeled(
spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=8), "8"
),
labeled(
spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=14), "14"
),
],
),
ft.Divider(height=8),
# SpinningLines — line_width
section(
"SpinningLines · line_width",
[
labeled(
spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=1),
"1",
),
labeled(
spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=2),
"2",
),
labeled(
spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=4),
"4",
),
labeled(
spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=6),
"6",
),
],
),
ft.Divider(height=8),
# PianoWave — item_count
section(
"PianoWave · item_count",
[
labeled(
spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=3), "3"
),
labeled(
spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=5), "5"
),
labeled(
spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=8), "8"
),
labeled(
spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=12), "12"
),
],
),
)


if __name__ == "__main__":
ft.run(main)

Available controls