reel_text 0.0.1 copy "reel_text: ^0.0.1" to clipboard
reel_text: ^0.0.1 copied to clipboard

A tactile Flutter text roll animation for tiny labels, counters, status text, and command buttons.

reel_text #

Dependency-light Flutter text roll animation for short labels, counters, status text, and command buttons.

reel_text brings the DOM text-roll idea from Danilaa1's original package to Flutter: every glyph gets its own measured slot, changed glyphs slide vertically, optional color flashes fade back to the inherited text color, and imperative flash() calls are safe for rapid button taps.

[reel_text showcase]

Live demo

Install #

dependencies:
  reel_text: ^0.0.1

Quick Start #

import 'package:reel_text/reel_text.dart';

const ReelText('Copy');

For the classic Copy -> Copied -> Copy interaction:

final controller = ReelTextController(initialText: 'Copy');

ReelText.controller(controller: controller);

controller.flash(
  'Copied',
  options: ReelTextFlashOptions(
    enter: ReelTextOptions(colorBuilder: chromatic()),
  ),
);

API #

Declarative #

ReelText(
  copied ? 'Copied' : 'Copy',
  options: ReelTextOptions(
    direction: copied ? ReelTextDirection.up : ReelTextDirection.down,
    colorBuilder: copied ? chromatic() : null,
  ),
);

Imperative #

final label = ReelTextController(initialText: 'Copy');

label.set('Copied');
label.set(
  'Copy',
  options: const ReelTextOptions(direction: ReelTextDirection.down),
);
label.flash('Copied');
label.dispose();

flash() captures the resting text on the first flash in a burst, resets the revert timer on repeated calls, and rolls back once after the last flash. Calling set() cancels a pending revert.

For async operations, use startProgress() and resolve the returned handle:

final exportLabel = ReelTextController(initialText: 'Export');

final progress = exportLabel.startProgress(
  'Exportaa',
  frames: const ['Exportee', 'Exportii', 'Exportoo'],
  interval: const Duration(milliseconds: 160),
  options: ReelTextOptions(colorBuilder: chromatic(from: 36, spread: 54)),
);

try {
  await exportFile();
  progress.complete(
    'Exported',
    options: const ReelTextOptions(color: Color(0xff38bdf8)),
  );
} catch (_) {
  progress.fail(
    'Error',
    options: const ReelTextOptions(color: Color(0xffe11d48)),
  );
}

The progress loop keeps rolling until the handle is completed, failed, or cancelled. Matching glyphs stay fixed by default, so Export -> Exportaa -> Exportee -> Exportii continuously animates the two uncertain suffix slots while waiting. complete('Exported') then performs the normal diff into the final word. Each emitted target accepts its own ReelTextOptions, so intermediate progress, success, and error states can use different color modes.

Waiting (idle) animations #

For the common case you don't need to invent frames: startWaiting() loops a designed idle animation until its handle is resolved.

final label = ReelTextController(initialText: 'Export');

final handle = label.startWaiting('Exporting');
try {
  await exportFile();
  handle.complete('Exported');
} catch (_) {
  handle.fail('Failed');
}

Pick the look with a ReelWaiting preset:

// Trailing dots: Exporting -> Exporting. -> Exporting.. -> Exporting...
label.startWaiting('Exporting', waiting: const ReelWaiting.ellipsis());

// The label stays readable and periodically "breathes": one stagger wave of
// self-rolls sweeps across the glyphs, then the word rests.
label.startWaiting(
  'Exporting',
  waiting: const ReelWaiting.wave(rest: Duration(milliseconds: 1200)),
);

// Explicit frames or a generator for full control (scrambles, spinners, ...).
label.startWaiting(
  'Exporting',
  waiting: ReelWaiting.builder((text, tick) => tick.isEven ? text : '$text…'),
);

All presets compile down to the same roll engine. Each preset ships with designed motion defaults — ellipsis ticks on a steady, metronome-like beat derived from the roll duration, and wave uses a calm, non-springy curve with almost no tilt so the loop reads as a ripple instead of a glitch. Pass your own ReelTextOptions to take full control of direction, curve, stagger, and color.

Reduced motion #

When the platform requests reduced motion (MediaQuery.disableAnimationsOf(context)), ReelText snaps to the target text instantly instead of rolling. Opt out per widget with respectDisableAnimations: false.

Dynamic fonts #

ReelText measures glyph slots from the active Flutter text layout. If your app loads fonts asynchronously, preload them before the first ReelText frame so initial slot widths are measured with the final font:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  GoogleFonts.archivoBlack();
  await GoogleFonts.pendingFonts();
  runApp(const App());
}

Options #

Option Default Description
direction ReelTextDirection.down Roll direction.
stagger 45ms Delay between glyph starts.
duration 300ms Per-glyph slide duration.
exitOffset 50ms Delay before incoming glyphs chase outgoing glyphs.
curve springy cubic Slide curve.
bounce 0.6 Per-glyph timing/tilt variation and settle-overshoot depth.
color null Flat incoming glyph tint.
colorBuilder null Per-glyph incoming tint, such as chromatic().
colorFade 280ms Tint fade-back duration.
skipUnchanged true Keeps identical same-index glyphs static.
interrupt true Interrupt in-flight rolls or queue the latest target.

Example #

Run the included example:

cd example
flutter run

The example is a two-page studio: Showcase is a designed demo of the hero roll, the three waiting presets, async operation handles, counters, and a motion desk; Recipes pairs live, working previews with copy-ready code for the most common situations (declarative swaps, flash() buttons, async handles, waiting presets, tabular counters, spam-safe buttons, and reduced motion).

14
likes
0
points
420
downloads

Publisher

verified publisherkicknext.dev

Weekly Downloads

A tactile Flutter text roll animation for tiny labels, counters, status text, and command buttons.

Homepage
Repository (GitHub)
View/report issues

Topics

#animation #text #widget #flutter

License

unknown (license)

Dependencies

flutter

More

Packages that depend on reel_text