neon_timeline_flutter 3.4.3 copy "neon_timeline_flutter: ^3.4.3" to clipboard
neon_timeline_flutter: ^3.4.3 copied to clipboard

Production-ready Flutter timelines and schedules with neon rendering, drag-to-reschedule, overlap logic, slidable actions, slivers, and accessibility.

Neon Timeline Flutter #

Neon Timeline Showcase

Production-ready Flutter timelines and planner schedules with animated neon rendering, slivers, drag-to-reschedule, overlap detection, current-time markers, and polished slide actions.

Screenshots #

These previews mirror the package assets and use GitHub raw URLs so they also render on pub.dev.

Schedule showcase in the spectral theme Schedule showcase in the omniverse theme
Schedule showcase in the Hyperion theme Holographic theme showcase
Aurora theme showcase Solar flare theme showcase
Cryogenic theme showcase Custom seeded theme showcase
Light theme showcase Midnight theme showcase
Neon theme showcase Neural Aurora showcase
Neural Ember showcase Ember showcase
Void pulses showcase Quantum showcase

The package has two independent layers:

  1. NeonTimeline, NeonFixedTimeline, and NeonSliverTimeline for generic status timelines.
  2. NeonScheduleTimeline<T> for planner and calendar applications.

Your application owns its models, state management, persistence, localization, and business rules. The package only renders and reports user intent through callbacks.

Features #

  • Vertical and horizontal generic timelines.
  • Start, center, end, alternating, and adaptive layouts.
  • Box, fixed, and sliver APIs.
  • Pending, active, completed, error, and disabled states.
  • Advanced indicator, connector, and card painters.
  • Shared sampled motion clock, scroll pausing, and reduced-motion support.
  • Planner-grade lazy NeonScheduleTimeline<T>.
  • Automatic sorting, duration sizing, gap rendering, and overlap detection.
  • Long-press drag-to-reschedule with configurable minute snapping.
  • Day-boundary clamping, haptic feedback, and edge auto-scroll.
  • Current-time marker and automatic current-entry activation.
  • flutter_slidable facade with package-owned actions and optional full-swipe dismissal.
  • Previous/next-day swipe wrapper.
  • Keyboard, pointer, semantics, and right-to-left support.
  • No dependency on Bloc, Provider, Firebase, Hive, or an application model.

Requirements #

  • Dart >=3.4.0 <4.0.0
  • Flutter >=3.22.0
  • flutter_slidable >=3.1.2 <4.0.0

The slidable range intentionally matches applications already using flutter_slidable: ^3.1.2.

Installation #

After publication:

flutter pub add neon_timeline_flutter

Before publication, use a path dependency:

dependencies:
  neon_timeline_flutter:
    path: ../neon_timeline_flutter

Import the complete public API:

import 'package:neon_timeline_flutter/neon_timeline_flutter.dart';

Or keep a web/application build focused by importing only the layer you use:

import 'package:neon_timeline_flutter/core.dart';
import 'package:neon_timeline_flutter/advanced.dart';
import 'package:neon_timeline_flutter/slidable.dart';

The original all-in-one import remains supported.

Production performance policy #

Version 3.4 defaults planner timelines to an adaptive rendering budget. It does not replace the UI: layout, colors, borders, cards, indicators, connectors, semantics, drag, and slide behavior stay the same. It limits only continuous work.

NeonScheduleTimeline<Task>(
  entries: entries,
  selectedDate: selectedDate,
  dataRevision: state.revision,
  performance: const NeonTimelinePerformanceConfig.adaptive(),
  itemBuilder: buildTask,
)

Available policies:

const NeonTimelinePerformanceConfig.adaptive();
const NeonTimelinePerformanceConfig.batterySaver();
const NeonTimelinePerformanceConfig.balanced();
const NeonTimelinePerformanceConfig.highQuality();

The adaptive policy:

  • starts motion after first paint rather than competing with startup;
  • uses one shared sampled clock;
  • pauses during scrolling, inactive lifecycle, inactive routes, disabled TickerMode, and reduced-motion preferences;
  • keeps at most one focal schedule row moving by default;
  • avoids large backdrop filters on web and dense lists;
  • reduces particle detail without changing geometry or colors;
  • keeps offscreen list children lazy.

For a very large generic builder timeline, provide the active indexes directly so the package does not scan every status just to locate the animated row:

NeonTimeline.builder(
  itemCount: events.length,
  animatedItemIndexes: <int>[activeIndex],
  performance: const NeonTimelinePerformanceConfig.adaptive(),
  statusBuilder: (index) => events[index].status,
  contentBuilder: buildEvent,
)

