Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docpilot_core/lib/docpilot_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ export 'src/validators/form_validators.dart';
// Theme utilities
export 'src/theme/theme_helper.dart';

export 'src/theme/text_style.dart';

200 changes: 200 additions & 0 deletions docpilot_core/lib/src/theme/text_style.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import 'package:flutter/material.dart';

/// DocPilot Text Styles
/// All text styles following the Figma design system
class DocPilotTextStyles {
// Private constructor to prevent instantiation
DocPilotTextStyles._();

// Font family
static const String _fontFamily = 'Inter';

// ==================== HEADING STYLES ====================

/// Heading 1 - Extra Bold / 24
/// Font weight: 800, Size: 24, Line height: 1.0 (100%)
static const TextStyle h1 = TextStyle(
fontFamily: _fontFamily,
fontSize: 24,
fontWeight: FontWeight.w800, // Extra Bold
height: 1.0, // 100% line height
letterSpacing: 0.24,
color: Color(0xFF1F1F1F),
);

/// Heading 2 - Extra Bold / 18
/// Font weight: 800, Size: 18, Line height: 1.0 (100%)
static const TextStyle h2 = TextStyle(
fontFamily: _fontFamily,
fontSize: 18,
fontWeight: FontWeight.w800, // Extra Bold
height: 1.0, // 100% line height
letterSpacing: 0.09,
color: Color(0xFF1F1F1F),
);

/// Heading 3 - Extra Bold / 16
/// Font weight: 800, Size: 16, Line height: 1.0 (100%)
static const TextStyle h3 = TextStyle(
fontFamily: _fontFamily,
fontSize: 16,
fontWeight: FontWeight.w800, // Extra Bold
height: 1.0, // 100% line height
letterSpacing: 0.08,
color: Color(0xFF1F1F1F),
);

/// Heading 4 - Bold / 14
/// Font weight: 700, Size: 14, Line height: 1.0 (100%)
static const TextStyle h4 = TextStyle(
fontFamily: _fontFamily,
fontSize: 14,
fontWeight: FontWeight.w700, // Bold
height: 1.0, // 100% line height
color: Color(0xFF1F1F1F),
);

/// Heading 5 - Bold / 12
/// Font weight: 700, Size: 12, Line height: 1.0 (100%)
static const TextStyle h5 = TextStyle(
fontFamily: _fontFamily,
fontSize: 12,
fontWeight: FontWeight.w700, // Bold
height: 1.0, // 100% line height
color: Color(0xFF1F1F1F),
);

// ==================== BODY STYLES ====================

/// Body XL - Regular / 18
/// Font weight: 400, Size: 18, Line height: 24
static const TextStyle bodyXL = TextStyle(
fontFamily: _fontFamily,
fontSize: 18,
fontWeight: FontWeight.w400, // Regular
height: 24 / 18, // Line height: 24px
color: Color(0xFF1F1F1F),
);

/// Body L - Regular / 16
/// Font weight: 400, Size: 16, Line height: 22
static const TextStyle bodyL = TextStyle(
fontFamily: _fontFamily,
fontSize: 16,
fontWeight: FontWeight.w400, // Regular
height: 22 / 16, // Line height: 22px
color: Color(0xFF1F1F1F),
);

/// Body M - Regular / 14
/// Font weight: 400, Size: 14, Line height: 20
static const TextStyle bodyM = TextStyle(
fontFamily: _fontFamily,
fontSize: 14,
fontWeight: FontWeight.w400, // Regular
height: 20 / 14, // Line height: 20px
color: Color(0xFF1F1F1F),
);

/// Body S - Regular / 12
/// Font weight: 400, Size: 12, Line height: 16
static const TextStyle bodyS = TextStyle(
fontFamily: _fontFamily,
fontSize: 12,
fontWeight: FontWeight.w400, // Regular
height: 16 / 12, // Line height: 16px
letterSpacing: 0.12,
color: Color(0xFF1F1F1F),
);

/// Body XS - Regular / 10
/// Font weight: 400, Size: 10, Line height: 14
static const TextStyle bodyXS = TextStyle(
fontFamily: _fontFamily,
fontSize: 10,
fontWeight: FontWeight.w400, // Regular
height: 14 / 10, // Line height: 14px
letterSpacing: 0.15,
color: Color(0xFF1F1F1F),
);

// ==================== ACTION STYLES ====================

/// Action L - Semi Bold / 14
/// Font weight: 600, Size: 14, Line height: 1.0 (100%)
static const TextStyle actionL = TextStyle(
fontFamily: _fontFamily,
fontSize: 14,
fontWeight: FontWeight.w600, // Semi Bold
height: 1.0, // 100% line height
color: Color(0xFF1F1F1F),
);

/// Action M - Semi Bold / 12
/// Font weight: 600, Size: 12, Line height: 1.0 (100%)
static const TextStyle actionM = TextStyle(
fontFamily: _fontFamily,
fontSize: 12,
fontWeight: FontWeight.w600, // Semi Bold
height: 1.0, // 100% line height
color: Color(0xFF1F1F1F),
);

/// Action S - Semi Bold / 10
/// Font weight: 600, Size: 10, Line height: 1.0 (100%)
static const TextStyle actionS = TextStyle(
fontFamily: _fontFamily,
fontSize: 10,
fontWeight: FontWeight.w600, // Semi Bold
height: 1.0, // 100% line height
color: Color(0xFF1F1F1F),
);

// ==================== CAPTION STYLES ====================

/// Caption M - Semi Bold / 10 (Uppercase)
/// Font weight: 600, Size: 10, Line height: 1.0 (100%)
/// Note: Text should be transformed to uppercase when using this style
static const TextStyle captionM = TextStyle(
fontFamily: _fontFamily,
fontSize: 10,
fontWeight: FontWeight.w600, // Semi Bold
height: 1.0, // 100% line height
letterSpacing: 0.5,
color: Color(0xFF1F1F1F),
);

// ==================== COLOR VARIANTS ====================

// Helper methods to apply different color variants to text styles

/// Apply dark color (#1F2024) to any text style
static TextStyle withDarkColor(TextStyle style) {
return style.copyWith(color: const Color(0xFF1F2024));
}

/// Apply medium dark color (#494A50) to any text style
static TextStyle withMediumDarkColor(TextStyle style) {
return style.copyWith(color: const Color(0xFF494A50));
}

/// Apply light dark color (#71727A) to any text style
static TextStyle withLightDarkColor(TextStyle style) {
return style.copyWith(color: const Color(0xFF71727A));
}

/// Apply lightest dark color (#8F9098) to any text style
static TextStyle withLightestDarkColor(TextStyle style) {
return style.copyWith(color: const Color(0xFF8F9098));
}

/// Apply highlight color (#006FFD) to any text style
static TextStyle withHighlightColor(TextStyle style) {
return style.copyWith(color: const Color(0xFF006FFD));
}

/// Apply white color to any text style
static TextStyle withWhiteColor(TextStyle style) {
return style.copyWith(color: const Color(0xFFFFFFFF));
}
}
119 changes: 111 additions & 8 deletions docpilot_core/lib/src/theme/theme_helper.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'text_style.dart';

