@tduncan / Cortana / commits / 459c92c

feat: implement Claude-inspired color palette with dark mode support

abdulmominsakib committed Apr 4, 2026 at 20:12 UTC 459c92cceb419778ec5fe82f4a9b87e2f109536b
7 files changed +120 -44
lib/core/theme/app_theme.dart
+12 -13
@@ -57,6 +57,7 @@ class AppTheme {
57 muted: AppColors.claudeSurface,
58 mutedForeground: AppColors.claudeMutedText,
59 ),
60 + radius: const BorderRadius.all(Radius.circular(12)),
61 );
62
63 static ThemeData get darkTheme => ThemeData(
@@ -293,10 +294,7 @@ class AppTheme {
294 onSurface: AppColors.claudePrimaryText,
295 outline: AppColors.claudeBorder,
296 ),
296 - textTheme: AppTypography.lightTextTheme.apply(
297 - bodyColor: AppColors.claudePrimaryText,
298 - displayColor: AppColors.claudePrimaryText,
299 - ),
297 + textTheme: AppTypography.claudeTextTheme,
298 appBarTheme: const AppBarTheme(
299 backgroundColor: AppColors.claudeBackground,
300 foregroundColor: AppColors.claudePrimaryText,
@@ -319,15 +317,15 @@ class AppTheme {
317 filled: true,
318 fillColor: AppColors.claudeSurface,
319 border: OutlineInputBorder(
322 - borderRadius: BorderRadius.circular(8),
320 + borderRadius: BorderRadius.circular(12),
321 borderSide: const BorderSide(color: AppColors.claudeBorder),
322 ),
323 enabledBorder: OutlineInputBorder(
326 - borderRadius: BorderRadius.circular(8),
324 + borderRadius: BorderRadius.circular(12),
325 borderSide: const BorderSide(color: AppColors.claudeBorder),
326 ),
327 focusedBorder: OutlineInputBorder(
330 - borderRadius: BorderRadius.circular(8),
328 + borderRadius: BorderRadius.circular(12),
329 borderSide: const BorderSide(color: AppColors.claudeAccent, width: 2),
330 ),
331 contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
@@ -337,7 +335,7 @@ class AppTheme {
335 backgroundColor: AppColors.claudeAccent,
336 foregroundColor: Colors.white,
337 shape: RoundedRectangleBorder(
340 - borderRadius: BorderRadius.circular(8),
338 + borderRadius: BorderRadius.circular(12),
339 ),
340 padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
341 ),
@@ -347,7 +345,7 @@ class AppTheme {
345 foregroundColor: AppColors.claudePrimaryText,
346 side: const BorderSide(color: AppColors.claudeBorder),
347 shape: RoundedRectangleBorder(
350 - borderRadius: BorderRadius.circular(8),
348 + borderRadius: BorderRadius.circular(8), // Secondary buttons are less rounded
349 ),
350 padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
351 ),
@@ -355,13 +353,13 @@ class AppTheme {
353 bottomSheetTheme: const BottomSheetThemeData(
354 backgroundColor: AppColors.claudeSurface,
355 shape: RoundedRectangleBorder(
358 - borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
356 + borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
357 ),
358 ),
359 dialogTheme: DialogThemeData(
360 backgroundColor: AppColors.claudeSurface,
361 shape: RoundedRectangleBorder(
364 - borderRadius: BorderRadius.circular(12),
362 + borderRadius: BorderRadius.circular(16),
363 ),
364 ),
365 navigationBarTheme: NavigationBarThemeData(
@@ -371,14 +369,15 @@ class AppTheme {
369 if (states.contains(WidgetState.selected)) {
370 return const TextStyle(color: AppColors.claudePrimaryText, fontSize: 12, fontWeight: FontWeight.w600);
371 }
374 - return const TextStyle(color: AppColors.claudeMutedText, fontSize: 12, fontWeight: FontWeight.w500);
372 + return const TextStyle(color: AppColors.claudeSecondaryText, fontSize: 12, fontWeight: FontWeight.w500);
373 }),
374 iconTheme: WidgetStateProperty.resolveWith((states) {
375 if (states.contains(WidgetState.selected)) {
376 return const IconThemeData(color: AppColors.claudePrimaryText);
377 }
380 - return const IconThemeData(color: AppColors.claudeMutedText);
378 + return const IconThemeData(color: AppColors.claudeSecondaryText);
379 }),
380 ),
381 );
382 +
383 }
lib/core/theme/colors.dart
+15 -6
@@ -18,12 +18,21 @@ class AppColors {
18 static const Color lightAccent = Color(0xFF0A0A0A);
19
20 // Claude Theme
21 - static const Color claudeBackground = Color(0xFFF6F4EB);
22 - static const Color claudeSurface = Color(0xFFFFFFFF);
23 - static const Color claudeBorder = Color(0xFFE5D5C5);
24 - static const Color claudePrimaryText = Color(0xFF1F1E1D);
25 - static const Color claudeMutedText = Color(0xFF8F8A80);
26 - static const Color claudeAccent = Color(0xFFDA7048);
21 + static const Color claudeBackground = Color(0xFFF5F4ED);
22 + static const Color claudeSurface = Color(0xFFFAF9F5);
23 + static const Color claudeBorder = Color(0xFFF0EEE6);
24 + static const Color claudePrimaryText = Color(0xFF141413);
25 + static const Color claudeSecondaryText = Color(0xFF5E5D59);
26 + static const Color claudeMutedText = Color(0xFF87867F);
27 + static const Color claudeAccent = Color(0xFFC96442);
28 +
29 + // Claude Dark Theme (Optional, but included in design)
30 + static const Color claudeDarkBackground = Color(0xFF141413);
31 + static const Color claudeDarkSurface = Color(0xFF30302E);
32 + static const Color claudeDarkBorder = Color(0xFF30302E);
33 + static const Color claudeDarkPrimaryText = Color(0xFFFAF9F5);
34 + static const Color claudeDarkSecondaryText = Color(0xFFB0AEA5);
35 +
36
37 static const Color success = Color(0xFF22C55E);
38 static const Color error = Color(0xFFEF4444);
lib/core/theme/typography.dart
+87
@@ -49,4 +49,91 @@ class AppTypography {
49 ),
50 );
51 }
52 + static TextTheme get claudeTextTheme {
53 + return GoogleFonts.loraTextTheme(
54 + const TextTheme(
55 + displayLarge: TextStyle(
56 + color: AppColors.claudePrimaryText,
57 + fontSize: 64,
58 + fontWeight: FontWeight.w500,
59 + height: 1.1,
60 + ),
61 + displayMedium: TextStyle(
62 + color: AppColors.claudePrimaryText,
63 + fontSize: 52,
64 + fontWeight: FontWeight.w500,
65 + height: 1.2,
66 + ),
67 + displaySmall: TextStyle(
68 + color: AppColors.claudePrimaryText,
69 + fontSize: 36,
70 + fontWeight: FontWeight.w500,
71 + height: 1.3,
72 + ),
73 + headlineLarge: TextStyle(
74 + color: AppColors.claudePrimaryText,
75 + fontSize: 32,
76 + fontWeight: FontWeight.w500,
77 + height: 1.1,
78 + ),
79 + headlineMedium: TextStyle(
80 + color: AppColors.claudePrimaryText,
81 + fontSize: 25,
82 + fontWeight: FontWeight.w500,
83 + height: 1.2,
84 + ),
85 + headlineSmall: TextStyle(
86 + color: AppColors.claudePrimaryText,
87 + fontSize: 20,
88 + fontWeight: FontWeight.w500,
89 + height: 1.2,
90 + ),
91 + titleLarge: TextStyle(
92 + color: AppColors.claudePrimaryText,
93 + fontSize: 17,
94 + fontWeight: FontWeight.w500,
95 + height: 1.1,
96 + ),
97 + ),
98 + ).copyWith(
99 + bodyLarge: GoogleFonts.inter(
100 + color: AppColors.claudePrimaryText,
101 + fontSize: 17,
102 + fontWeight: FontWeight.w400,
103 + height: 1.6,
104 + ),
105 + bodyMedium: GoogleFonts.inter(
106 + color: AppColors.claudePrimaryText,
107 + fontSize: 16,
108 + fontWeight: FontWeight.w400,
109 + height: 1.6,
110 + ),
111 + bodySmall: GoogleFonts.inter(
112 + color: AppColors.claudeSecondaryText,
113 + fontSize: 15,
114 + fontWeight: FontWeight.w400,
115 + height: 1.6,
116 + ),
117 + labelLarge: GoogleFonts.inter(
118 + color: AppColors.claudePrimaryText,
119 + fontSize: 14,
120 + fontWeight: FontWeight.w500,
121 + height: 1.4,
122 + ),
123 + labelMedium: GoogleFonts.inter(
124 + color: AppColors.claudeSecondaryText,
125 + fontSize: 12,
126 + fontWeight: FontWeight.w500,
127 + height: 1.4,
128 + letterSpacing: 0.12,
129 + ),
130 + labelSmall: GoogleFonts.inter(
131 + color: AppColors.claudeMutedText,
132 + fontSize: 10,
133 + fontWeight: FontWeight.w500,
134 + height: 1.6,
135 + letterSpacing: 0.5,
136 + ),
137 + );
138 + }
139 }
lib/features/conversations/views/components/new_chat_button.dart
-13
@@ -9,9 +9,6 @@ class NewChatButton extends ConsumerWidget {
9
10 @override
11 Widget build(BuildContext context, WidgetRef ref) {
12 - final theme = Theme.of(context);
13 - final isDark = theme.brightness == Brightness.dark;
14 -
12 return Container(
13 padding: const EdgeInsets.symmetric(horizontal: 16),
14 child: SizedBox(
@@ -26,16 +23,6 @@ class NewChatButton extends ConsumerWidget {
23 },
24 icon: const Icon(Icons.add, size: 18),
25 label: const Text('New Chat'),
29 - style: ElevatedButton.styleFrom(
30 - backgroundColor: isDark
31 - ? const Color(0xFF3B82F6)
32 - : const Color(0xFF2563EB),
33 - foregroundColor: Colors.white,
34 - padding: const EdgeInsets.symmetric(vertical: 12),
35 - shape: RoundedRectangleBorder(
36 - borderRadius: BorderRadius.circular(8),
37 - ),
38 - ),
26 ),
27 ),
28 );
lib/features/sidebar/sidebar_widget.dart
+2 -3
@@ -19,7 +19,6 @@ class SidebarWidget extends ConsumerWidget {
19 @override
20 Widget build(BuildContext context, WidgetRef ref) {
21 final theme = Theme.of(context);
22 - final isDark = theme.brightness == Brightness.dark;
22 final groupedConversations = ref.watch(groupedConversationsProvider);
23 final activeConversation = ref.watch(activeConversationProvider);
24 final searchQuery = ref.watch(conversationSearchProvider);
@@ -32,10 +31,10 @@ class SidebarWidget extends ConsumerWidget {
31 return Container(
32 width: 300,
33 decoration: BoxDecoration(
35 - color: isDark ? const Color(0xFF0A0A0A) : const Color(0xFFFAFAFA),
34 + color: theme.scaffoldBackgroundColor,
35 border: Border(
36 right: BorderSide(
38 - color: isDark ? const Color(0xFF1A1A1A) : const Color(0xFFE5E5E5),
37 + color: theme.colorScheme.outline,
38 ),
39 ),
40 ),
lib/main.dart
+3 -8
@@ -1,22 +1,17 @@
1 import 'package:flutter/material.dart';
2 import 'package:flutter_riverpod/flutter_riverpod.dart';
3 -import 'package:google_fonts/google_fonts.dart';
3 import 'app.dart';
4 import 'core/storage/hive_initializer.dart';
5 import 'core/providers/storage_providers.dart';
6
7 Future<void> main() async {
8 WidgetsFlutterBinding.ensureInitialized();
10 -
11 - GoogleFonts.config.allowRuntimeFetching = false;
12 -
9 +
10 final hiveBoxes = await HiveInitializer.initialize();
14 -
11 +
12 runApp(
13 ProviderScope(
17 - overrides: [
18 - hiveBoxesProvider.overrideWithValue(hiveBoxes),
19 - ],
14 + overrides: [hiveBoxesProvider.overrideWithValue(hiveBoxes)],
15 child: const App(),
16 ),
17 );
pubspec.yaml
+1 -1
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
16 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 # In Windows, build-name is used as the major, minor, and patch parts
18 # of the product and file versions while build-number is used as the build suffix.
19 -version: 1.0.0+3
19 +version: 1.0.0+4
20
21 environment:
22 sdk: ^3.11.0