Files
doormile_milderapp/lib/views/helpers/constants/Font_constant.dart
Thiru-tenext d7348e253f Miler rider app: surface system, visible design language, backend lifecycle
Design system
- MilerSurface ladder (canvas → working → raised → floating) with MilerPanel
  as layer 1; canvas moved to #DEE3EA so white separates at 1.290:1.
- Visible vocabulary applied across Home, Deliveries, Activity, Account and
  the sheets: hero heads (tabular numeral + small caption, clamped at 1.3x),
  canvas wells for anything that opens, small filled tags for shelf labels,
  demoted placeholders. Recorded in DESIGN_SYSTEM.md §6.
- One icon family: 222 Material glyphs migrated to Lucide; none left outside
  lib/xpress.
- Colour semantics corrected: amber only for what is genuinely owed, brand red
  reserved for the live stop, disabled primaries go neutral rather than pale.

Data and lifecycle
- lib/data/lifecycle.dart reads mutations for what they prove; route_order.dart
  makes admin sequence the single ordering authority; service_day.dart, and
  stop_area.dart rewritten against live Coimbatore addresses (digit-token
  stripping, city stoplist, street suffixes, stammer collapse).
- countLabel states the load once, in bags.

Testing
- 1440 tests passing; golden shot harnesses for Home, Deliveries, Activity,
  sheets and verify, with test/failures/ now gitignored (diff debris).
- New pins: home_gutter_test, stop_area_test, plus updated structural bounds.

Note: this commit also carries pre-existing working-tree deletions that were
present before this work (API_SPEC.md, README.md, demo test fixtures).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 05:40:35 +05:30

169 lines
5.7 KiB
Dart

import 'package:flutter/material.dart';
class FontConstants {
/// ── The app's typeface ──
///
/// Poppins: geometric, OFL-licensed, and the one every screen now reads from.
/// It replaced Manrope, which was itself a stand-in for Uber Move.
///
/// **Read this before changing it.** The family was already declared in
/// `pubspec.yaml` as `poppins`, with a lowercase path on every one of its
/// seven assets, while the files on disk are `assets/fonts/Poppins/Poppins-*`.
/// Asset bundling is case-sensitive on both platforms, so not one of them
/// resolved: anything asking for the family fell back to Roboto and no error
/// was raised anywhere. The declaration is fixed and all seven static weights
/// are registered — Poppins ships as separate files rather than a variable
/// font, and without explicit 800/900 entries Flutter synthesises them by
/// smearing SemiBold, which is what makes a heading look muddy at exactly the
/// size it is meant to be read from.
/// ── The weight scale is calibrated for THIS family ──
///
/// Poppins runs optically heavier than Manrope at every grade: it is
/// geometric, its bowls are wide and its stems thick, so `w800` here is far
/// darker on the page than `w800` was in a variable Manrope. The whole scale
/// was tuned against Manrope and came across a grade too heavy — headings
/// read as shouting and body copy as bold.
///
/// Every weight in `lib/` (outside `lib/xpress`, which is Proxima Nova) was
/// stepped down one grade: 900→800, 800→700, 700→600, 600→500. The *relative*
/// hierarchy is untouched — each level is still one step from its neighbour —
/// so nothing lost its rank; the whole run just sits where it should for this
/// typeface.
///
/// **If the family changes again, re-tune this.** A weight is a number, not a
/// design: what it looks like belongs to the font.
static const String fontFamily = 'Poppins';
/// Only ever reached for a glyph Poppins does not carry. Manrope covers the
/// Latin and currency sets the app uses, so this is a safety net rather than
/// a second typeface in the design.
static String fontFamilyFallback = 'Manrope';
// Typography scale
static const double displayLg = 32.0;
static const double headlineMd = 24.0;
static const double headlineSm = 20.0;
static const double bodyLg = 18.0;
static const double bodyMd = 16.0;
static const double labelBold = 14.0;
static const double labelSm = 12.0;
static TextStyle displayLgStyle = const TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
letterSpacing: -0.64,
fontFamily: fontFamily,
);
static TextStyle headlineMdStyle = const TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
letterSpacing: -0.24,
fontFamily: fontFamily,
);
static TextStyle headlineSmStyle = const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
letterSpacing: -0.2,
fontFamily: fontFamily,
);
static TextStyle bodyLgStyle = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
fontFamily: fontFamily,
);
static TextStyle bodyMdStyle = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
fontFamily: fontFamily,
);
static TextStyle labelBoldStyle = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: fontFamily,
);
static TextStyle labelSmStyle = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
fontFamily: fontFamily,
);
static double getResponsiveFontSize(BuildContext context, double baseSize) {
return baseSize;
}
static double extraSmall(BuildContext context) =>
getResponsiveFontSize(context, 10);
static double small(BuildContext context) =>
getResponsiveFontSize(context, labelSm);
static double medium(BuildContext context) =>
getResponsiveFontSize(context, bodyMd);
static double regular(BuildContext context) =>
getResponsiveFontSize(context, bodyLg);
static double large(BuildContext context) =>
getResponsiveFontSize(context, headlineSm);
static double xLarge(BuildContext context) =>
getResponsiveFontSize(context, headlineMd);
static double xxLarge(BuildContext context) =>
getResponsiveFontSize(context, 28);
static double xxxLarge(BuildContext context) =>
getResponsiveFontSize(context, 30);
static double huge(BuildContext context) =>
getResponsiveFontSize(context, displayLg);
}
class ReusableTextWidget extends StatelessWidget {
final String text;
final double? fontSize;
final double? textHeight;
final String? fontFamily;
final FontWeight? fontWeight;
final FontStyle? fontStyle;
final Color? color;
final TextAlign? textAlign;
final int? maxLines;
final TextDecoration? isUnderText;
const ReusableTextWidget({
super.key,
required this.text,
this.fontSize,
this.textHeight,
this.fontFamily,
this.fontWeight,
this.fontStyle,
this.color,
this.textAlign,
this.maxLines,
this.isUnderText,
});
@override
Widget build(BuildContext context) {
return Text(
text,
softWrap: true,
style: TextStyle(
fontSize: fontSize ?? FontConstants.medium(context),
decoration: isUnderText,
fontFamily: fontFamily ?? FontConstants.fontFamily,
decorationColor: color,
fontWeight: fontWeight ?? FontWeight.normal,
fontStyle: fontStyle ?? FontStyle.normal,
color: color ?? Colors.grey.shade900,
overflow: TextOverflow.ellipsis,
decorationStyle: TextDecorationStyle.solid,
decorationThickness: 1,
height: textHeight,
),
maxLines: maxLines,
textAlign: textAlign ?? TextAlign.start,
);
}
}