first commit

This commit is contained in:
2026-08-11 13:16:33 +05:30
parent 18531bf46b
commit c8350563d9
388 changed files with 69656 additions and 0 deletions

View File

@@ -0,0 +1,171 @@
import 'package:flutter/material.dart';
/// Miler Professional Design System Constants
/// Centralized design tokens for spacing, radius, shadows, and layout
/// ─────────────────────────────────────────────────────────────────────────
/// SHARED RADII AND ELEVATION
///
/// ── Why this used to be much bigger ──
///
/// This class shipped 43 members: a nine-step spacing scale, eleven `EdgeInsets`
/// presets, six radii, five shadows, a `cardDecoration` helper and three named
/// border radii. An audit found **six of them used, 17 times in total.** The
/// spacing scale had never been referenced once; every screen writes `16.w` or
/// `12.h` inline, which is both more readable at the call site and correct for
/// this app, because those need ScreenUtil's per-device scaling and a `const
/// double` cannot have it.
///
/// The 37 dead members were not harmless. A token nobody uses still has to be
/// read, still looks authoritative, and is the reason someone reaches for
/// `Colors.grey.shade100` instead — a design system that is mostly aspirational
/// teaches people to ignore it. So the unused members are gone and what is left
/// is only what the app actually reaches for.
///
/// The audit metric that flagged this file was itself misleading, which is worth
/// recording: 13 files import `design_constants.dart` and only 5 mention
/// `DesignConstants`. The other 8 import it for [ButtonSizes], which lives in
/// this same file and is used 72 times. Colocating a thriving class with a dead
/// one hid both facts.
///
/// **Adding to this class:** don't, until a second call site needs the value.
/// Two uses make a token; one use is a local constant.
/// ─────────────────────────────────────────────────────────────────────────
class DesignConstants {
DesignConstants._();
// ── Motion ────────────────────────────────────────────────────────────
//
// The app was using 35 distinct durations. No shared vocabulary means every
// transition is a fresh guess, and some of the guesses sat directly in the
// rider's path between two stops — an 800ms entrance and several 500ms
// cross-fades on screens he passes through 40 times a shift.
//
// Motion on a driver app is a tax paid all day. It earns its place only when
// it explains a state change; anything else is time spent standing still.
/// Press and release. Fast enough to feel like the surface responded rather
/// than animated.
static const Duration motionPress = Duration(milliseconds: 120);
/// A state change in place: a chip selecting, a tick landing, a row opening.
static const Duration motionState = Duration(milliseconds: 200);
/// A page or a sheet arriving. The ceiling for anything on the critical path.
static const Duration motionPage = Duration(milliseconds: 300);
/// Celebration, and only celebration — once per completed route, never on a
/// screen the rider is trying to get through.
static const Duration motionCelebrate = Duration(milliseconds: 600);
// ── Border radius ─────────────────────────────────────────────────────
//
// ── Three, because 26 communicated nothing ──
//
// An audit counted 26 distinct radii in use against the four declared here,
// and found the most common value in the app was 14 — `ButtonSizes.radius`,
// a *button* token, being applied to cards and sheets. Radius is one of the
// strongest cues that two things belong to the same family; at 26 values it
// says nothing, and two elements side by side at 12 and 14 read as a
// rendering bug rather than a decision.
//
// `radius2xl` (20) is retired: it was the third-most-used value and had no
// job the container radius could not do.
/// **Inner** — inputs, chips, small tiles, panels *inside* a container.
static const double radiusLg = 12.0;
/// **Container** — cards, sheets, and anything that is a surface in its own
/// right. Buttons use this too, so a button and the card it sits on agree.
static const double radiusXl = 16.0;
/// **Pill** — fully rounded: pills, circular tracks, avatars.
static const double radiusFull = 999.0;
// ── Elevation ─────────────────────────────────────────────────────────
//
// Only two survive, and both are used sparingly. Most cards in the app are
// now borderless fills with no shadow at all — see
// `ColorConstants.cardSurface` — so elevation is the exception, not the
// default it once was.
/// A card lifted just off the page.
static const List<BoxShadow> shadowSm = [
BoxShadow(color: Color(0x1A000000), blurRadius: 4, offset: Offset(0, 2)),
];
/// Something floating over content: a menu, a dragged element.
static const List<BoxShadow> shadowLg = [
BoxShadow(color: Color(0x2A000000), blurRadius: 12, offset: Offset(0, 8)),
];
}
/// ─────────────────────────────────────────────────────────────────────────
/// BUTTON SIZING — one scale for the whole app.
///
/// Buttons had drifted to a dozen different heights (44, 48, 52, 54, 56, 58)
/// across the pickup flow, Home, auth and the sheets. On a screen the rider
/// uses 30–50 times a day that reads as sloppiness, and worse, it breaks the
/// muscle memory that lets him hit a control without looking: if "the green
/// one at the bottom" is a different size on every screen, he has to aim.
///
/// Three sizes, and only three. Every button in the app must pick one.
/// ─────────────────────────────────────────────────────────────────────────
class ButtonSizes {
ButtonSizes._();
/// **Primary** — the one action a screen exists for. Full-width CTAs:
/// Accept Trip, Start Pickup, Confirm, Navigate.
static const double primary = 56.0;
/// **Secondary** — supporting actions that sit beside or below a primary:
/// Reject, Skip, Details, filter chips with a tap target.
static const double secondary = 48.0;
/// **Compact** — dense rows where several actions share a line, e.g. the
/// per-stop Accept/Reject pair inside a trip card. Still above the 44dp
/// accessibility floor.
static const double compact = 44.0;
/// Square icon-only buttons (call, overflow) match [primary] so they line up
/// with the CTA they sit next to.
static const double icon = 56.0;
/// Corner radius, shared by every button size so they read as one family.
///
/// 14 → 16 so it matches [DesignConstants.radiusXl]. At 14 a button sitting
/// on a 16pt card had a visibly tighter corner than the card holding it,
/// which is the kind of two-point difference nobody can name and everybody
/// sees.
static const double radius = DesignConstants.radiusXl;
/// Absolute floor for any tappable target, per accessibility guidance.
static const double minTapTarget = 44.0;
}
/// ─────────────────────────────────────────────────────────────────────────
/// DESIGN TRIAL — full addresses on stop cards
///
/// Turn on to see every stop card carrying its **complete** address rather than
/// the trimmed one, over [kFullAddressMaxLines] lines instead of two.
///
/// Two separate things are suppressed normally, and both are lifted together
/// here or the trial would not show what it claims to:
///
/// • **Home shortens the text.** `Trip.shortAddress` strips the tail every stop
/// on the route shares — the city, the state, the pincode — because repeating
/// "Coimbatore, Tamil Nadu 641006" on all six stops tells the rider nothing
/// about which one he is looking at. With the trial on, the raw address is
/// used instead. Bookings already shows the raw value.
///
/// • **Both screens cap the lines.** Two, so a card's height does not depend on
/// how verbose a customer was — a list of cards that step unevenly down the
/// screen is harder to scan and fits fewer stops.
///
/// Both caps exist for measured reasons, so this is a switch rather than a
/// deletion. **Set to `false` to restore the shipped behaviour.**
const bool kFullAddressTrial = true;
/// Line cap while [kFullAddressTrial] is on. Four fits a full Indian address at
/// 13sp in a stop card's column without letting one pathological record run the
/// card off the screen.
const int kFullAddressMaxLines = 4;