Use highQuality() only for a short hero/showcase surface after profiling the slowest supported device. It is deliberately not the production default.

Planner schedule quick start #

Map your own model into NeonScheduleEntry<T>:

final entries = tasks.map((task) {
  return NeonScheduleEntry<Task>(
    id: task.id,
    value: task,
    start: task.startTime,
    duration: Duration(minutes: task.duration ?? 30),
    status: task.isCompleted
        ? NeonTimelineStatus.completed
        : NeonTimelineStatus.pending,
    color: task.color,
    semanticLabel: task.title,
    draggable: !task.isCalendarEvent,
  );
}).toList();

Render the schedule and keep all persistence in your application:

NeonScheduleTimeline<Task>(
  entries: entries,
  selectedDate: selectedDate,
  itemBuilder: (context, details) {
    final task = details.entry.value;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Text(task.title),
        Text('${details.displayDuration.inMinutes} min'),
      ],
    );
  },
  onEntryTap: (context, details) {
    openTask(details.entry.value);
  },
  onEntryMoved: (context, details, newStart) async {
    await repository.update(
      details.entry.value.copyWith(startTime: newStart),
    );
  },
)

What the schedule computes #

Each builder receives NeonScheduleEntryDetails<T> with:

  • normalized display start and duration;
  • previous and next entries;
  • free-time gaps;
  • previous and next overlap flags;
  • back-to-back flags;
  • current-entry state;
  • first and last positions.

This keeps scheduling geometry out of application widgets.

Slide actions #

NeonSlidableTimeline is backed by flutter_slidable, but the public action configuration belongs to this package:

NeonScheduleTimeline<Task>(
  entries: entries,
  selectedDate: selectedDate,
  itemBuilder: (context, details) => Text(details.entry.value.title),
  startActionsBuilder: (context, details) => [
    NeonTimelineAction(
      icon: Icons.calendar_month,
      label: 'PLAN',
      color: const Color(0xFF2980B9),
      onPressed: (_) => schedule(details.entry.value),
    ),
  ],
  endActionsBuilder: (context, details) => [
    NeonTimelineAction(
      icon: Icons.delete_outline,
      label: 'DELETE',
      color: const Color(0xFFE5485D),
      onPressed: (_) => delete(details.entry.value),
    ),
  ],
  onEntryEndDismissed: (context, details) async {
    await delete(details.entry.value);
  },
)

To keep an existing application-specific action layout, provide child while retaining the package surface, semantics, and gesture behavior:

NeonTimelineAction(
  icon: Icons.delete_outline,
  label: 'Delete',
  color: Colors.red,
  onPressed: (_) => delete(task),
  child: YourExistingSwipeActionContent(task: task),
)

When using full-swipe dismissal on NeonSlidableTimeline directly, pass a stable slidableKey (or key the child). NeonScheduleTimeline does this automatically from each entry id.

The action and full-swipe callbacks accept synchronous or asynchronous work. The package does not remove data automatically; your state update remains the source of truth.

Day swipe navigation #

NeonTimelineDayPager(
  selectedDate: selectedDate,
  onDateChanged: cubit.setSelectedDate,
  child: NeonScheduleTimeline<Task>(
    entries: entries,
    selectedDate: selectedDate,
    itemBuilder: buildTask,
  ),
)

Do not combine whole-page day swiping with a card action gesture unless the interaction is tested on real devices. Both use horizontal gestures. A common production choice is to keep day swiping on empty timeline space and slide actions on cards.

Generic status timeline #

NeonTimeline(
  padding: const EdgeInsets.all(16),
  theme: NeonTimelineThemeData.omniverse(),
  items: const [
    NeonTimelineItem(
      id: 'created',
      status: NeonTimelineStatus.completed,
      oppositeContent: Text('09:00'),
      content: NeonTimelineCard(child: Text('Created')),
    ),
    NeonTimelineItem(
      id: 'review',
      status: NeonTimelineStatus.active,
      oppositeContent: Text('10:30'),
      content: NeonTimelineCard(child: Text('Review')),
    ),
  ],
)

Use NeonTimeline.builder for dynamic lists and NeonSliverTimeline.builder inside CustomScrollView.

Schedule styling #

NeonTimelineThemeData controls color and painter effects. NeonScheduleTimelineStyle controls schedule geometry and gestures:

const style = NeonScheduleTimelineStyle(
  pixelsPerMinute: 1.35,
  snapMinutes: 5,
  minimumEntryExtent: 64,
  maximumEntryExtent: 260,
  cardVariant: NeonTimelineCardVariant.liquidCrystal,
  showGapLabels: true,
  keepEntriesInsideDay: true,
);

For dense lists, use a lighter card and render quality:

