1use frus_core::Color;
6
7use crate::media::{Brightness, MediaQuery};
8use crate::Theme;
9
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
20pub enum CupertinoUserInterfaceLevelData {
21 #[default]
23 Base,
24 Elevated,
26}
27
28impl CupertinoUserInterfaceLevelData {
29 pub fn around<Msg: 'static>(
32 self,
33 child: impl crate::Widget<Msg> + 'static,
34 ) -> crate::Themed<Msg> {
35 crate::Themed::tweak(move |t| t.user_interface_level = self, child)
36 }
37
38 pub fn of(theme: &Theme) -> Self {
40 theme.user_interface_level
41 }
42}
43
44#[derive(Clone, Copy, Debug)]
66pub struct CupertinoDynamicColor {
67 pub color: Color,
69 pub dark_color: Color,
71 pub high_contrast_color: Color,
73 pub dark_high_contrast_color: Color,
75 pub elevated_color: Color,
77 pub dark_elevated_color: Color,
79 pub high_contrast_elevated_color: Color,
81 pub dark_high_contrast_elevated_color: Color,
83 pub debug_label: Option<&'static str>,
85}
86
87impl CupertinoDynamicColor {
88 #[allow(clippy::too_many_arguments)]
90 pub const fn new(
91 color: Color,
92 dark_color: Color,
93 high_contrast_color: Color,
94 dark_high_contrast_color: Color,
95 elevated_color: Color,
96 dark_elevated_color: Color,
97 high_contrast_elevated_color: Color,
98 dark_high_contrast_elevated_color: Color,
99 ) -> Self {
100 Self {
101 color,
102 dark_color,
103 high_contrast_color,
104 dark_high_contrast_color,
105 elevated_color,
106 dark_elevated_color,
107 high_contrast_elevated_color,
108 dark_high_contrast_elevated_color,
109 debug_label: None,
110 }
111 }
112
113 pub const fn with_brightness_and_contrast(
116 color: Color,
117 dark_color: Color,
118 high_contrast_color: Color,
119 dark_high_contrast_color: Color,
120 ) -> Self {
121 Self::new(
122 color,
123 dark_color,
124 high_contrast_color,
125 dark_high_contrast_color,
126 color,
127 dark_color,
128 high_contrast_color,
129 dark_high_contrast_color,
130 )
131 }
132
133 pub const fn with_brightness(color: Color, dark_color: Color) -> Self {
135 Self::new(
136 color, dark_color, color, dark_color, color, dark_color, color, dark_color,
137 )
138 }
139
140 #[must_use]
142 pub const fn labelled(mut self, label: &'static str) -> Self {
143 self.debug_label = Some(label);
144 self
145 }
146
147 pub fn resolve_with(
150 &self,
151 brightness: Brightness,
152 level: CupertinoUserInterfaceLevelData,
153 high_contrast: bool,
154 ) -> Color {
155 use CupertinoUserInterfaceLevelData::{Base, Elevated};
156 match (brightness, level, high_contrast) {
157 (Brightness::Light, Base, false) => self.color,
158 (Brightness::Light, Base, true) => self.high_contrast_color,
159 (Brightness::Light, Elevated, false) => self.elevated_color,
160 (Brightness::Light, Elevated, true) => self.high_contrast_elevated_color,
161 (Brightness::Dark, Base, false) => self.dark_color,
162 (Brightness::Dark, Base, true) => self.dark_high_contrast_color,
163 (Brightness::Dark, Elevated, false) => self.dark_elevated_color,
164 (Brightness::Dark, Elevated, true) => self.dark_high_contrast_elevated_color,
165 }
166 }
167
168 pub fn resolve(&self, theme: &Theme) -> Color {
178 self.resolve_with(
179 crate::CupertinoTheme::brightness_of(theme),
180 theme.user_interface_level,
181 MediaQuery::of().accessibility.high_contrast,
182 )
183 }
184}
185
186impl PartialEq for CupertinoDynamicColor {
188 fn eq(&self, other: &Self) -> bool {
189 self.color == other.color
190 && self.dark_color == other.dark_color
191 && self.high_contrast_color == other.high_contrast_color
192 && self.dark_high_contrast_color == other.dark_high_contrast_color
193 && self.elevated_color == other.elevated_color
194 && self.dark_elevated_color == other.dark_elevated_color
195 && self.high_contrast_elevated_color == other.high_contrast_elevated_color
196 && self.dark_high_contrast_elevated_color == other.dark_high_contrast_elevated_color
197 }
198}
199
200impl From<Color> for CupertinoDynamicColor {
203 fn from(c: Color) -> Self {
204 Self::with_brightness(c, c)
205 }
206}
207
208impl From<CupertinoDynamicColor> for Color {
210 fn from(c: CupertinoDynamicColor) -> Color {
211 c.color
212 }
213}
214
215pub struct CupertinoColors;
228
229impl CupertinoColors {
230 pub const ACTIVE_BLUE: CupertinoDynamicColor = Self::SYSTEM_BLUE;
232
233 pub const ACTIVE_GREEN: CupertinoDynamicColor = Self::SYSTEM_GREEN;
235
236 pub const ACTIVE_ORANGE: CupertinoDynamicColor = Self::SYSTEM_ORANGE;
238
239 pub const WHITE: Color = Color::from_argb_u32(0xFFFFFFFF);
241
242 pub const BLACK: Color = Color::from_argb_u32(0xFF000000);
244
245 pub const TRANSPARENT: Color = Color::from_argb_u32(0x00000000);
247
248 pub const LIGHT_BACKGROUND_GRAY: Color = Color::from_argb_u32(0xFFE5E5EA);
250
251 pub const EXTRA_LIGHT_BACKGROUND_GRAY: Color = Color::from_argb_u32(0xFFEFEFF4);
253
254 pub const DARK_BACKGROUND_GRAY: Color = Color::from_argb_u32(0xFF171717);
256
257 pub const INACTIVE_GRAY: CupertinoDynamicColor = CupertinoDynamicColor::with_brightness(
259 Color::from_argb_u32(0xFF999999),
260 Color::from_argb_u32(0xFF757575),
261 )
262 .labelled("inactiveGray");
263
264 pub const DESTRUCTIVE_RED: CupertinoDynamicColor = Self::SYSTEM_RED;
266
267 pub const SYSTEM_BLUE: CupertinoDynamicColor =
269 CupertinoDynamicColor::with_brightness_and_contrast(
270 Color::rgba8(0, 122, 255, 255),
271 Color::rgba8(10, 132, 255, 255),
272 Color::rgba8(0, 64, 221, 255),
273 Color::rgba8(64, 156, 255, 255),
274 )
275 .labelled("systemBlue");
276
277 pub const SYSTEM_GREEN: CupertinoDynamicColor =
279 CupertinoDynamicColor::with_brightness_and_contrast(
280 Color::rgba8(52, 199, 89, 255),
281 Color::rgba8(48, 209, 88, 255),
282 Color::rgba8(36, 138, 61, 255),
283 Color::rgba8(48, 219, 91, 255),
284 )
285 .labelled("systemGreen");
286
287 pub const SYSTEM_MINT: CupertinoDynamicColor =
289 CupertinoDynamicColor::with_brightness_and_contrast(
290 Color::rgba8(0, 199, 190, 255),
291 Color::rgba8(99, 230, 226, 255),
292 Color::rgba8(12, 129, 123, 255),
293 Color::rgba8(102, 212, 207, 255),
294 )
295 .labelled("systemMint");
296
297 pub const SYSTEM_INDIGO: CupertinoDynamicColor =
299 CupertinoDynamicColor::with_brightness_and_contrast(
300 Color::rgba8(88, 86, 214, 255),
301 Color::rgba8(94, 92, 230, 255),
302 Color::rgba8(54, 52, 163, 255),
303 Color::rgba8(125, 122, 255, 255),
304 )
305 .labelled("systemIndigo");
306
307 pub const SYSTEM_ORANGE: CupertinoDynamicColor =
309 CupertinoDynamicColor::with_brightness_and_contrast(
310 Color::rgba8(255, 149, 0, 255),
311 Color::rgba8(255, 159, 10, 255),
312 Color::rgba8(201, 52, 0, 255),
313 Color::rgba8(255, 179, 64, 255),
314 )
315 .labelled("systemOrange");
316
317 pub const SYSTEM_PINK: CupertinoDynamicColor =
319 CupertinoDynamicColor::with_brightness_and_contrast(
320 Color::rgba8(255, 45, 85, 255),
321 Color::rgba8(255, 55, 95, 255),
322 Color::rgba8(211, 15, 69, 255),
323 Color::rgba8(255, 100, 130, 255),
324 )
325 .labelled("systemPink");
326
327 pub const SYSTEM_BROWN: CupertinoDynamicColor =
329 CupertinoDynamicColor::with_brightness_and_contrast(
330 Color::rgba8(162, 132, 94, 255),
331 Color::rgba8(172, 142, 104, 255),
332 Color::rgba8(127, 101, 69, 255),
333 Color::rgba8(181, 148, 105, 255),
334 )
335 .labelled("systemBrown");
336
337 pub const SYSTEM_PURPLE: CupertinoDynamicColor =
339 CupertinoDynamicColor::with_brightness_and_contrast(
340 Color::rgba8(175, 82, 222, 255),
341 Color::rgba8(191, 90, 242, 255),
342 Color::rgba8(137, 68, 171, 255),
343 Color::rgba8(218, 143, 255, 255),
344 )
345 .labelled("systemPurple");
346
347 pub const SYSTEM_RED: CupertinoDynamicColor =
349 CupertinoDynamicColor::with_brightness_and_contrast(
350 Color::rgba8(255, 59, 48, 255),
351 Color::rgba8(255, 69, 58, 255),
352 Color::rgba8(215, 0, 21, 255),
353 Color::rgba8(255, 105, 97, 255),
354 )
355 .labelled("systemRed");
356
357 pub const SYSTEM_TEAL: CupertinoDynamicColor =
359 CupertinoDynamicColor::with_brightness_and_contrast(
360 Color::rgba8(90, 200, 250, 255),
361 Color::rgba8(100, 210, 255, 255),
362 Color::rgba8(0, 113, 164, 255),
363 Color::rgba8(112, 215, 255, 255),
364 )
365 .labelled("systemTeal");
366
367 pub const SYSTEM_CYAN: CupertinoDynamicColor =
369 CupertinoDynamicColor::with_brightness_and_contrast(
370 Color::rgba8(50, 173, 230, 255),
371 Color::rgba8(100, 210, 255, 255),
372 Color::rgba8(0, 113, 164, 255),
373 Color::rgba8(112, 215, 255, 255),
374 )
375 .labelled("systemCyan");
376
377 pub const SYSTEM_YELLOW: CupertinoDynamicColor =
379 CupertinoDynamicColor::with_brightness_and_contrast(
380 Color::rgba8(255, 204, 0, 255),
381 Color::rgba8(255, 214, 10, 255),
382 Color::rgba8(160, 90, 0, 255),
383 Color::rgba8(255, 212, 38, 255),
384 )
385 .labelled("systemYellow");
386
387 pub const SYSTEM_GREY: CupertinoDynamicColor =
389 CupertinoDynamicColor::with_brightness_and_contrast(
390 Color::rgba8(142, 142, 147, 255),
391 Color::rgba8(142, 142, 147, 255),
392 Color::rgba8(108, 108, 112, 255),
393 Color::rgba8(174, 174, 178, 255),
394 )
395 .labelled("systemGrey");
396
397 pub const SYSTEM_GREY_2: CupertinoDynamicColor =
399 CupertinoDynamicColor::with_brightness_and_contrast(
400 Color::rgba8(174, 174, 178, 255),
401 Color::rgba8(99, 99, 102, 255),
402 Color::rgba8(142, 142, 147, 255),
403 Color::rgba8(124, 124, 128, 255),
404 )
405 .labelled("systemGrey2");
406
407 pub const SYSTEM_GREY_3: CupertinoDynamicColor =
409 CupertinoDynamicColor::with_brightness_and_contrast(
410 Color::rgba8(199, 199, 204, 255),
411 Color::rgba8(72, 72, 74, 255),
412 Color::rgba8(174, 174, 178, 255),
413 Color::rgba8(84, 84, 86, 255),
414 )
415 .labelled("systemGrey3");
416
417 pub const SYSTEM_GREY_4: CupertinoDynamicColor =
419 CupertinoDynamicColor::with_brightness_and_contrast(
420 Color::rgba8(209, 209, 214, 255),
421 Color::rgba8(58, 58, 60, 255),
422 Color::rgba8(188, 188, 192, 255),
423 Color::rgba8(68, 68, 70, 255),
424 )
425 .labelled("systemGrey4");
426
427 pub const SYSTEM_GREY_5: CupertinoDynamicColor =
429 CupertinoDynamicColor::with_brightness_and_contrast(
430 Color::rgba8(229, 229, 234, 255),
431 Color::rgba8(44, 44, 46, 255),
432 Color::rgba8(216, 216, 220, 255),
433 Color::rgba8(54, 54, 56, 255),
434 )
435 .labelled("systemGrey5");
436
437 pub const SYSTEM_GREY_6: CupertinoDynamicColor =
439 CupertinoDynamicColor::with_brightness_and_contrast(
440 Color::rgba8(242, 242, 247, 255),
441 Color::rgba8(28, 28, 30, 255),
442 Color::rgba8(235, 235, 240, 255),
443 Color::rgba8(36, 36, 38, 255),
444 )
445 .labelled("systemGrey6");
446
447 pub const LABEL: CupertinoDynamicColor = CupertinoDynamicColor::new(
449 Color::rgba8(0, 0, 0, 255),
450 Color::rgba8(255, 255, 255, 255),
451 Color::rgba8(0, 0, 0, 255),
452 Color::rgba8(255, 255, 255, 255),
453 Color::rgba8(0, 0, 0, 255),
454 Color::rgba8(255, 255, 255, 255),
455 Color::rgba8(0, 0, 0, 255),
456 Color::rgba8(255, 255, 255, 255),
457 )
458 .labelled("label");
459
460 pub const SECONDARY_LABEL: CupertinoDynamicColor = CupertinoDynamicColor::new(
462 Color::rgba8(60, 60, 67, 153),
463 Color::rgba8(235, 235, 245, 153),
464 Color::rgba8(60, 60, 67, 173),
465 Color::rgba8(235, 235, 245, 173),
466 Color::rgba8(60, 60, 67, 153),
467 Color::rgba8(235, 235, 245, 153),
468 Color::rgba8(60, 60, 67, 173),
469 Color::rgba8(235, 235, 245, 173),
470 )
471 .labelled("secondaryLabel");
472
473 pub const TERTIARY_LABEL: CupertinoDynamicColor = CupertinoDynamicColor::new(
475 Color::rgba8(60, 60, 67, 76),
476 Color::rgba8(235, 235, 245, 76),
477 Color::rgba8(60, 60, 67, 96),
478 Color::rgba8(235, 235, 245, 96),
479 Color::rgba8(60, 60, 67, 76),
480 Color::rgba8(235, 235, 245, 76),
481 Color::rgba8(60, 60, 67, 96),
482 Color::rgba8(235, 235, 245, 96),
483 )
484 .labelled("tertiaryLabel");
485
486 pub const QUATERNARY_LABEL: CupertinoDynamicColor = CupertinoDynamicColor::new(
488 Color::rgba8(60, 60, 67, 45),
489 Color::rgba8(235, 235, 245, 40),
490 Color::rgba8(60, 60, 67, 66),
491 Color::rgba8(235, 235, 245, 61),
492 Color::rgba8(60, 60, 67, 45),
493 Color::rgba8(235, 235, 245, 40),
494 Color::rgba8(60, 60, 67, 66),
495 Color::rgba8(235, 235, 245, 61),
496 )
497 .labelled("quaternaryLabel");
498
499 pub const SYSTEM_FILL: CupertinoDynamicColor = CupertinoDynamicColor::new(
501 Color::rgba8(120, 120, 128, 51),
502 Color::rgba8(120, 120, 128, 91),
503 Color::rgba8(120, 120, 128, 71),
504 Color::rgba8(120, 120, 128, 112),
505 Color::rgba8(120, 120, 128, 51),
506 Color::rgba8(120, 120, 128, 91),
507 Color::rgba8(120, 120, 128, 71),
508 Color::rgba8(120, 120, 128, 112),
509 )
510 .labelled("systemFill");
511
512 pub const SECONDARY_SYSTEM_FILL: CupertinoDynamicColor = CupertinoDynamicColor::new(
514 Color::rgba8(120, 120, 128, 40),
515 Color::rgba8(120, 120, 128, 81),
516 Color::rgba8(120, 120, 128, 61),
517 Color::rgba8(120, 120, 128, 102),
518 Color::rgba8(120, 120, 128, 40),
519 Color::rgba8(120, 120, 128, 81),
520 Color::rgba8(120, 120, 128, 61),
521 Color::rgba8(120, 120, 128, 102),
522 )
523 .labelled("secondarySystemFill");
524
525 pub const TERTIARY_SYSTEM_FILL: CupertinoDynamicColor = CupertinoDynamicColor::new(
527 Color::rgba8(118, 118, 128, 30),
528 Color::rgba8(118, 118, 128, 61),
529 Color::rgba8(118, 118, 128, 51),
530 Color::rgba8(118, 118, 128, 81),
531 Color::rgba8(118, 118, 128, 30),
532 Color::rgba8(118, 118, 128, 61),
533 Color::rgba8(118, 118, 128, 51),
534 Color::rgba8(118, 118, 128, 81),
535 )
536 .labelled("tertiarySystemFill");
537
538 pub const QUATERNARY_SYSTEM_FILL: CupertinoDynamicColor = CupertinoDynamicColor::new(
540 Color::rgba8(116, 116, 128, 20),
541 Color::rgba8(118, 118, 128, 45),
542 Color::rgba8(116, 116, 128, 40),
543 Color::rgba8(118, 118, 128, 66),
544 Color::rgba8(116, 116, 128, 20),
545 Color::rgba8(118, 118, 128, 45),
546 Color::rgba8(116, 116, 128, 40),
547 Color::rgba8(118, 118, 128, 66),
548 )
549 .labelled("quaternarySystemFill");
550
551 pub const PLACEHOLDER_TEXT: CupertinoDynamicColor = CupertinoDynamicColor::new(
553 Color::rgba8(60, 60, 67, 76),
554 Color::rgba8(235, 235, 245, 76),
555 Color::rgba8(60, 60, 67, 96),
556 Color::rgba8(235, 235, 245, 96),
557 Color::rgba8(60, 60, 67, 76),
558 Color::rgba8(235, 235, 245, 76),
559 Color::rgba8(60, 60, 67, 96),
560 Color::rgba8(235, 235, 245, 96),
561 )
562 .labelled("placeholderText");
563
564 pub const SYSTEM_BACKGROUND: CupertinoDynamicColor = CupertinoDynamicColor::new(
566 Color::rgba8(255, 255, 255, 255),
567 Color::rgba8(0, 0, 0, 255),
568 Color::rgba8(255, 255, 255, 255),
569 Color::rgba8(0, 0, 0, 255),
570 Color::rgba8(255, 255, 255, 255),
571 Color::rgba8(28, 28, 30, 255),
572 Color::rgba8(255, 255, 255, 255),
573 Color::rgba8(36, 36, 38, 255),
574 )
575 .labelled("systemBackground");
576
577 pub const SECONDARY_SYSTEM_BACKGROUND: CupertinoDynamicColor = CupertinoDynamicColor::new(
579 Color::rgba8(242, 242, 247, 255),
580 Color::rgba8(28, 28, 30, 255),
581 Color::rgba8(235, 235, 240, 255),
582 Color::rgba8(36, 36, 38, 255),
583 Color::rgba8(242, 242, 247, 255),
584 Color::rgba8(44, 44, 46, 255),
585 Color::rgba8(235, 235, 240, 255),
586 Color::rgba8(54, 54, 56, 255),
587 )
588 .labelled("secondarySystemBackground");
589
590 pub const TERTIARY_SYSTEM_BACKGROUND: CupertinoDynamicColor = CupertinoDynamicColor::new(
592 Color::rgba8(255, 255, 255, 255),
593 Color::rgba8(44, 44, 46, 255),
594 Color::rgba8(255, 255, 255, 255),
595 Color::rgba8(54, 54, 56, 255),
596 Color::rgba8(255, 255, 255, 255),
597 Color::rgba8(58, 58, 60, 255),
598 Color::rgba8(255, 255, 255, 255),
599 Color::rgba8(68, 68, 70, 255),
600 )
601 .labelled("tertiarySystemBackground");
602
603 pub const SYSTEM_GROUPED_BACKGROUND: CupertinoDynamicColor = CupertinoDynamicColor::new(
605 Color::rgba8(242, 242, 247, 255),
606 Color::rgba8(0, 0, 0, 255),
607 Color::rgba8(235, 235, 240, 255),
608 Color::rgba8(0, 0, 0, 255),
609 Color::rgba8(242, 242, 247, 255),
610 Color::rgba8(28, 28, 30, 255),
611 Color::rgba8(235, 235, 240, 255),
612 Color::rgba8(36, 36, 38, 255),
613 )
614 .labelled("systemGroupedBackground");
615
616 pub const SECONDARY_SYSTEM_GROUPED_BACKGROUND: CupertinoDynamicColor =
618 CupertinoDynamicColor::new(
619 Color::rgba8(255, 255, 255, 255),
620 Color::rgba8(28, 28, 30, 255),
621 Color::rgba8(255, 255, 255, 255),
622 Color::rgba8(36, 36, 38, 255),
623 Color::rgba8(255, 255, 255, 255),
624 Color::rgba8(44, 44, 46, 255),
625 Color::rgba8(255, 255, 255, 255),
626 Color::rgba8(54, 54, 56, 255),
627 )
628 .labelled("secondarySystemGroupedBackground");
629
630 pub const TERTIARY_SYSTEM_GROUPED_BACKGROUND: CupertinoDynamicColor =
632 CupertinoDynamicColor::new(
633 Color::rgba8(242, 242, 247, 255),
634 Color::rgba8(44, 44, 46, 255),
635 Color::rgba8(235, 235, 240, 255),
636 Color::rgba8(54, 54, 56, 255),
637 Color::rgba8(242, 242, 247, 255),
638 Color::rgba8(58, 58, 60, 255),
639 Color::rgba8(235, 235, 240, 255),
640 Color::rgba8(68, 68, 70, 255),
641 )
642 .labelled("tertiarySystemGroupedBackground");
643
644 pub const SEPARATOR: CupertinoDynamicColor = CupertinoDynamicColor::new(
646 Color::rgba8(60, 60, 67, 73),
647 Color::rgba8(84, 84, 88, 153),
648 Color::rgba8(60, 60, 67, 94),
649 Color::rgba8(84, 84, 88, 173),
650 Color::rgba8(60, 60, 67, 73),
651 Color::rgba8(210, 210, 210, 153),
652 Color::rgba8(60, 60, 67, 94),
653 Color::rgba8(84, 84, 88, 173),
654 )
655 .labelled("separator");
656
657 pub const OPAQUE_SEPARATOR: CupertinoDynamicColor = CupertinoDynamicColor::new(
659 Color::rgba8(198, 198, 200, 255),
660 Color::rgba8(56, 56, 58, 255),
661 Color::rgba8(198, 198, 200, 255),
662 Color::rgba8(56, 56, 58, 255),
663 Color::rgba8(198, 198, 200, 255),
664 Color::rgba8(56, 56, 58, 255),
665 Color::rgba8(198, 198, 200, 255),
666 Color::rgba8(56, 56, 58, 255),
667 )
668 .labelled("opaqueSeparator");
669
670 pub const LINK: CupertinoDynamicColor = CupertinoDynamicColor::new(
672 Color::rgba8(0, 122, 255, 255),
673 Color::rgba8(9, 132, 255, 255),
674 Color::rgba8(0, 122, 255, 255),
675 Color::rgba8(9, 132, 255, 255),
676 Color::rgba8(0, 122, 255, 255),
677 Color::rgba8(9, 132, 255, 255),
678 Color::rgba8(0, 122, 255, 255),
679 Color::rgba8(9, 132, 255, 255),
680 )
681 .labelled("link");
682}
683
684#[cfg(test)]
685mod tests {
686 use super::{CupertinoColors as C, CupertinoDynamicColor, CupertinoUserInterfaceLevelData};
687 use crate::media::{Accessibility, Brightness, MediaQuery};
688 use crate::{build_ui, Container, Flex, Runtime, Theme, ThemeBuilder, Widget};
689 use frus_core::{Color, Primitive, Size};
690 use CupertinoUserInterfaceLevelData::{Base, Elevated};
691
692 #[derive(Clone, Debug, PartialEq)]
693 enum Msg {}
694
695 #[test]
698 fn each_condition_picks_its_value() {
699 let v: Vec<Color> = (0..8).map(|i| Color::rgb8(i * 10, 0, 0)).collect();
700 let c = CupertinoDynamicColor::new(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
701 let light = Brightness::Light;
702 let dark = Brightness::Dark;
703 assert_eq!(c.resolve_with(light, Base, false), v[0]);
704 assert_eq!(c.resolve_with(dark, Base, false), v[1]);
705 assert_eq!(c.resolve_with(light, Base, true), v[2]);
706 assert_eq!(c.resolve_with(dark, Base, true), v[3]);
707 assert_eq!(c.resolve_with(light, Elevated, false), v[4]);
708 assert_eq!(c.resolve_with(dark, Elevated, false), v[5]);
709 assert_eq!(c.resolve_with(light, Elevated, true), v[6]);
710 assert_eq!(c.resolve_with(dark, Elevated, true), v[7]);
711 assert_eq!(Color::from(c), v[0]);
713 }
714
715 #[test]
718 fn the_shorter_constructors_fill_the_other_axes() {
719 let [a, b, c, d] = [1, 2, 3, 4].map(|i| Color::rgb8(i, 0, 0));
720 assert_eq!(
721 CupertinoDynamicColor::with_brightness_and_contrast(a, b, c, d),
722 CupertinoDynamicColor::new(a, b, c, d, a, b, c, d)
723 );
724 assert_eq!(
725 CupertinoDynamicColor::with_brightness(a, b),
726 CupertinoDynamicColor::new(a, b, a, b, a, b, a, b)
727 );
728 assert_eq!(
730 CupertinoDynamicColor::with_brightness(a, b).labelled("ink"),
731 CupertinoDynamicColor::with_brightness(a, b)
732 );
733 }
734
735 #[test]
739 fn the_palette_is_the_reference_s() {
740 let rgba = Color::rgba8;
741 assert_eq!(
742 C::SYSTEM_BLUE,
743 CupertinoDynamicColor::with_brightness_and_contrast(
744 rgba(0, 122, 255, 255),
745 rgba(10, 132, 255, 255),
746 rgba(0, 64, 221, 255),
747 rgba(64, 156, 255, 255),
748 )
749 );
750 assert_eq!(C::SYSTEM_BLUE.debug_label, Some("systemBlue"));
751 assert_eq!(C::ACTIVE_BLUE, C::SYSTEM_BLUE);
752 assert_eq!(C::ACTIVE_GREEN, C::SYSTEM_GREEN);
753 assert_eq!(C::ACTIVE_ORANGE, C::SYSTEM_ORANGE);
754 assert_eq!(C::DESTRUCTIVE_RED, C::SYSTEM_RED);
755 assert_eq!(C::SECONDARY_LABEL.color, rgba(60, 60, 67, 153));
756 assert_eq!(
757 C::SECONDARY_LABEL.dark_high_contrast_color,
758 rgba(235, 235, 245, 173)
759 );
760 assert_eq!(C::SYSTEM_BACKGROUND.dark_color, rgba(0, 0, 0, 255));
761 assert_eq!(
762 C::SYSTEM_BACKGROUND.dark_elevated_color,
763 rgba(28, 28, 30, 255)
764 );
765 assert_eq!(
766 C::SYSTEM_BACKGROUND.dark_high_contrast_elevated_color,
767 rgba(36, 36, 38, 255)
768 );
769 assert_eq!(C::SEPARATOR.dark_elevated_color, rgba(210, 210, 210, 153));
770 assert_eq!(C::SYSTEM_GREY_6.color, rgba(242, 242, 247, 255));
771 assert_eq!(
772 C::INACTIVE_GRAY.dark_color,
773 Color::from_argb_u32(0xFF757575)
774 );
775 assert_eq!(
776 C::EXTRA_LIGHT_BACKGROUND_GRAY,
777 Color::from_argb_u32(0xFFEFEFF4)
778 );
779 }
780
781 #[test]
784 fn resolve_reads_the_theme_and_the_surface() {
785 let bg = C::SYSTEM_BACKGROUND;
786 assert_eq!(bg.resolve(&Theme::light()), bg.color);
787 assert_eq!(bg.resolve(&Theme::dark()), bg.dark_color);
788 let mut raised = Theme::dark();
789 raised.user_interface_level = Elevated;
790 assert_eq!(bg.resolve(&raised), bg.dark_elevated_color);
791 let mut surface = MediaQuery::new(Size::new(100.0, 100.0));
792 surface.accessibility = Accessibility {
793 high_contrast: true,
794 ..Accessibility::NONE
795 };
796 surface.scope(|| {
797 assert_eq!(bg.resolve(&raised), bg.dark_high_contrast_elevated_color);
798 assert_eq!(
799 C::LABEL.resolve(&Theme::light()),
800 C::LABEL.high_contrast_color
801 );
802 });
803 }
804
805 #[test]
808 fn a_raised_subtree_resolves_raised() {
809 assert_eq!(Theme::default().user_interface_level, Base);
810 let mut raised = Theme::dark();
811 raised.user_interface_level = Elevated;
812 assert_eq!(raised.lerp(&raised, 0.3).user_interface_level, Elevated);
813 assert_eq!(
814 Theme::dark().lerp(&raised, 0.7).user_interface_level,
815 Elevated
816 );
817 assert_eq!(Theme::dark().lerp(&raised, 0.3).user_interface_level, Base);
818
819 let swatch = || {
820 ThemeBuilder::new(|t: &Theme| {
821 Container::new()
822 .width(50.0)
823 .height(50.0)
824 .color(C::SYSTEM_BACKGROUND.resolve(t))
825 })
826 };
827 let tree = Flex::<Msg>::column()
828 .width(200.0)
829 .height(200.0)
830 .child(swatch())
831 .child(Elevated.around(swatch()));
832 let painted: Vec<Color> = build_ui(
833 &tree as &dyn Widget<Msg>,
834 Size::new(200.0, 200.0),
835 &Runtime::default(),
836 &Theme::dark(),
837 )
838 .scene()
839 .primitives()
840 .iter()
841 .filter_map(|p| match p {
842 Primitive::Rect { color, blur, .. } if *blur == 0.0 => Some(*color),
843 _ => None,
844 })
845 .collect();
846 assert_eq!(
847 painted,
848 vec![
849 C::SYSTEM_BACKGROUND.dark_color,
850 C::SYSTEM_BACKGROUND.dark_elevated_color
851 ]
852 );
853 assert_eq!(CupertinoUserInterfaceLevelData::of(&raised), Elevated);
854 }
855}