1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.fenix.theme
7 import androidx.compose.foundation.isSystemInDarkTheme
8 import androidx.compose.material.MaterialTheme
9 import androidx.compose.runtime.Composable
10 import androidx.compose.runtime.CompositionLocalProvider
11 import androidx.compose.runtime.Stable
12 import androidx.compose.runtime.getValue
13 import androidx.compose.runtime.mutableStateOf
14 import androidx.compose.runtime.remember
15 import androidx.compose.runtime.setValue
16 import androidx.compose.runtime.staticCompositionLocalOf
17 import androidx.compose.ui.graphics.Color
18 import mozilla.components.ui.colors.PhotonColors
21 * The theme for Mozilla Firefox for Android (Fenix).
25 darkTheme: Boolean = isSystemInDarkTheme(),
26 content: @Composable () -> Unit
28 val colors = if (darkTheme) darkColorPalette else lightColorPalette
30 ProvideFirefoxColors(colors) {
38 val colors: FirefoxColors
40 get() = localFirefoxColors.current
43 private val darkColorPalette = FirefoxColors(
44 layer1 = PhotonColors.DarkGrey60,
45 layer2 = PhotonColors.DarkGrey30,
46 layer3 = PhotonColors.DarkGrey30,
47 layerAccent = PhotonColors.Violet40,
48 layerAccentNonOpaque = PhotonColors.Violet50A32,
49 scrim = PhotonColors.DarkGrey90A95,
50 gradientStart = PhotonColors.Violet70,
51 gradientEnd = PhotonColors.Violet40,
52 actionPrimary = PhotonColors.Violet60,
53 actionSecondary = PhotonColors.LightGrey05,
54 actionTertiary = PhotonColors.DarkGrey10,
55 actionQuarternary = PhotonColors.DarkGrey80,
56 formDefault = PhotonColors.LightGrey05,
57 formSelected = PhotonColors.Violet40,
58 formSurface = PhotonColors.DarkGrey05,
59 formDisabled = PhotonColors.DarkGrey05,
60 formOn = PhotonColors.Violet40,
61 formOff = PhotonColors.LightGrey05,
62 indicatorActive = PhotonColors.LightGrey90,
63 indicatorInactive = PhotonColors.DarkGrey05,
64 textPrimary = PhotonColors.LightGrey05,
65 textSecondary = PhotonColors.LightGrey40,
66 textDisabled = PhotonColors.LightGrey05A40,
67 textWarning = PhotonColors.Red20,
68 textWarningButton = PhotonColors.Red70,
69 textAccent = PhotonColors.Violet20,
70 textAccentDisabled = PhotonColors.Violet20A60,
71 textOnColorPrimary = PhotonColors.LightGrey05,
72 textOnColorSecondary = PhotonColors.LightGrey40,
73 textActionPrimary = PhotonColors.LightGrey05,
74 textActionSecondary = PhotonColors.DarkGrey90,
75 textActionTertiary = PhotonColors.LightGrey05,
76 textActionTertiaryActive = PhotonColors.LightGrey05,
77 iconPrimary = PhotonColors.LightGrey05,
78 iconPrimaryInactive = PhotonColors.LightGrey05A60,
79 iconSecondary = PhotonColors.LightGrey40,
80 iconActive = PhotonColors.Violet40,
81 iconDisabled = PhotonColors.LightGrey05A40,
82 iconOnColor = PhotonColors.LightGrey05,
83 iconNotice = PhotonColors.Blue30,
84 iconButton = PhotonColors.LightGrey05,
85 iconWarning = PhotonColors.Red20,
86 iconWarningButton = PhotonColors.Red70,
87 iconAccentViolet = PhotonColors.Violet20,
88 iconAccentBlue = PhotonColors.Blue20,
89 iconAccentPink = PhotonColors.Pink20,
90 iconAccentGreen = PhotonColors.Green20,
91 iconAccentYellow = PhotonColors.Yellow20,
92 iconGradientStart = PhotonColors.Violet20,
93 iconGradientEnd = PhotonColors.Blue20,
94 borderPrimary = PhotonColors.DarkGrey05,
95 borderInverted = PhotonColors.LightGrey30,
96 borderFormDefault = PhotonColors.LightGrey05,
97 borderAccent = PhotonColors.Violet40,
98 borderDisabled = PhotonColors.LightGrey05A40,
99 borderWarning = PhotonColors.Red40
102 private val lightColorPalette = FirefoxColors(
103 layer1 = PhotonColors.LightGrey10,
104 layer2 = PhotonColors.White,
105 layer3 = PhotonColors.LightGrey20,
106 layerAccent = PhotonColors.Ink20,
107 layerAccentNonOpaque = PhotonColors.Violet70A12,
108 scrim = PhotonColors.DarkGrey30A95,
109 gradientStart = PhotonColors.Violet70,
110 gradientEnd = PhotonColors.Violet40,
111 actionPrimary = PhotonColors.Ink20,
112 actionSecondary = PhotonColors.LightGrey30,
113 actionTertiary = PhotonColors.LightGrey40,
114 actionQuarternary = PhotonColors.LightGrey10,
115 formDefault = PhotonColors.DarkGrey90,
116 formSelected = PhotonColors.Ink20,
117 formSurface = PhotonColors.LightGrey50,
118 formDisabled = PhotonColors.LightGrey50,
119 formOn = PhotonColors.Ink20,
120 formOff = PhotonColors.LightGrey05,
121 indicatorActive = PhotonColors.LightGrey50,
122 indicatorInactive = PhotonColors.LightGrey30,
123 textPrimary = PhotonColors.DarkGrey90,
124 textSecondary = PhotonColors.DarkGrey05,
125 textDisabled = PhotonColors.DarkGrey90A40,
126 textWarning = PhotonColors.Red70,
127 textWarningButton = PhotonColors.Red70,
128 textAccent = PhotonColors.Violet70,
129 textAccentDisabled = PhotonColors.Violet70A80,
130 textOnColorPrimary = PhotonColors.LightGrey05,
131 textOnColorSecondary = PhotonColors.LightGrey40,
132 textActionPrimary = PhotonColors.LightGrey05,
133 textActionSecondary = PhotonColors.DarkGrey90,
134 textActionTertiary = PhotonColors.DarkGrey90,
135 textActionTertiaryActive = PhotonColors.LightGrey05,
136 iconPrimary = PhotonColors.DarkGrey90,
137 iconPrimaryInactive = PhotonColors.DarkGrey90A60,
138 iconSecondary = PhotonColors.DarkGrey05,
139 iconActive = PhotonColors.Ink20,
140 iconDisabled = PhotonColors.DarkGrey90A40,
141 iconOnColor = PhotonColors.LightGrey05,
142 iconNotice = PhotonColors.Blue30,
143 iconButton = PhotonColors.Ink20,
144 iconWarning = PhotonColors.Red70,
145 iconWarningButton = PhotonColors.Red70,
146 iconAccentViolet = PhotonColors.Violet60,
147 iconAccentBlue = PhotonColors.Blue60,
148 iconAccentPink = PhotonColors.Pink60,
149 iconAccentGreen = PhotonColors.Green60,
150 iconAccentYellow = PhotonColors.Yellow60,
151 iconGradientStart = PhotonColors.Violet50,
152 iconGradientEnd = PhotonColors.Blue60,
153 borderPrimary = PhotonColors.LightGrey30,
154 borderInverted = PhotonColors.DarkGrey05,
155 borderFormDefault = PhotonColors.DarkGrey90,
156 borderAccent = PhotonColors.Ink20,
157 borderDisabled = PhotonColors.DarkGrey90A40,
158 borderWarning = PhotonColors.Red70
162 * A custom Color Palette for Mozilla Firefox for Android (Fenix).
164 @Suppress("LargeClass", "LongParameterList")
171 layerAccentNonOpaque: Color,
173 gradientStart: Color,
175 actionPrimary: Color,
176 actionSecondary: Color,
177 actionTertiary: Color,
178 actionQuarternary: Color,
185 indicatorActive: Color,
186 indicatorInactive: Color,
188 textSecondary: Color,
191 textWarningButton: Color,
193 textAccentDisabled: Color,
194 textOnColorPrimary: Color,
195 textOnColorSecondary: Color,
196 textActionPrimary: Color,
197 textActionSecondary: Color,
198 textActionTertiary: Color,
199 textActionTertiaryActive: Color,
201 iconPrimaryInactive: Color,
202 iconSecondary: Color,
209 iconWarningButton: Color,
210 iconAccentViolet: Color,
211 iconAccentBlue: Color,
212 iconAccentPink: Color,
213 iconAccentGreen: Color,
214 iconAccentYellow: Color,
215 iconGradientStart: Color,
216 iconGradientEnd: Color,
217 borderPrimary: Color,
218 borderInverted: Color,
219 borderFormDefault: Color,
221 borderDisabled: Color,
226 // Default Screen background, Frontlayer background, App Bar Top, App Bar Bottom, Frontlayer header
227 var layer1 by mutableStateOf(layer1)
229 // Card background, Menu background, Dialog, Banner
230 var layer2 by mutableStateOf(layer2)
233 var layer3 by mutableStateOf(layer3)
235 // App Bar Top (edit), Text Cursor, Selected Tab Check
236 var layerAccent by mutableStateOf(layerAccent)
239 var layerAccentNonOpaque by mutableStateOf(layerAccentNonOpaque)
241 var scrim by mutableStateOf(scrim)
244 var gradientStart by mutableStateOf(gradientStart)
247 var gradientEnd by mutableStateOf(gradientEnd)
252 // Primary button, Snackbar, Floating action button, Chip selected
253 var actionPrimary by mutableStateOf(actionPrimary)
256 var actionSecondary by mutableStateOf(actionSecondary)
259 var actionTertiary by mutableStateOf(actionTertiary)
262 var actionQuarternary by mutableStateOf(actionQuarternary)
264 // Checkbox default, Radio button default
265 var formDefault by mutableStateOf(formDefault)
267 // Checkbox selected, Radio button selected
268 var formSelected by mutableStateOf(formSelected)
270 // Switch background OFF, Switch background ON
271 var formSurface by mutableStateOf(formSurface)
273 // Checkbox disabled, Radio disabled
274 var formDisabled by mutableStateOf(formDisabled)
277 var formOn by mutableStateOf(formOn)
280 var formOff by mutableStateOf(formOff)
282 // Scroll indicator active
283 var indicatorActive by mutableStateOf(indicatorActive)
285 // Scroll indicator inactive
286 var indicatorInactive by mutableStateOf(indicatorInactive)
292 var textPrimary by mutableStateOf(textPrimary)
295 var textSecondary by mutableStateOf(textSecondary)
298 var textDisabled by mutableStateOf(textDisabled)
301 var textWarning by mutableStateOf(textWarning)
303 // Warning text on Secondary button
304 var textWarningButton by mutableStateOf(textWarningButton)
306 // Small heading, Text link
307 var textAccent by mutableStateOf(textAccent)
309 // Small heading, Text link
310 var textAccentDisabled by mutableStateOf(textAccentDisabled)
312 // Text Inverted/On Color
313 var textOnColorPrimary by mutableStateOf(textOnColorPrimary)
315 // Text Inverted/On Color
316 var textOnColorSecondary by mutableStateOf(textOnColorSecondary)
318 // Action Primary text
319 var textActionPrimary by mutableStateOf(textActionPrimary)
321 // Action Secondary text
322 var textActionSecondary by mutableStateOf(textActionSecondary)
324 // Action Tertiary text
325 var textActionTertiary by mutableStateOf(textActionTertiary)
327 // Action Tertiary Active text
328 var textActionTertiaryActive by mutableStateOf(textActionTertiaryActive)
334 var iconPrimary by mutableStateOf(iconPrimary)
337 var iconPrimaryInactive by mutableStateOf(iconPrimaryInactive)
340 var iconSecondary by mutableStateOf(iconSecondary)
343 var iconActive by mutableStateOf(iconActive)
346 var iconDisabled by mutableStateOf(iconDisabled)
348 // Icon inverted (on color)
349 var iconOnColor by mutableStateOf(iconOnColor)
352 var iconNotice by mutableStateOf(iconNotice)
355 var iconButton by mutableStateOf(iconButton)
357 var iconWarning by mutableStateOf(iconWarning)
359 // Warning icon on Secondary button
360 var iconWarningButton by mutableStateOf(iconWarningButton)
362 var iconAccentViolet by mutableStateOf(iconAccentViolet)
364 var iconAccentBlue by mutableStateOf(iconAccentBlue)
366 var iconAccentPink by mutableStateOf(iconAccentPink)
368 var iconAccentGreen by mutableStateOf(iconAccentGreen)
370 var iconAccentYellow by mutableStateOf(iconAccentYellow)
372 // Reader, ETP Shield
373 var iconGradientStart by mutableStateOf(iconGradientStart)
375 // Reader, ETP Shield
376 var iconGradientEnd by mutableStateOf(iconGradientEnd)
381 // Default, Divider, Dotted
382 var borderPrimary by mutableStateOf(borderPrimary)
385 var borderInverted by mutableStateOf(borderInverted)
388 var borderFormDefault by mutableStateOf(borderFormDefault)
390 // Active tab (Nav), Selected tab, Active form
391 var borderAccent by mutableStateOf(borderAccent)
394 var borderDisabled by mutableStateOf(borderDisabled)
397 var borderWarning by mutableStateOf(borderWarning)
400 fun update(other: FirefoxColors) {
401 layer1 = other.layer1
402 layer2 = other.layer2
403 layer3 = other.layer3
404 layerAccent = other.layerAccent
405 layerAccentNonOpaque = other.layerAccentNonOpaque
407 gradientStart = other.gradientStart
408 gradientEnd = other.gradientEnd
409 actionPrimary = other.actionPrimary
410 actionSecondary = other.actionSecondary
411 actionTertiary = other.actionTertiary
412 actionQuarternary = other.actionQuarternary
413 formDefault = other.formDefault
414 formSelected = other.formSelected
415 formSurface = other.formSurface
416 formDisabled = other.formDisabled
417 formOn = other.formOn
418 formOff = other.formOff
419 indicatorActive = other.indicatorActive
420 indicatorInactive = other.indicatorInactive
421 textPrimary = other.textPrimary
422 textSecondary = other.textSecondary
423 textDisabled = other.textDisabled
424 textWarning = other.textWarning
425 textWarningButton = other.textWarningButton
426 textAccent = other.textAccent
427 textAccentDisabled = other.textAccentDisabled
428 textOnColorPrimary = other.textOnColorPrimary
429 textOnColorSecondary = other.textOnColorSecondary
430 textActionPrimary = other.textActionPrimary
431 textActionSecondary = other.textSecondary
432 textActionTertiary = other.textActionTertiary
433 textActionTertiaryActive = other.textActionTertiaryActive
434 iconPrimary = other.iconPrimary
435 iconPrimaryInactive = other.iconPrimaryInactive
436 iconSecondary = other.iconSecondary
437 iconActive = other.iconActive
438 iconDisabled = other.iconDisabled
439 iconOnColor = other.iconOnColor
440 iconNotice = other.iconNotice
441 iconButton = other.iconButton
442 iconWarning = other.iconWarning
443 iconWarningButton = other.iconWarningButton
444 iconAccentViolet = other.iconAccentViolet
445 iconAccentBlue = other.iconAccentBlue
446 iconAccentPink = other.iconAccentPink
447 iconAccentGreen = other.iconAccentGreen
448 iconAccentYellow = other.iconAccentYellow
449 iconGradientStart = other.iconGradientStart
450 iconGradientEnd = other.iconGradientEnd
451 borderPrimary = other.borderPrimary
452 borderInverted = other.borderInverted
453 borderFormDefault = other.borderFormDefault
454 borderAccent = other.borderAccent
455 borderDisabled = other.borderDisabled
456 borderWarning = other.borderWarning
459 fun copy(): FirefoxColors = FirefoxColors(
463 layerAccent = layerAccent,
464 layerAccentNonOpaque = layerAccentNonOpaque,
466 gradientStart = gradientStart,
467 gradientEnd = gradientEnd,
468 actionPrimary = actionPrimary,
469 actionSecondary = actionSecondary,
470 actionTertiary = actionTertiary,
471 actionQuarternary = actionQuarternary,
472 formDefault = formDefault,
473 formSelected = formSelected,
474 formSurface = formSurface,
475 formDisabled = formDisabled,
478 indicatorActive = indicatorActive,
479 indicatorInactive = indicatorInactive,
480 textPrimary = textPrimary,
481 textSecondary = textSecondary,
482 textDisabled = textDisabled,
483 textWarning = textWarning,
484 textWarningButton = textWarningButton,
485 textAccent = textAccent,
486 textAccentDisabled = textAccentDisabled,
487 textOnColorPrimary = textOnColorPrimary,
488 textOnColorSecondary = textOnColorSecondary,
489 textActionPrimary = textActionPrimary,
490 textActionSecondary = textActionSecondary,
491 textActionTertiary = textActionTertiary,
492 textActionTertiaryActive = textActionTertiaryActive,
493 iconPrimary = iconPrimary,
494 iconPrimaryInactive = iconPrimaryInactive,
495 iconSecondary = iconSecondary,
496 iconActive = iconActive,
497 iconDisabled = iconDisabled,
498 iconOnColor = iconOnColor,
499 iconNotice = iconNotice,
500 iconButton = iconButton,
501 iconWarning = iconWarning,
502 iconWarningButton = iconWarningButton,
503 iconAccentViolet = iconAccentViolet,
504 iconAccentBlue = iconAccentBlue,
505 iconAccentPink = iconAccentPink,
506 iconAccentGreen = iconAccentGreen,
507 iconAccentYellow = iconAccentYellow,
508 iconGradientStart = iconGradientStart,
509 iconGradientEnd = iconGradientEnd,
510 borderPrimary = borderPrimary,
511 borderInverted = borderInverted,
512 borderFormDefault = borderFormDefault,
513 borderAccent = borderAccent,
514 borderDisabled = borderDisabled,
515 borderWarning = borderWarning
520 fun ProvideFirefoxColors(
521 colors: FirefoxColors,
522 content: @Composable () -> Unit
524 val colorPalette = remember {
525 // Explicitly creating a new object here so we don't mutate the initial [colors]
526 // provided, and overwrite the values set in it.
529 colorPalette.update(colors)
530 CompositionLocalProvider(localFirefoxColors provides colorPalette, content = content)
533 private val localFirefoxColors = staticCompositionLocalOf<FirefoxColors> {
534 error("No FirefoxColors provided")