final theme = NeonTimelineThemeData.spectral().copyWith(
  indicatorStyle: const NeonTimelineIndicatorStyle(
    effect: NeonIndicatorEffect.glass,
    quality: NeonTimelineRenderQuality.balanced,
  ),
  connectorStyle: const NeonTimelineConnectorStyle(
    effect: NeonConnectorEffect.energy,
    quality: NeonTimelineRenderQuality.balanced,
  ),
);

Optional presentation components #

The package includes optional page-level widgets. They are not inserted around existing timelines automatically:

NeonTimelineSurface(
  child: Column(
    children: [
      const NeonTimelineHeader(
        title: 'Today',
        trailing: NeonTimelineBadge(label: 'Live'),
      ),
      Expanded(
        child: NeonScheduleTimeline<Task>(
          entries: entries,
          selectedDate: selectedDate,
          itemBuilder: buildTask,
        ),
      ),
    ],
  ),
)

NeonTimelineEmptyState provides a matching empty screen while still allowing a completely custom emptyBuilder.

Complete example #

The example/ application demonstrates the real public package API rather than copying private implementation code:

  • schedule timeline with overlap and free-time logic;
  • long-press drag and five-minute snapping;
  • start/end slide actions, async busy locking, full swipe, delete, and undo;
  • previous/next day paging and empty state;
  • lazy, fixed, horizontal, and sliver timelines;
  • every indicator, connector, and card renderer;
  • runtime themes, reduced motion, adaptive performance, and 500 lazy rows;
  • web contour-glow fallback and accessible web metadata.

Run it with:

cd example
flutter pub get
flutter run --profile

For Lighthouse, build and serve the release output rather than measuring flutter run debug mode:

flutter build web --release
cd build/web
python -m http.server 7357

Performance defaults #

The advanced appearance remains enabled, but continuous work is constrained:

  • schedule rows are built lazily near the viewport;
  • one 24 Hz sampled motion clock is shared by visible painters;
  • clocks sleep completely when no animated painter is listening;
  • decorative motion pauses while scrolling and when the app is inactive;
  • at most one current/active schedule row animates continuously by default;
  • standalone indicators and connectors use the same sampled clock rather than a display-refresh controller;
  • standalone advanced cards animate on interaction unless continuousAnimation: true is requested;
  • Gaussian painter blur is cached on native platforms and avoided on Web;
  • advanced backdrop filters share one grouped backdrop input;
  • drag and hover updates are snapped, coalesced, and throttled;
  • asynchronous slide actions are protected against duplicate submission.
NeonScheduleTimeline<Task>(
  entries: entries,
  selectedDate: selectedDate,
  motionFramesPerSecond: 24,
  pauseMotionWhileScrolling: true,
  animateOnlyCurrentEntry: true,
  maxAnimatedEntries: 1,
  addAutomaticKeepAlives: false,
  itemBuilder: buildTask,
)

For constrained hardware, keep the same painted card design but disable the backdrop sampling layer:

const NeonScheduleTimelineStyle(
  cardVariant: NeonTimelineCardVariant.liquidCrystal,
  useBackdropFilter: false,
  enableCardParallax: false,
)

See PERFORMANCE.md for production, battery, and hero profiles.

State-management integration #

The package is intentionally state-management agnostic. It works with Bloc, Cubit, Riverpod, Provider, ChangeNotifier, Redux, or local state because it only needs immutable input and callbacks.

A callback should update the application state. The rebuilt entry list then becomes the new visual state. The package never edits an entry object in place.

Accessibility and motion #

  • Entry semantics can be supplied through semanticLabel.
  • Disabled entries suppress interaction.
  • Active animation respects MediaQuery.disableAnimations.
  • Interactive indicators and cards support keyboard activation.
  • Logical start and end actions follow text direction.
  • Gap, conflict, current-time, and entry-time labels can be localized with builders.
  • Set motionEnabled: false for golden tests or battery-sensitive surfaces.

Publication #

Read PUBLISHING.md before uploading. At minimum run:

flutter pub get
flutter analyze
flutter test
flutter pub publish --dry-run

Publishing is permanent. Verify the package name, license ownership, repository metadata, the screenshot gallery, and the dry-run file list before the final command.

License #

MIT. See LICENSE.

1
likes
130
points
33
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Production-ready Flutter timelines and schedules with neon rendering, drag-to-reschedule, overlap logic, slidable actions, slivers, and accessibility.

Repository (GitHub)
View/report issues
Contributing

Topics

#timeline #schedule #animation #slidable #widget

License

MIT (license)

Dependencies

flutter, flutter_slidable

More

Packages that depend on neon_timeline_flutter