154 lines
4.8 KiB
Dart
154 lines
4.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class FontConstants {
|
|
/// ── The app's typeface ──
|
|
///
|
|
/// Manrope: a free, OFL-licensed geometric sans, bundled as a single
|
|
/// variable font (`assets/fonts/Manrope/Manrope-VF.ttf`) and chosen as the
|
|
/// closest legal stand-in for Uber Move, which is proprietary.
|
|
///
|
|
/// **Poppins was tried here and reverted.** It is declared in `pubspec.yaml`
|
|
/// and its seven static weights do resolve, so it is one string away if it is
|
|
/// ever wanted again — but it runs optically far heavier than Manrope at
|
|
/// every grade: geometric, wide bowls, thick stems. Swapping the family
|
|
/// alone turned the whole app bold, headings especially, and stepping the
|
|
/// weight scale down a grade to compensate was not enough to undo it.
|
|
///
|
|
/// **The weight scale below is calibrated for THIS family.** If the family
|
|
/// changes again, re-tune it — a weight is a number, not a design; what it
|
|
/// looks like belongs to the font.
|
|
static const String fontFamily = 'Manrope';
|
|
|
|
/// Only ever reached for a glyph Manrope 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 = 'PlusJakartaSans';
|
|
|
|
// 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.w700,
|
|
letterSpacing: -0.64,
|
|
fontFamily: fontFamily,
|
|
);
|
|
|
|
static TextStyle headlineMdStyle = const TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.w700,
|
|
letterSpacing: -0.24,
|
|
fontFamily: fontFamily,
|
|
);
|
|
|
|
static TextStyle headlineSmStyle = const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.w600,
|
|
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.w700,
|
|
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,
|
|
);
|
|
}
|
|
}
|