/// Helper utilities for building consistent theme configurations across DocPilot apps.
///
Expand All @@ -18,6 +19,35 @@ class ThemeHelper {
static const double borderRadiusLarge = 12.0;
static const double borderRadiusXLarge = 16.0;

// Neutral Light Colors
static const Color neutralLightDarkest = Color(0xFFC5C6CC);
static const Color neutralLightDark = Color(0xFFD4D6DD);
static const Color neutralLightMedium = Color(0xFFE8E9F1);
static const Color neutralLightLight = Color(0xFFF8F9FE);
static const Color neutralLightLightest = Color(0xFFFFFFFF);

// Neutral Dark Colors
static const Color neutralDarkDarkest = Color(0xFF1F2024);
static const Color neutralDarkDark = Color(0xFF2F3036);
static const Color neutralDarkMedium = Color(0xFF494A50);
static const Color neutralDarkLight = Color(0xFF71727A);
static const Color neutralDarkLightest = Color(0xFF8F9098);

// Success Colors
static const Color successDark = Color(0xFF147D64);
static const Color successMedium = Color(0xFF3AC0A0);
static const Color successLight = Color(0xFFE7F4E8);

// Warning Colors
static const Color warningDark = Color(0xFFE86339);
static const Color warningMedium = Color(0xFFFFB37C);
static const Color warningLight = Color(0xFFFFF4E4);

// Error Colors
static const Color errorDark = Color(0xFFED3241);
static const Color errorMedium = Color(0xFFFF616D);
static const Color errorLight = Color(0xFFFFE2E5);

/// Input height
static const double inputHeight = 48.0;

Expand Down Expand Up @@ -70,14 +100,72 @@ class ThemeHelper {
brightness: brightness,
primaryColor: primaryColor,
fontFamily: fontFamily,

colorScheme: ColorScheme.fromSeed(
seedColor: primaryColor,
brightness: brightness,
// Customize specific colors
primary: primaryColor,
),

filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
backgroundColor: primaryColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: spacingXLarge,
vertical: spacingMedium,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadiusXLarge),
),
elevation: 0,
),
),

outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: primaryColor,
side: BorderSide(color: primaryColor),
padding: const EdgeInsets.symmetric(
horizontal: spacingXLarge,
vertical: spacingMedium,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadiusXLarge),
),
),
),

textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: primaryColor,
padding: const EdgeInsets.symmetric(
horizontal: spacingMedium,
vertical: spacingSmall,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(borderRadiusXLarge),
),
),
),

progressIndicatorTheme: ProgressIndicatorThemeData(
color: primaryColor,
borderRadius: BorderRadius.circular(borderRadiusSmall),
circularTrackColor: neutralLightMedium,
strokeWidth: 5.0,
strokeAlign: BorderSide.strokeAlignCenter,
strokeCap: StrokeCap.round,
circularTrackPadding: EdgeInsets.all(2.0),
constraints: BoxConstraints(
maxWidth: 32.0,
maxHeight: 32.0,
minHeight: 16.0,
minWidth: 16.0,
),
linearTrackColor: neutralLightMedium,
linearMinHeight: 6,
),

// Input decoration theme - no borders since components handle their own
inputDecorationTheme: const InputDecorationTheme(
border: InputBorder.none,
Expand All @@ -87,7 +175,22 @@ class ThemeHelper {
disabledBorder: InputBorder.none,
focusedErrorBorder: InputBorder.none,
),

navigationBarTheme: NavigationBarThemeData(
backgroundColor: neutralLightLightest,
indicatorColor: neutralLightLightest,
overlayColor: WidgetStatePropertyAll(Colors.transparent),
labelTextStyle: WidgetStateProperty.resolveWith<TextStyle>(
(states) {
if (states.contains(WidgetState.selected)) {
return DocPilotTextStyles.actionM
.copyWith(color: neutralDarkDarkest);
}
return DocPilotTextStyles.bodyXS
.copyWith(color: neutralDarkDarkest);
},
),
),

// Text theme with Inter font
textTheme: TextTheme(
// Display styles
Expand All @@ -106,7 +209,7 @@ class ThemeHelper {
fontWeight: FontWeight.w400,
fontFamily: fontFamily,
),

// Headline styles
headlineLarge: TextStyle(
fontSize: 32,
Expand All @@ -123,7 +226,7 @@ class ThemeHelper {
fontWeight: FontWeight.w600,
fontFamily: fontFamily,
),

// Title styles
titleLarge: TextStyle(
fontSize: 20,
Expand All @@ -140,7 +243,7 @@ class ThemeHelper {
fontWeight: FontWeight.w600,
fontFamily: fontFamily,
),

// Body styles
bodyLarge: TextStyle(
fontSize: 16,
Expand All @@ -157,7 +260,7 @@ class ThemeHelper {
fontWeight: FontWeight.w400,
fontFamily: fontFamily,
),

// Label styles
labelLarge: TextStyle(
fontSize: 14,
Expand All @@ -177,4 +280,4 @@ class ThemeHelper {
),
);
}
}
}
4 changes: 4 additions & 0 deletions docpilot_doctor/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release

*.gen.dart
*.g.dart
*.freezed.dart
Loading