willink_theme 1.5.0 copy "willink_theme: ^1.5.0" to clipboard
willink_theme: ^1.5.0 copied to clipboard

i-Willink Design System theme for Flutter — Material 3 ThemeData factories on a single-brand baseline, consumer-overridable via ColorScheme copyWith.

willink_theme #

Material 3 theme for i-Willink Design System Flutter apps — ThemeData factory, spacing / token constants, and 9 brand-aware components on a single-brand baseline. The Flutter counterpart of @willink-labs/react / @willink-labs/tailwind-preset.

Quick start #

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

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      theme: WillinkTheme.willink(), // light baseline (since 0.5.0)
      home: const HomeScreen(),
    );
  }
}

Dark mode #

Since 1.5.0 the DS ships WillinkTheme.willinkDark() — the semantic flip of the light baseline per ADR-0013 (surfaces flip to the dark neutral ladder; brand identity stays the same violet, exactly like the web preset under data-theme="dark"). Wire it up the standard Material way and the OS preference drives the switch:

MaterialApp(
  theme: WillinkTheme.willink(),
  darkTheme: WillinkTheme.willinkDark(),
  themeMode: ThemeMode.system,
)

All 9 components read Theme.of(context).colorScheme, so they follow the active mode automatically — no component carries dark-specific styles.

Customizing the brand color #

The DS ships the i-Willink violet (#7C3AED) baseline. Consumers re-brand via standard Material 3 copyWith — every component reads colors from Theme.of(context).colorScheme, so overrides flow through automatically (the Flutter equivalent of the CSS --color-brand :root override on the npm side):

final theme = WillinkTheme.willink().copyWith(
  colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF2563EB)),
);

Components (9) #

Component Mirrors (React DS) Shape
WillinkButton Button variants (WillinkButtonVariant) × sizes (WillinkButtonSize)
WillinkEmptyState icon + message + optional CTA
WillinkErrorState error message + retry
WillinkLoadingState full-area loading state (centered spinner + caption)
WillinkSectionCard Card section container
WillinkTabBar Tabs PreferredSizeWidget, slots into AppBar.bottom
WillinkBottomSheet Sheet (side="bottom") WillinkBottomSheet.show<T>() + title/child scaffold
WillinkSnackBar Toast WillinkSnackBar.show() with info / success / error variants
WillinkProgressIndicator Progress determinate (value 0.0–1.0) / indeterminate (null)
// TabBar — inside an AppBar
appBar: AppBar(
  bottom: const WillinkTabBar(
    tabs: [Tab(text: 'アカウント'), Tab(text: 'パスワード')],
  ),
),

// BottomSheet
final applied = await WillinkBottomSheet.show<bool>(
  context,
  builder: (context) => WillinkBottomSheet(
    title: 'フィルター',
    child: const FilterForm(),
  ),
);

// SnackBar
WillinkSnackBar.show(
  context,
  message: '保存しました',
  variant: WillinkSnackBarVariant.success,
);

// Progress
WillinkProgressIndicator(value: 0.65)

Spacing #

Material 3 4-multiple scale. Use these everywhere you'd otherwise hard-code a double for padding / gap / margin:

Padding(padding: EdgeInsets.all(WillinkSpacing.md), child: ...)
SizedBox(height: WillinkSpacing.lg)
Token dp Typical use
WillinkSpacing.xs 4 icon ↔ label gap, dense rows
WillinkSpacing.sm 8 chip gaps, compact layouts
WillinkSpacing.md 16 default content padding
WillinkSpacing.lg 24 section separator
WillinkSpacing.xl 32 between page-level sections
WillinkSpacing.xxl 48 hero blocks, top-of-page padding

Brand tokens beyond Material #

Tokens that don't fit Material's palette (glow color, gradient presets, soft shadows) ride a ThemeExtension:

final tokens = Theme.of(context).extension<WillinkBrandTokens>()!;
Container(decoration: BoxDecoration(gradient: tokens.brandGradient));  // hero
Container(decoration: BoxDecoration(gradient: tokens.subtleGradient)); // bg
Container(decoration: BoxDecoration(gradient: tokens.aiGradient));     // AI moments

Token sync #

WillinkPrimitives.* constants must match @willink-labs/tokens/src/primitive.json. Verified by test/tokens_sync_test.dart — CI fails if a hex value drifts.

This is the same "single source of truth" guarantee that vitest's check-tokens.test.ts enforces on the React side. Both languages share one canonical DTCG JSON.

Versioning #

Strict SemVer 2.0 since 1.0.0. willink_theme versions independently of the @willink-labs/* npm packages — see ADR-0011. Pin ^1.0.0 and trust MINOR / PATCH per ADR-0010.

License #

MIT License — see LICENSE for details.

0
likes
150
points
285
downloads

Documentation

Documentation
API reference

Publisher

verified publisheri-willink.com

Weekly Downloads

i-Willink Design System theme for Flutter — Material 3 ThemeData factories on a single-brand baseline, consumer-overridable via ColorScheme copyWith.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

flutter

More

Packages that depend on willink_theme