flutter_tooth_chart

A beautiful customizable 3D tooth chart widget for Flutter apps. Top-down occlusal view of the full human dental arch — 32 permanent teeth or 20 primary teeth — with animated highlight support, gum background, and per-tooth completed / active states.

Extracted from the smart-mirror project's brushing UI. Pure Flutter framework, no other dependencies, single CustomPainter — dropped into any app in ~10 lines of code.

Features

  • 32 permanent teeth (adult) or 20 primary teeth (child), FDI World Dental Federation numbering
  • 3D-lit occlusal surfaces (shadow + fill gradient + top highlight + subtle border) per tooth
  • Animated breathing glow on the currently-brushed tooth
  • Mint-green tint + soft glow on completed teeth (gold star in kids mode)
  • 4 tooth kinds with distinct occlusal drawing routines: incisor edge line, canine centre cusp, premolar 2-cusp + median groove, molar 4-cusp + cross fissure
  • 3 shipped colour presets (dark, light, kids) and full ToothChartPalette customisation
  • No assets — everything drawn with CustomPainter
  • No dependencies beyond flutter

Quick start

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

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

  @override
  Widget build(BuildContext context) {
    return const ToothArchWidget(
      mode: ToothChartMode.adult,
      completedFdis: {18, 17, 16, 15, 14, 13, 12, 11},
      currentFdi: 21,
    );
  }
}

Usage examples

1. Adult chart, brushing in-progress

ToothArchWidget(
  mode: ToothChartMode.adult,
  completedFdis: const {18, 17, 16, 15, 14},
  currentFdi: 13,
)

2. Kids mode with custom palette

ToothArchWidget(
  mode: ToothChartMode.child,
  completedFdis: const {55, 54, 53, 52, 51},
  currentFdi: 61,
  palette: ToothChartPalette.kids,
)

3. Fully custom colours

ToothArchWidget(
  mode: ToothChartMode.adult,
  currentFdi: 26,
  palette: ToothChartPalette(
    backgroundCenter: Color(0xFF102030),
    backgroundEdge:   Color(0xFF08111C),
    gumGlow:          Color(0x14FFFFFF),
    archOutline:      Color(0x0DFFFFFF),
    lipLine:          Color(0x33FFFFFF),
    archLabel:        Color(0x66FFFFFF),
    toothBase:        Color(0xFFF5EDD8),
    toothActive:      Color(0xFF00E5FF),
    toothActiveHighlight: Color(0xFF80F5FF),
    toothCompletedBorder: Color(0xB300E676),
    toothCompletedTint:   Color(0x5500E676),
    toothCompletedGlow:   Color(0x3800E676),
    activeGlow:           Color(0xFF00E5FF),
    starColor:            Color(0x00000000),
  ),
)

API reference

ToothArchWidget

Parameter Type Default Purpose
mode ToothChartMode ToothChartMode.adult adult (32) or child (20)
completedFdis Set<int> {} Teeth rendered with mint tint + glow
currentFdi int? null Tooth rendered with pulsing glow (or null)
currentSectorFdis Set<int> {} Reserved for future "same-sector neighbours" styling
palette ToothChartPalette? ToothChartPalette.dark Colour theme
onToothTap void Function(int)? null Reserved — per-tooth hit-testing not yet implemented
showGumBackground bool true Whether to paint the dark radial background + gum glow
showArchLabels bool true Whether to paint upperLabel/lowerLabel
upperLabel String 'Upper' Text above the upper arch
lowerLabel String 'Lower' Text below the lower arch
showActiveFdiLabel bool true Whether to print the FDI number above the active tooth
breathPeriod Duration 1600 ms Duration of one half-breath of the active glow

ToothChartPalette

Three presets:

  • ToothChartPalette.dark — the original smart-mirror reference (dark blue-grey background, ivory teeth, cyan-blue active glow, mint completed tint). Visual-frozen; do not change.
  • ToothChartPalette.light — bright variant for daytime UIs.
  • ToothChartPalette.kids — soft pink/yellow, gold stars over completed teeth.

All 14 colour slots can be overridden via const ToothChartPalette(...) — see Example 3 above.

ToothKind, ToothSpec

Exported for advanced use only — the built-in painter constructs its own tooth list from internal coordinate tables. Consumers that want to build a custom painter can drive it from ToothSpec values.

Layout

The widget lays out to a self-computed size (~ min(400, parent - 32) wide, aspect ratio ~0.78). Place it inside an Expanded or a fixed-size box.

Not-yet-implemented

  • onToothTap — hit-testing per tooth requires either splitting into one CustomPaint per tooth or a manual hit-test path lookup. Reserved in the API for stability.
  • Per-tooth progress values (e.g. gradual fill).
  • Semantic labels for accessibility.

Contributions welcome.

License

MIT. See LICENSE.

Libraries

flutter_tooth_chart
A beautiful customizable 3D tooth chart widget for Flutter apps.