delft_ui 0.1.0
delft_ui: ^0.1.0 copied to clipboard
A porcelain design system for Flutter. White glaze, cobalt pigment, and a continuous relief scale where colour pools in the recesses.
// Copyright 2026 Siloé Bezerra Bispo
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
import 'package:delft_ui/delft_ui.dart';
import 'package:flutter/material.dart';
import 'gallery/gallery_shell.dart';
import 'tuning_panel.dart';
void main() => runApp(const GalleryApp());
/// The delft_ui gallery and calibration playground.
class GalleryApp extends StatefulWidget {
/// Creates the gallery.
const GalleryApp({super.key});
@override
State<GalleryApp> createState() => _GalleryAppState();
}
class _GalleryAppState extends State<GalleryApp> {
var _paletteIndex = 0;
var _brightness = Brightness.light;
var _glaze = GlazeTokens.porcelain;
DelftPalette get _palette => _brightness == Brightness.light
? delftPalettes[_paletteIndex].light
: delftPalettes[_paletteIndex].dark;
DelftThemeData get _theme => DelftThemeData(palette: _palette, glaze: _glaze);
@override
Widget build(BuildContext context) {
final controls = _ThemeControls(
paletteIndex: _paletteIndex,
brightness: _brightness,
onPaletteChanged: (value) => setState(() => _paletteIndex = value),
onBrightnessChanged: (value) => setState(() => _brightness = value),
);
return MaterialApp(
// On web this becomes the document title, overwriting the one in
// index.html, so it carries the full sentence rather than the package
// name.
title: 'delft_ui — a porcelain design system for Flutter',
debugShowCheckedModeBanner: false,
// The gallery chrome is plain Material on purpose. Dressing the
// instrument in the material it is measuring makes it impossible to tell
// which half of the screen is being evaluated.
theme: ThemeData(
brightness: _brightness,
colorSchemeSeed: _palette.accent.fill,
),
home: AnimatedDelftTheme(
data: _theme,
child: GalleryShell(
themeControls: controls,
calibrationPanel: TuningPanel(
glaze: _glaze,
onGlazeChanged: (value) => setState(() => _glaze = value),
),
),
),
);
}
}
/// Pigment and firing. Global, because both change every specimen at once.
class _ThemeControls extends StatelessWidget {
const _ThemeControls({
required this.paletteIndex,
required this.brightness,
required this.onPaletteChanged,
required this.onBrightnessChanged,
});
final int paletteIndex;
final Brightness brightness;
final ValueChanged<int> onPaletteChanged;
final ValueChanged<Brightness> onBrightnessChanged;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SegmentedButton<int>(
showSelectedIcon: false,
segments: [
for (var i = 0; i < delftPalettes.length; i++)
ButtonSegment(value: i, label: Text(delftPalettes[i].light.name)),
],
selected: {paletteIndex},
onSelectionChanged: (value) => onPaletteChanged(value.first),
),
const SizedBox(height: 6),
SegmentedButton<Brightness>(
showSelectedIcon: false,
segments: const [
ButtonSegment(value: Brightness.light, label: Text('Daylight')),
ButtonSegment(value: Brightness.dark, label: Text('Night')),
],
selected: {brightness},
onSelectionChanged: (value) => onBrightnessChanged(value.first),
),
],
);
}
}