Focus outline for interactive widgets

Draw a consistent, animated focus outline around any interactive widget.

Providing a uniform focus indication can be surprisingly hard in real apps: default focus highlights can be clipped by layout, covered by other widgets, or look inconsistent across components. This package draws the focus outline in an Overlay, helping you keep a consistent design and improve UX while working toward accessibility guidelines (e.g. WCAG/BITV) that require visible keyboard focus.

Focus outline demo

Features

  • Draws a focus outline for a widget when it (or a descendant) is focused
  • Works across different focusable widgets (buttons, fields, custom widgets)
  • Multiple stroke styles: solid, dashed, dotted
  • Optional bordered stroke (inner color + outer border color)
  • Built-in animations, including configurable stroke reveal
  • Implemented via Overlay + CompositedTransformFollower to avoid clipping

Getting started

Add the dependency:

dependencies:
  focus_outline: ^0.1.0

Minimum supported Flutter SDK is >=3.10.0 (see pubspec.yaml).

Usage

Wrap any focusable widget:

import 'package:flutter/material.dart';
import 'package:focus_outline/focus_outline.dart';

class Example extends StatelessWidget {
  const Example({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: FocusOutline(
        strokeWidth: 3,
        child: OutlinedButton(
          onPressed: () {},
          child: const Text('Focusable'),
        ),
      ),
    );
  }
}

Stroke styles

FocusOutline(
  strokePattern: FocusOutlineStrokePattern.dashed,
  dashLength: 14,
  dashGap: 10,
  child: const TextField(),
);
FocusOutline(
  strokePattern: FocusOutlineStrokePattern.dotted,
  strokeCap: StrokeCap.round,
  dashGap: 10,
  child: const TextField(),
);

Bordered outline (stroke + border)

FocusOutline(
  color: Colors.blue,
  strokeWidth: 3,
  strokeBorderColor: Colors.black,
  strokeBorderWidth: 2,
  child: const TextField(),
);

Animations

By default, FocusOutline uses FocusOutlineAnimation.none (no animation).

FocusOutline(
  duration: const Duration(milliseconds: 300),
  animationBuilder: FocusOutlineAnimation.fadeScale,
  child: const TextField(),
);

Stroke reveal

FocusOutline(
  duration: const Duration(milliseconds: 300),
  animationBuilder: FocusOutlineAnimation.strokeReveal(
    start: FocusOutlineStrokeStart.topCenter,
    type: FocusOutlineStrokeType.bidirectional,
  ),
  child: const TextField(),
);

Accessibility notes

Ensure the outline color has sufficient contrast against the background.

Contributing

Contributions are welcome. Please open an issue or a pull request.

License

MIT. See LICENSE.

Libraries

focus_outline
A Flutter widget that draws a consistent, animated focus outline.
testing
Test-only utilities for focus_outline.