diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index e3b94c2e..ef807ff3 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -14,6 +14,6 @@ jobs: - uses: subosito/flutter-action@v2 with: cache: true - - uses: ZebraDevs/flutter-code-quality@v1.0.1 + - uses: ZebraDevs/flutter-code-quality@v1.0.3 with: token: ${{secrets.GITHUB_TOKEN}} diff --git a/coverage/lcov.info b/coverage/lcov.info index 913cd03b..eaaa72d0 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -11,8 +11,8 @@ DA:48,2 DA:57,3 DA:59,3 DA:61,2 -DA:70,2 -DA:72,2 +DA:70,3 +DA:72,3 DA:74,2 DA:83,2 DA:85,2 @@ -181,29 +181,28 @@ LF:74 LH:53 end_of_record SF:lib/src/utils/rounded.dart -DA:11,8 -DA:21,13 -DA:22,13 -DA:25,2 -DA:26,6 +DA:9,8 +DA:19,13 +DA:20,13 +DA:23,2 +DA:24,6 +DA:25,1 DA:27,1 -DA:29,1 -DA:30,3 -DA:37,227 -DA:42,8 -DA:44,8 -DA:45,24 -DA:52,5 -DA:57,3 -DA:59,3 -DA:60,9 -DA:67,14 -DA:69,46 -DA:70,12 -DA:73,16 -DA:76,43 -LF:21 -LH:21 +DA:28,3 +DA:35,227 +DA:40,9 +DA:42,9 +DA:43,27 +DA:50,7 +DA:55,4 +DA:57,4 +DA:58,12 +DA:65,14 +DA:67,46 +DA:68,12 +DA:74,43 +LF:20 +LH:20 end_of_record SF:lib/src/components/avatars/avatar.dart DA:39,0 @@ -422,33 +421,36 @@ LH:58 end_of_record SF:lib/src/components/badges/label.dart DA:15,1 -DA:32,1 -DA:34,2 -DA:36,1 -DA:38,1 DA:40,1 -DA:42,1 -DA:43,1 -DA:44,2 +DA:42,2 +DA:44,1 +DA:45,2 +DA:46,1 +DA:48,1 DA:50,1 DA:52,1 -DA:54,3 -DA:55,3 -DA:56,3 +DA:53,1 +DA:54,2 DA:61,1 -DA:62,2 -DA:64,1 -DA:65,1 -DA:66,1 -DA:67,1 -DA:68,1 -DA:69,2 -DA:70,1 -DA:71,1 -DA:72,1 -DA:73,2 -LF:26 -LH:26 +DA:63,1 +DA:65,3 +DA:66,3 +DA:67,3 +DA:68,3 +DA:73,1 +DA:74,2 +DA:76,1 +DA:77,1 +DA:78,1 +DA:79,1 +DA:80,1 +DA:81,2 +DA:82,1 +DA:83,1 +DA:84,1 +DA:85,2 +LF:29 +LH:29 end_of_record SF:lib/src/components/badges/priority_pill.dart DA:33,1 @@ -462,176 +464,185 @@ DA:41,1 DA:42,1 DA:43,1 DA:51,1 -DA:97,1 -DA:99,3 -DA:100,2 -DA:101,2 -DA:102,1 -DA:103,1 -DA:104,1 -DA:106,1 -DA:108,1 +DA:105,1 +DA:107,3 +DA:108,2 +DA:109,5 DA:110,1 -DA:111,1 +DA:112,1 +DA:113,1 +DA:114,1 DA:115,1 +DA:117,1 DA:119,1 -DA:120,2 -DA:121,2 -DA:122,4 -DA:123,3 -DA:124,3 -DA:125,2 +DA:121,1 +DA:122,1 DA:126,1 -DA:128,1 -DA:129,1 +DA:130,1 DA:131,2 -DA:134,1 -DA:135,1 +DA:132,2 +DA:133,4 +DA:134,3 +DA:135,3 +DA:136,2 +DA:137,1 +DA:139,1 DA:140,1 -DA:141,4 DA:142,2 -DA:143,1 DA:145,1 +DA:146,1 +DA:151,1 +DA:153,2 +DA:154,1 DA:156,1 -DA:158,1 -DA:160,3 -DA:161,3 -DA:162,3 -DA:163,3 -DA:164,3 -DA:165,3 -DA:166,3 -DA:167,3 -LF:51 -LH:51 +DA:168,1 +DA:170,1 +DA:172,3 +DA:173,3 +DA:174,3 +DA:175,3 +DA:176,3 +DA:177,3 +DA:178,3 +DA:179,3 +DA:180,3 +LF:53 +LH:53 end_of_record SF:lib/src/components/badges/status_label.dart DA:11,2 -DA:28,2 -DA:30,4 -DA:32,2 -DA:33,2 -DA:34,2 -DA:35,4 DA:36,2 -DA:38,2 +DA:38,4 DA:40,2 +DA:41,4 DA:42,2 DA:43,2 DA:44,2 -DA:45,2 +DA:45,4 DA:46,2 -DA:49,2 +DA:48,2 DA:50,2 -DA:51,6 -DA:60,1 -DA:62,1 -DA:64,3 -DA:65,3 -DA:66,3 -DA:67,3 -LF:24 -LH:24 +DA:52,2 +DA:53,2 +DA:54,2 +DA:55,2 +DA:56,2 +DA:59,2 +DA:60,2 +DA:61,6 +DA:71,1 +DA:73,1 +DA:75,3 +DA:76,3 +DA:77,3 +DA:78,3 +DA:79,3 +LF:27 +LH:27 end_of_record SF:lib/src/components/badges/tag.dart DA:18,1 -DA:26,1 -DA:29,1 -DA:42,1 -DA:44,1 -DA:45,1 -DA:46,3 -DA:47,1 -DA:48,1 -DA:49,3 -DA:50,1 +DA:27,1 +DA:31,1 DA:52,1 -DA:53,2 DA:54,1 -DA:55,1 +DA:55,2 DA:56,1 -DA:58,1 +DA:57,1 +DA:58,3 DA:59,1 -DA:67,3 -DA:72,1 -DA:73,1 -DA:74,2 -DA:87,1 -DA:88,1 -DA:90,1 -DA:91,3 -DA:92,1 -DA:93,1 -DA:98,1 +DA:60,1 +DA:61,3 +DA:62,1 +DA:64,1 +DA:65,2 +DA:66,1 +DA:67,1 +DA:68,1 +DA:70,1 +DA:71,1 +DA:79,3 +DA:85,1 +DA:86,1 +DA:87,2 DA:100,1 -DA:102,3 -DA:103,3 +DA:101,1 +DA:103,1 DA:104,3 -DA:109,1 -DA:119,1 -DA:121,1 -DA:122,2 +DA:105,1 +DA:106,1 +DA:111,1 +DA:113,1 +DA:115,3 +DA:116,3 +DA:117,3 +DA:118,3 DA:123,1 -DA:124,4 -DA:126,1 -DA:129,1 +DA:133,1 +DA:135,1 +DA:136,2 DA:137,1 +DA:138,4 DA:140,1 -DA:141,2 -DA:142,1 -DA:145,6 -DA:146,1 -DA:147,2 -DA:148,2 -DA:149,2 -DA:150,3 -DA:151,2 -DA:152,2 -DA:155,4 -DA:159,2 -DA:160,3 -DA:161,1 -DA:166,0 -LF:58 -LH:57 +DA:143,1 +DA:151,1 +DA:154,1 +DA:155,2 +DA:156,1 +DA:159,6 +DA:160,1 +DA:161,2 +DA:162,2 +DA:163,2 +DA:164,3 +DA:165,2 +DA:166,2 +DA:169,4 +DA:173,2 +DA:174,3 +DA:175,1 +DA:180,0 +LF:61 +LH:60 end_of_record SF:lib/src/components/banner/banner.dart DA:37,0 -DA:46,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:54,0 -DA:55,0 -DA:56,0 -DA:57,0 -DA:59,0 +DA:63,0 DA:65,0 DA:66,0 DA:67,0 DA:68,0 +DA:69,0 +DA:71,0 DA:72,0 +DA:73,0 DA:74,0 DA:76,0 -DA:78,0 +DA:82,0 +DA:83,0 DA:84,0 +DA:86,0 +DA:87,0 DA:91,0 -DA:92,0 DA:93,0 -DA:94,0 -DA:100,0 -DA:101,0 -DA:104,0 -DA:105,0 -DA:106,0 -DA:107,0 -DA:108,0 -DA:109,0 -DA:110,0 +DA:95,0 +DA:97,0 +DA:103,0 DA:111,0 -LF:35 +DA:112,0 +DA:113,0 +DA:114,0 +DA:120,0 +DA:121,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +LF:36 LH:0 end_of_record SF:lib/src/components/bottom sheets/bottom_sheet.dart @@ -771,88 +782,98 @@ DA:107,0 DA:109,0 DA:110,0 DA:120,0 -DA:144,0 -DA:145,0 -DA:147,0 -DA:149,0 -DA:151,0 DA:152,0 DA:153,0 -DA:154,0 DA:155,0 +DA:157,0 +DA:159,0 +DA:160,0 +DA:161,0 DA:162,0 +DA:163,0 DA:164,0 -DA:165,0 -DA:166,0 -DA:167,0 -DA:172,0 +DA:171,0 +DA:173,0 DA:174,0 DA:175,0 DA:176,0 -DA:177,0 -DA:180,0 +DA:181,0 DA:183,0 DA:184,0 DA:185,0 DA:186,0 DA:187,0 DA:188,0 -DA:190,0 -DA:193,0 -DA:194,0 +DA:189,0 +DA:192,0 DA:195,0 -DA:203,0 -DA:204,0 +DA:196,0 +DA:197,0 +DA:198,0 +DA:199,0 +DA:200,0 +DA:202,0 DA:205,0 +DA:206,0 DA:207,0 -DA:208,0 -DA:211,0 -DA:213,0 -DA:214,0 -DA:215,0 +DA:216,0 DA:217,0 +DA:218,0 +DA:220,0 +DA:221,0 +DA:224,0 DA:226,0 -DA:234,0 -DA:235,0 -DA:241,0 -DA:243,0 -DA:244,0 -DA:246,0 -DA:247,0 -DA:248,0 -DA:249,0 -DA:250,0 -DA:251,0 +DA:227,0 +DA:228,0 +DA:230,0 +DA:239,0 +DA:253,0 DA:254,0 DA:255,0 -DA:256,0 DA:257,0 -DA:259,0 -DA:260,0 -DA:262,0 -DA:263,0 +DA:258,0 DA:265,0 DA:267,0 DA:268,0 -DA:269,0 +DA:270,0 DA:271,0 +DA:272,0 DA:273,0 -DA:274,0 +DA:275,0 +DA:276,0 +DA:277,0 DA:278,0 -DA:279,0 -DA:280,0 +DA:281,0 DA:282,0 -DA:285,0 +DA:283,0 +DA:284,0 DA:286,0 +DA:287,0 +DA:289,0 DA:290,0 -DA:291,0 -DA:297,0 +DA:292,0 +DA:294,0 +DA:295,0 +DA:296,0 +DA:298,0 +DA:300,0 DA:301,0 -DA:302,0 -DA:303,0 -DA:304,0 +DA:305,0 +DA:306,0 +DA:307,0 +DA:309,0 +DA:312,0 DA:313,0 -LF:128 +DA:317,0 +DA:318,0 +DA:321,0 +DA:324,0 +DA:329,0 +DA:330,0 +DA:331,0 +DA:332,0 +DA:341,0 +LF:138 LH:0 end_of_record SF:lib/src/components/button_group/button_group.dart @@ -877,198 +898,206 @@ DA:59,0 DA:60,0 DA:61,0 DA:70,0 -DA:85,0 -DA:101,0 -DA:116,0 -DA:165,0 -DA:166,0 -DA:169,0 +DA:86,0 +DA:103,0 +DA:119,0 DA:176,0 DA:177,0 -DA:178,0 -DA:179,0 DA:180,0 -DA:181,0 -DA:182,0 -DA:183,0 -DA:184,0 -DA:185,0 -DA:186,0 -DA:187,0 DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 DA:192,0 +DA:193,0 DA:194,0 +DA:195,0 DA:196,0 DA:197,0 DA:198,0 DA:199,0 DA:200,0 DA:201,0 -DA:202,0 -DA:203,0 -DA:204,0 DA:205,0 +DA:207,0 +DA:209,0 +DA:210,0 +DA:211,0 DA:212,0 +DA:213,0 DA:214,0 DA:215,0 +DA:216,0 +DA:217,0 DA:218,0 -DA:220,0 -DA:221,0 -DA:222,0 +DA:219,0 DA:226,0 DA:228,0 +DA:229,0 DA:232,0 -DA:233,0 +DA:234,0 DA:235,0 DA:236,0 -DA:238,0 -DA:239,0 -DA:243,0 -DA:244,0 -DA:245,0 +DA:240,0 +DA:242,0 +DA:246,0 +DA:247,0 +DA:249,0 DA:250,0 -DA:251,0 +DA:252,0 +DA:253,0 +DA:257,0 +DA:258,0 DA:259,0 -DA:260,0 -DA:261,0 -DA:262,0 -DA:263,0 -DA:266,0 -DA:267,0 -DA:268,0 -DA:270,0 -DA:271,0 +DA:264,0 +DA:265,0 DA:273,0 -DA:274,0 -DA:276,0 DA:278,0 -DA:280,0 +DA:279,0 DA:281,0 -DA:282,0 -DA:284,0 -DA:285,0 -DA:288,0 -DA:292,0 -DA:297,0 -DA:298,0 -DA:300,0 +DA:294,0 +DA:295,0 +DA:299,0 +DA:301,0 +DA:302,0 +DA:305,0 +DA:306,0 +DA:307,0 +DA:311,0 +DA:312,0 DA:313,0 -DA:314,0 -DA:318,0 +DA:317,0 DA:320,0 DA:321,0 +DA:322,0 DA:324,0 DA:325,0 DA:326,0 +DA:327,0 DA:330,0 DA:331,0 DA:332,0 -DA:336,0 -DA:339,0 +DA:334,0 +DA:335,0 +DA:337,0 +DA:338,0 DA:340,0 DA:342,0 -DA:343,0 DA:344,0 +DA:345,0 DA:346,0 DA:348,0 DA:349,0 -DA:350,0 +DA:352,0 DA:354,0 DA:355,0 +DA:357,0 +DA:359,0 +DA:360,0 DA:361,0 -DA:363,0 -DA:367,0 -DA:368,0 -DA:369,0 -DA:370,0 -DA:371,0 -DA:372,0 -DA:374,0 +DA:365,0 +DA:366,0 +DA:373,0 DA:375,0 -DA:376,0 -DA:377,0 +DA:379,0 +DA:380,0 +DA:381,0 +DA:382,0 DA:383,0 -DA:389,0 -DA:391,0 -DA:392,0 -LF:135 +DA:385,0 +DA:386,0 +DA:387,0 +DA:388,0 +DA:394,0 +DA:399,0 +DA:400,0 +DA:402,0 +DA:403,0 +DA:408,0 +DA:410,0 +DA:411,0 +LF:139 LH:0 end_of_record SF:lib/src/components/buttons/button.dart DA:9,3 -DA:22,1 -DA:34,1 -DA:46,1 -DA:58,1 -DA:70,1 -DA:82,1 -DA:94,2 -DA:133,1 -DA:143,1 -DA:144,1 -DA:145,1 -DA:146,0 -DA:147,0 -DA:148,1 -DA:149,1 -DA:150,1 -DA:151,1 -DA:155,2 -DA:157,4 -DA:158,2 -DA:159,6 -DA:160,2 -DA:161,2 -DA:162,2 -DA:163,2 -DA:165,4 -DA:166,2 -DA:169,2 +DA:23,1 +DA:36,1 +DA:49,1 +DA:62,1 +DA:75,1 +DA:88,1 +DA:101,2 +DA:148,1 +DA:158,1 +DA:159,1 +DA:160,1 +DA:161,0 +DA:162,0 +DA:163,1 +DA:164,1 +DA:165,1 +DA:166,1 DA:170,2 -DA:172,2 +DA:172,4 DA:173,2 -DA:174,1 -DA:175,1 -DA:176,1 -DA:178,4 -DA:179,2 +DA:175,2 +DA:176,4 +DA:178,2 +DA:179,6 DA:180,2 DA:181,2 +DA:182,2 DA:183,2 -DA:184,1 -DA:185,1 -DA:186,1 +DA:185,4 +DA:186,2 DA:189,2 -DA:194,2 -DA:195,4 -DA:201,6 +DA:190,2 +DA:192,2 +DA:193,2 +DA:194,1 +DA:195,1 +DA:196,1 +DA:198,4 +DA:199,2 +DA:200,2 +DA:201,2 DA:203,2 -DA:204,2 -DA:205,2 -DA:208,2 -DA:211,1 -DA:216,2 -DA:217,2 -DA:218,2 -DA:221,2 -DA:224,1 -DA:229,1 -DA:230,1 -DA:231,1 +DA:204,1 +DA:205,1 +DA:206,1 +DA:209,2 +DA:214,2 +DA:215,4 +DA:222,6 +DA:224,2 +DA:225,2 +DA:226,2 +DA:229,2 DA:232,1 -DA:234,1 -DA:239,1 -DA:241,1 -DA:243,3 -DA:244,3 -DA:245,3 -DA:246,3 -DA:247,3 -DA:248,3 -DA:249,3 -DA:250,3 -LF:72 -LH:70 +DA:237,2 +DA:238,2 +DA:239,2 +DA:242,2 +DA:245,1 +DA:250,1 +DA:251,1 +DA:252,1 +DA:253,1 +DA:255,1 +DA:260,1 +DA:262,1 +DA:264,3 +DA:265,3 +DA:266,3 +DA:267,3 +DA:268,3 +DA:269,3 +DA:270,3 +DA:271,3 +DA:272,3 +LF:76 +LH:74 end_of_record SF:lib/src/components/buttons/button_style.dart DA:40,2 @@ -1135,69 +1164,77 @@ LH:59 end_of_record SF:lib/src/components/buttons/icon_button.dart DA:9,0 -DA:19,0 -DA:28,0 -DA:37,0 -DA:46,0 -DA:55,0 -DA:64,0 -DA:73,0 -DA:99,0 -DA:101,0 -DA:103,0 -DA:104,0 -DA:105,0 -DA:107,0 -DA:108,0 -DA:111,0 -DA:115,0 -DA:116,0 -DA:117,0 -DA:119,0 -DA:121,0 +DA:21,0 +DA:32,0 +DA:43,0 +DA:54,0 +DA:65,0 +DA:76,0 +DA:87,0 +DA:120,0 +DA:122,0 +DA:124,0 +DA:125,0 DA:126,0 DA:127,0 DA:128,0 -DA:130,0 +DA:129,0 +DA:131,0 DA:132,0 -DA:137,0 -DA:139,0 +DA:135,0 DA:141,0 DA:142,0 DA:143,0 -DA:144,0 DA:145,0 -LF:33 +DA:147,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,0 +DA:158,0 +DA:163,0 +DA:165,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:172,0 +LF:37 LH:0 end_of_record SF:lib/src/components/buttons/input_icon_button.dart DA:9,0 -DA:35,0 -DA:36,0 -DA:37,0 -DA:39,0 DA:41,0 -DA:46,0 -DA:48,0 -DA:50,0 -DA:51,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:47,0 DA:52,0 -DA:53,0 DA:54,0 -DA:55,0 DA:56,0 DA:58,0 DA:59,0 -DA:60,0 DA:61,0 +DA:62,0 +DA:63,0 +DA:64,0 DA:65,0 +DA:66,0 DA:67,0 DA:69,0 DA:70,0 DA:71,0 DA:72,0 -DA:73,0 -LF:26 +DA:77,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +LF:30 LH:0 end_of_record SF:lib/src/components/chat_item/chat_item.dart @@ -1362,95 +1399,99 @@ LH:0 end_of_record SF:lib/src/components/checkbox/checkbox.dart DA:16,1 -DA:27,1 -DA:30,1 +DA:28,1 DA:31,1 -DA:33,1 +DA:32,1 DA:34,1 DA:35,1 -DA:40,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:73,1 -DA:75,3 -DA:76,3 -DA:77,3 -DA:78,3 -DA:79,3 -DA:80,3 -DA:86,1 -DA:87,1 -DA:95,1 -DA:130,1 -DA:131,1 -DA:132,1 -DA:134,1 -DA:136,3 -DA:137,3 -DA:138,3 -DA:139,3 -DA:140,3 -DA:141,3 -DA:142,3 -DA:143,3 -DA:148,3 -DA:153,1 -DA:154,2 -DA:155,2 -DA:156,1 -DA:161,1 -DA:163,1 -DA:165,1 -DA:166,7 -DA:168,1 -DA:170,1 -DA:171,2 -DA:172,2 -DA:174,1 -DA:175,2 -DA:176,2 -DA:177,2 -DA:178,2 -DA:179,1 -DA:180,2 -DA:181,4 +DA:36,1 +DA:41,1 +DA:78,1 +DA:79,1 +DA:80,1 +DA:82,1 +DA:84,3 +DA:85,3 +DA:86,3 +DA:87,3 +DA:88,3 +DA:89,3 +DA:90,3 +DA:96,1 +DA:97,1 +DA:105,1 +DA:148,1 +DA:149,1 +DA:150,1 +DA:152,1 +DA:154,3 +DA:155,3 +DA:156,3 +DA:157,3 +DA:158,3 +DA:159,3 +DA:160,3 +DA:161,3 +DA:162,3 +DA:167,3 +DA:172,1 +DA:173,2 +DA:174,2 +DA:175,1 +DA:180,1 DA:182,1 -DA:184,1 +DA:183,2 +DA:184,2 +DA:188,3 +DA:189,4 +DA:190,1 DA:192,1 -DA:193,1 -DA:194,1 -DA:196,1 -DA:198,1 +DA:193,7 +DA:195,1 +DA:197,1 +DA:198,2 DA:199,2 -DA:200,6 -DA:204,1 +DA:200,2 +DA:201,2 +DA:202,1 +DA:203,2 +DA:204,4 +DA:205,1 DA:207,1 -DA:208,1 -DA:210,1 -DA:211,1 -DA:212,3 -DA:213,1 -DA:216,3 +DA:215,1 +DA:216,1 +DA:217,1 DA:219,1 -DA:220,2 -DA:227,2 -DA:228,1 -DA:229,1 -DA:231,3 -DA:238,1 -DA:239,4 -DA:240,4 -DA:241,1 -DA:242,3 -DA:247,1 -DA:248,1 -DA:249,1 -DA:251,0 -DA:252,0 -DA:255,0 -LF:88 -LH:85 +DA:221,1 +DA:222,2 +DA:223,6 +DA:227,1 +DA:230,1 +DA:231,1 +DA:233,1 +DA:234,1 +DA:235,3 +DA:236,1 +DA:239,3 +DA:242,1 +DA:243,2 +DA:250,2 +DA:251,1 +DA:252,1 +DA:254,3 +DA:261,1 +DA:262,4 +DA:263,4 +DA:264,3 +DA:265,3 +DA:270,1 +DA:271,5 +DA:272,1 +DA:274,1 +DA:275,3 +DA:278,3 +LF:92 +LH:92 end_of_record SF:lib/src/components/chips/assist_chip.dart DA:14,0 @@ -1459,108 +1500,123 @@ LH:0 end_of_record SF:lib/src/components/chips/chip.dart DA:17,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:68,0 -DA:70,0 -DA:71,0 DA:72,0 DA:73,0 DA:74,0 -DA:75,0 DA:76,0 -DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 DA:84,0 +DA:85,0 DA:86,0 -DA:87,0 -DA:90,0 -DA:91,0 -DA:92,0 DA:93,0 -DA:94,0 +DA:95,0 DA:96,0 +DA:99,0 +DA:100,0 DA:101,0 +DA:102,0 DA:103,0 -DA:104,0 -DA:106,0 -DA:107,0 -DA:108,0 -DA:109,0 +DA:105,0 DA:110,0 -DA:111,0 +DA:112,0 DA:113,0 +DA:115,0 DA:116,0 DA:117,0 DA:118,0 +DA:119,0 DA:120,0 -DA:125,0 +DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 DA:126,0 -DA:127,0 -DA:128,0 DA:129,0 DA:130,0 DA:131,0 -DA:132,0 -DA:134,0 -DA:135,0 -DA:136,0 -DA:137,0 +DA:133,0 DA:139,0 +DA:140,0 +DA:141,0 DA:142,0 +DA:143,0 +DA:144,0 DA:145,0 -DA:146,0 -DA:148,0 -DA:151,0 -DA:152,0 +DA:150,0 DA:153,0 DA:154,0 -DA:156,0 -DA:157,0 -DA:158,0 -DA:160,0 -DA:162,0 +DA:155,0 DA:163,0 +DA:164,0 DA:165,0 DA:166,0 +DA:167,0 DA:168,0 DA:169,0 -DA:171,0 +DA:170,0 DA:172,0 DA:173,0 DA:174,0 -DA:176,0 -DA:182,0 +DA:175,0 +DA:177,0 +DA:180,0 +DA:183,0 DA:184,0 -DA:185,0 DA:186,0 DA:189,0 DA:190,0 +DA:191,0 DA:192,0 +DA:194,0 +DA:195,0 DA:196,0 -DA:197,0 DA:198,0 -DA:199,0 DA:200,0 DA:201,0 -DA:202,0 +DA:203,0 DA:204,0 DA:206,0 DA:207,0 -DA:208,0 -DA:219,0 -DA:221,0 +DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:214,0 +DA:220,0 +DA:222,0 DA:223,0 DA:224,0 -DA:225,0 -LF:95 +DA:227,0 +DA:228,0 +DA:230,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:237,0 +DA:238,0 +DA:239,0 +DA:240,0 +DA:242,0 +DA:244,0 +DA:245,0 +DA:246,0 +DA:257,0 +DA:259,0 +DA:261,0 +DA:262,0 +DA:263,0 +LF:111 LH:0 end_of_record SF:lib/src/components/chips/filter_chip.dart DA:14,0 -DA:23,0 -DA:26,0 -DA:29,0 +DA:24,0 +DA:27,0 DA:30,0 DA:31,0 DA:32,0 @@ -1568,6 +1624,7 @@ DA:33,0 DA:34,0 DA:35,0 DA:36,0 +DA:37,0 LF:11 LH:0 end_of_record @@ -1578,157 +1635,164 @@ LH:0 end_of_record SF:lib/src/components/contact_item/contact_item.dart DA:8,0 -DA:33,0 -DA:35,0 DA:37,0 -DA:38,0 DA:39,0 -DA:40,0 DA:41,0 DA:42,0 DA:43,0 -DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 DA:48,0 +DA:49,0 DA:50,0 -DA:51,0 DA:52,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:61,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 DA:62,0 +DA:63,0 DA:64,0 -DA:67,0 +DA:65,0 +DA:66,0 DA:68,0 -DA:69,0 -DA:70,0 -DA:74,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:82,0 -DA:97,0 -DA:99,0 -DA:101,0 -DA:102,0 -LF:34 -LH:0 -end_of_record -SF:lib/src/components/date_input/date_input.dart -DA:16,0 -DA:32,0 DA:71,0 DA:72,0 DA:73,0 -DA:75,0 -DA:77,0 +DA:74,0 DA:78,0 -DA:79,0 DA:80,0 DA:81,0 DA:82,0 +DA:86,0 +DA:104,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 +LF:37 +LH:0 +end_of_record +SF:lib/src/components/date_input/date_input.dart +DA:16,0 +DA:34,0 DA:83,0 DA:84,0 DA:85,0 -DA:86,0 DA:87,0 -DA:88,0 DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 DA:97,0 -DA:106,0 -DA:108,0 -DA:109,0 -DA:110,0 -DA:115,0 -DA:117,0 -DA:118,0 -DA:119,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:111,0 +DA:120,0 +DA:122,0 DA:123,0 DA:124,0 -DA:125,0 -DA:126,0 DA:129,0 +DA:131,0 DA:132,0 -DA:134,0 -DA:135,0 +DA:133,0 +DA:137,0 DA:138,0 DA:139,0 DA:140,0 -DA:142,0 -DA:145,0 +DA:143,0 DA:146,0 -DA:147,0 -DA:150,0 -DA:151,0 +DA:148,0 +DA:149,0 DA:152,0 DA:153,0 -DA:155,0 +DA:154,0 +DA:156,0 +DA:159,0 +DA:160,0 DA:161,0 DA:164,0 +DA:165,0 DA:166,0 -DA:168,0 +DA:167,0 DA:169,0 -DA:172,0 -DA:174,0 DA:175,0 -DA:176,0 -DA:177,0 DA:178,0 -DA:179,0 -DA:184,0 +DA:180,0 +DA:182,0 +DA:183,0 +DA:186,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 DA:193,0 -DA:197,0 -DA:199,0 -DA:200,0 -DA:201,0 -DA:202,0 -DA:204,0 -DA:205,0 -DA:208,0 -DA:209,0 +DA:198,0 +DA:207,0 DA:211,0 DA:213,0 DA:214,0 DA:215,0 DA:216,0 -DA:217,0 DA:218,0 DA:219,0 -DA:220,0 -DA:221,0 DA:222,0 DA:223,0 -DA:224,0 -DA:226,0 +DA:225,0 DA:227,0 DA:228,0 DA:229,0 DA:230,0 +DA:231,0 DA:232,0 DA:233,0 +DA:234,0 +DA:235,0 +DA:236,0 +DA:237,0 DA:238,0 -DA:239,0 +DA:240,0 +DA:241,0 +DA:242,0 DA:243,0 DA:244,0 -DA:245,0 -DA:248,0 -DA:249,0 -DA:250,0 +DA:246,0 +DA:247,0 DA:252,0 DA:253,0 -DA:254,0 -DA:255,0 DA:257,0 +DA:258,0 DA:259,0 -DA:260,0 -DA:261,0 DA:262,0 -LF:108 -LH:0 -end_of_record -SF:lib/src/interfaces/form_field.dart -DA:17,2 -DA:37,1 +DA:263,0 +DA:264,0 +DA:266,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:270,0 +DA:272,0 +DA:274,0 +DA:275,0 +DA:276,0 +DA:277,0 +DA:278,0 +LF:112 +LH:0 +end_of_record +SF:lib/src/interfaces/form_field.dart +DA:17,2 +DA:37,1 DA:39,1 DA:41,3 DA:42,3 @@ -1797,24 +1861,25 @@ DA:185,2 DA:187,1 DA:189,1 DA:191,1 -DA:195,1 -DA:197,2 -DA:198,4 -DA:200,1 -DA:202,1 -DA:203,4 -DA:205,2 -DA:206,1 +DA:192,1 +DA:196,1 +DA:198,2 +DA:199,4 +DA:201,1 +DA:203,1 +DA:204,4 +DA:206,2 DA:207,1 -DA:209,1 +DA:208,1 DA:210,1 -DA:214,1 +DA:211,1 DA:215,1 -DA:216,2 +DA:216,1 DA:217,2 -DA:218,4 -LF:75 -LH:75 +DA:218,2 +DA:219,4 +LF:76 +LH:76 end_of_record SF:lib/src/components/dialog/dialog.dart DA:15,0 @@ -1918,237 +1983,245 @@ DA:25,0 DA:31,0 DA:36,0 DA:54,0 -DA:116,0 -DA:117,0 -DA:118,0 -DA:120,0 -DA:122,0 -DA:123,0 -DA:124,0 -DA:125,0 -DA:126,0 -DA:127,0 DA:128,0 DA:129,0 DA:130,0 +DA:132,0 +DA:134,0 DA:135,0 +DA:136,0 DA:137,0 DA:138,0 -DA:165,0 -DA:166,0 -DA:169,0 -DA:171,0 -DA:172,0 -DA:173,0 -DA:174,0 -DA:176,0 -DA:177,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:147,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:152,0 DA:179,0 +DA:180,0 DA:183,0 DA:185,0 +DA:186,0 DA:187,0 DA:188,0 -DA:189,0 +DA:190,0 DA:191,0 -DA:192,0 DA:193,0 -DA:196,0 DA:197,0 -DA:198,0 DA:199,0 +DA:201,0 +DA:202,0 +DA:203,0 DA:205,0 DA:206,0 DA:207,0 -DA:209,0 +DA:210,0 +DA:211,0 +DA:212,0 DA:213,0 -DA:214,0 -DA:215,0 -DA:218,0 +DA:219,0 DA:220,0 DA:221,0 -DA:222,0 -DA:224,0 +DA:223,0 +DA:227,0 DA:228,0 +DA:229,0 DA:232,0 -DA:233,0 DA:234,0 -DA:237,0 +DA:235,0 +DA:236,0 DA:238,0 -DA:240,0 DA:242,0 +DA:246,0 DA:247,0 DA:248,0 -DA:249,0 -DA:250,0 +DA:251,0 DA:252,0 -DA:257,0 +DA:254,0 +DA:256,0 +DA:261,0 DA:262,0 DA:263,0 DA:264,0 -DA:265,0 -DA:268,0 -DA:272,0 -DA:273,0 -DA:274,0 -DA:275,0 +DA:266,0 +DA:271,0 +DA:276,0 +DA:277,0 DA:278,0 DA:279,0 -DA:280,0 -DA:281,0 DA:282,0 -DA:284,0 -DA:285,0 -DA:291,0 +DA:286,0 +DA:287,0 +DA:288,0 +DA:289,0 DA:292,0 DA:293,0 DA:294,0 DA:295,0 DA:296,0 -DA:297,0 -DA:298,0 -DA:301,0 -DA:302,0 -DA:303,0 -DA:305,0 +DA:299,0 +DA:300,0 DA:306,0 DA:307,0 DA:308,0 +DA:309,0 DA:310,0 DA:311,0 +DA:312,0 DA:313,0 DA:314,0 +DA:315,0 +DA:316,0 DA:317,0 -DA:318,0 +DA:320,0 DA:321,0 DA:322,0 DA:323,0 -DA:324,0 -DA:325,0 DA:326,0 DA:327,0 DA:328,0 -DA:329,0 DA:330,0 -DA:332,0 +DA:331,0 DA:333,0 +DA:334,0 +DA:337,0 +DA:338,0 +DA:341,0 +DA:342,0 +DA:343,0 +DA:344,0 DA:345,0 +DA:346,0 DA:347,0 +DA:348,0 DA:349,0 DA:350,0 DA:352,0 -DA:355,0 -DA:362,0 -DA:389,0 -DA:390,0 -DA:391,0 -DA:393,0 -DA:395,0 -DA:396,0 -DA:397,0 -DA:398,0 -DA:399,0 -DA:401,0 -DA:404,0 -DA:405,0 -DA:412,0 -DA:414,0 +DA:353,0 +DA:366,0 +DA:368,0 +DA:370,0 +DA:371,0 +DA:373,0 +DA:376,0 +DA:383,0 DA:415,0 DA:416,0 DA:417,0 +DA:419,0 +DA:421,0 DA:422,0 +DA:423,0 DA:424,0 DA:425,0 -DA:428,0 +DA:427,0 DA:430,0 +DA:431,0 DA:432,0 -DA:435,0 +DA:439,0 DA:441,0 +DA:442,0 DA:443,0 DA:444,0 -DA:445,0 -DA:446,0 -DA:447,0 -DA:448,0 -DA:453,0 -DA:456,0 +DA:449,0 +DA:451,0 +DA:452,0 +DA:455,0 DA:457,0 -DA:458,0 DA:459,0 -DA:460,0 +DA:462,0 +DA:468,0 +DA:469,0 DA:470,0 -DA:471,0 DA:472,0 DA:473,0 DA:474,0 DA:475,0 DA:476,0 DA:477,0 -DA:480,0 -DA:481,0 -DA:482,0 +DA:478,0 DA:484,0 -DA:485,0 +DA:486,0 +DA:487,0 DA:488,0 -DA:489,0 -DA:493,0 -DA:494,0 -DA:495,0 -DA:496,0 DA:497,0 +DA:498,0 DA:499,0 DA:500,0 +DA:501,0 DA:502,0 DA:503,0 -DA:505,0 -DA:506,0 +DA:504,0 +DA:507,0 +DA:508,0 DA:509,0 DA:511,0 DA:512,0 -DA:513,0 DA:515,0 -DA:517,0 -DA:518,0 -DA:519,0 +DA:516,0 +DA:520,0 +DA:521,0 DA:522,0 DA:523,0 DA:524,0 -DA:534,0 +DA:526,0 +DA:527,0 +DA:529,0 +DA:530,0 +DA:532,0 +DA:533,0 DA:536,0 -DA:537,0 DA:538,0 +DA:539,0 DA:540,0 -DA:548,0 +DA:542,0 +DA:544,0 +DA:545,0 +DA:546,0 +DA:549,0 +DA:550,0 +DA:551,0 +DA:560,0 +DA:562,0 +DA:563,0 +DA:564,0 +DA:566,0 DA:574,0 -DA:575,0 -DA:576,0 -DA:578,0 -DA:580,0 -DA:581,0 -DA:582,0 -DA:583,0 -DA:584,0 -DA:585,0 -DA:590,0 -DA:592,0 -DA:593,0 -DA:595,0 -DA:596,0 -DA:597,0 +DA:600,0 +DA:601,0 +DA:602,0 +DA:604,0 +DA:606,0 +DA:607,0 DA:608,0 DA:609,0 DA:610,0 -DA:613,0 -DA:614,0 -DA:617,0 +DA:611,0 +DA:616,0 DA:618,0 DA:619,0 DA:621,0 DA:622,0 DA:623,0 -DA:624,0 -DA:627,0 -DA:628,0 -LF:242 +DA:634,0 +DA:635,0 +DA:636,0 +DA:639,0 +DA:640,0 +DA:643,0 +DA:644,0 +DA:645,0 +DA:647,0 +DA:648,0 +DA:649,0 +DA:650,0 +DA:653,0 +DA:654,0 +LF:250 LH:0 end_of_record SF:lib/src/components/fabs/fab.dart @@ -2177,11 +2250,11 @@ DA:116,1 DA:118,6 DA:119,2 DA:120,1 -DA:121,0 +DA:121,3 DA:123,1 DA:124,1 DA:126,1 -DA:127,0 +DA:127,1 DA:131,1 DA:132,1 DA:133,1 @@ -2215,29 +2288,31 @@ DA:194,1 DA:203,2 DA:204,2 LF:62 -LH:60 +LH:62 end_of_record SF:lib/src/components/filter_selection/filter_selection.dart DA:9,0 -DA:22,0 -DA:24,0 -DA:26,0 -DA:27,0 DA:28,0 DA:30,0 -DA:31,0 +DA:32,0 DA:33,0 -DA:40,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 DA:41,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:56,0 +DA:42,0 +DA:44,0 +DA:52,0 +DA:53,0 +DA:57,0 DA:58,0 -DA:60,0 -DA:61,0 -LF:19 +DA:66,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:72,0 +LF:21 LH:0 end_of_record SF:lib/src/components/global_header/global_header.dart @@ -2347,21 +2422,21 @@ LF:27 LH:0 end_of_record SF:lib/src/components/icon/icon.dart -DA:17,219 -DA:190,10 -DA:192,10 -DA:193,20 -DA:194,10 -DA:195,10 -DA:196,10 -DA:197,10 -DA:198,10 -DA:199,10 -DA:200,10 -DA:201,10 -DA:202,10 -DA:203,10 -DA:204,10 +DA:17,217 +DA:190,8 +DA:192,8 +DA:193,16 +DA:194,8 +DA:195,8 +DA:196,8 +DA:197,8 +DA:198,8 +DA:199,8 +DA:200,8 +DA:201,8 +DA:202,8 +DA:203,8 +DA:204,8 DA:208,1 DA:210,1 DA:212,3 @@ -2382,8 +2457,8 @@ DA:231,8 DA:233,8 DA:234,8 DA:235,8 -DA:240,10 -DA:241,20 +DA:240,8 +DA:241,16 DA:242,16 LF:38 LH:38 @@ -2445,67 +2520,72 @@ LH:51 end_of_record SF:lib/src/components/list_item/dropdown_list_item.dart DA:10,0 -DA:41,0 -DA:42,0 -DA:43,0 -DA:45,0 DA:47,0 DA:48,0 DA:49,0 -DA:50,0 DA:51,0 -DA:52,0 -DA:62,0 -DA:64,0 -DA:65,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 DA:69,0 -DA:70,0 -DA:73,0 -DA:74,0 +DA:71,0 +DA:72,0 DA:76,0 -DA:79,0 +DA:77,0 +DA:80,0 DA:81,0 -DA:82,0 -DA:84,0 -DA:87,0 +DA:83,0 +DA:86,0 +DA:88,0 DA:89,0 -DA:90,0 -DA:93,0 +DA:91,0 DA:94,0 -DA:95,0 +DA:96,0 DA:97,0 -DA:98,0 DA:100,0 +DA:101,0 +DA:102,0 DA:104,0 -DA:106,0 -DA:108,0 -DA:109,0 +DA:105,0 +DA:107,0 DA:111,0 -DA:112,0 +DA:113,0 DA:115,0 DA:116,0 -DA:117,0 DA:118,0 DA:119,0 +DA:120,0 +DA:122,0 DA:123,0 -DA:124,0 -DA:125,0 DA:126,0 DA:127,0 DA:128,0 DA:129,0 -DA:131,0 -DA:132,0 -DA:133,0 +DA:130,0 +DA:134,0 DA:135,0 +DA:136,0 DA:137,0 +DA:138,0 +DA:139,0 DA:140,0 +DA:141,0 DA:143,0 -DA:146,0 +DA:144,0 +DA:145,0 DA:147,0 -DA:148,0 DA:149,0 -LF:61 +DA:152,0 +DA:156,0 +DA:159,0 +DA:160,0 +DA:161,0 +DA:162,0 +LF:66 LH:0 end_of_record SF:lib/src/components/list_item/list_scope.dart @@ -2531,267 +2611,262 @@ DA:31,0 DA:32,0 DA:33,0 DA:34,0 -DA:40,0 -DA:42,0 +DA:41,0 DA:43,0 -DA:52,0 -DA:64,0 -DA:73,0 -DA:78,0 -DA:81,0 -DA:91,0 -DA:97,0 -DA:100,0 -DA:110,0 -DA:115,0 -DA:145,0 -DA:147,0 -DA:149,0 +DA:44,0 +DA:53,0 +DA:65,0 +DA:74,0 +DA:79,0 +DA:82,0 +DA:92,0 +DA:98,0 +DA:101,0 +DA:111,0 +DA:116,0 +DA:146,0 +DA:148,0 DA:150,0 DA:151,0 DA:152,0 DA:153,0 DA:154,0 -DA:157,0 -DA:159,0 +DA:155,0 +DA:158,0 DA:160,0 -DA:162,0 -DA:164,0 -DA:166,0 +DA:161,0 +DA:163,0 +DA:165,0 DA:167,0 DA:168,0 DA:169,0 DA:170,0 +DA:171,0 DA:172,0 -DA:173,0 DA:174,0 -DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 DA:179,0 -DA:184,0 -DA:186,0 -DA:187,0 +DA:183,0 DA:188,0 -DA:189,0 +DA:190,0 DA:191,0 -DA:197,0 -DA:198,0 -DA:200,0 +DA:192,0 +DA:193,0 +DA:195,0 DA:201,0 DA:202,0 +DA:204,0 +DA:205,0 DA:206,0 -DA:207,0 -DA:208,0 -DA:219,0 -DA:220,0 +DA:210,0 +DA:211,0 +DA:212,0 +DA:223,0 DA:224,0 -LF:62 +DA:228,0 +LF:64 LH:0 end_of_record SF:lib/src/components/list_item/notification_list_item.dart DA:9,0 -DA:42,0 -DA:43,0 -DA:46,0 +DA:48,0 +DA:49,0 +DA:51,0 +DA:53,0 +DA:55,0 DA:56,0 DA:57,0 DA:58,0 DA:59,0 -DA:60,0 -DA:61,0 -DA:62,0 +DA:64,0 DA:66,0 +DA:67,0 DA:68,0 -DA:70,0 +DA:69,0 DA:71,0 -DA:72,0 DA:73,0 +DA:74,0 +DA:75,0 DA:78,0 -DA:80,0 -DA:81,0 +DA:79,0 DA:82,0 DA:83,0 DA:84,0 DA:85,0 +DA:87,0 DA:88,0 -DA:89,0 +DA:90,0 +DA:91,0 DA:92,0 DA:93,0 DA:94,0 DA:95,0 -DA:97,0 -DA:98,0 +DA:96,0 +DA:99,0 DA:100,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 +DA:106,0 +DA:107,0 DA:108,0 DA:109,0 -DA:114,0 -DA:115,0 +DA:110,0 +DA:111,0 +DA:113,0 DA:116,0 DA:117,0 -DA:118,0 DA:119,0 -DA:121,0 DA:123,0 -DA:124,0 -DA:126,0 -DA:130,0 -DA:134,0 +DA:127,0 +DA:128,0 +DA:131,0 +DA:133,0 DA:135,0 -DA:138,0 -DA:140,0 +DA:141,0 DA:142,0 -DA:147,0 -DA:148,0 -DA:149,0 -DA:151,0 -DA:152,0 -DA:160,0 -DA:161,0 -DA:162,0 -DA:163,0 -DA:164,0 -DA:165,0 -DA:173,0 -DA:181,0 -DA:189,0 -DA:208,0 -DA:210,0 +DA:143,0 +DA:145,0 +DA:146,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:167,0 +DA:175,0 +DA:183,0 +DA:202,0 +DA:204,0 +DA:205,0 +DA:206,0 +DA:208,0 +DA:209,0 DA:211,0 DA:212,0 -DA:214,0 +DA:213,0 DA:215,0 DA:217,0 -DA:218,0 DA:219,0 DA:221,0 -DA:223,0 -DA:225,0 -DA:227,0 -DA:232,0 -DA:234,0 -DA:236,0 -DA:237,0 -LF:87 +DA:226,0 +DA:228,0 +DA:230,0 +DA:231,0 +LF:83 LH:0 end_of_record SF:lib/src/components/navigation bar/navigation_bar.dart DA:11,0 DA:30,0 -DA:40,0 -DA:45,0 -DA:52,0 -DA:63,0 -DA:69,0 -DA:79,0 -DA:85,0 +DA:41,0 +DA:46,0 +DA:59,0 +DA:71,0 +DA:105,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:110,0 DA:111,0 -DA:112,0 -DA:114,0 +DA:113,0 DA:115,0 -DA:116,0 -DA:117,0 DA:119,0 DA:121,0 DA:125,0 +DA:126,0 DA:127,0 +DA:128,0 +DA:129,0 +DA:130,0 DA:131,0 -DA:132,0 DA:133,0 -DA:134,0 -DA:135,0 -DA:136,0 DA:137,0 +DA:138,0 DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 DA:143,0 -DA:144,0 -DA:145,0 -DA:146,0 DA:147,0 -DA:148,0 -DA:149,0 +DA:150,0 +DA:151,0 DA:153,0 -DA:156,0 -DA:157,0 +DA:154,0 +DA:155,0 DA:159,0 -DA:160,0 -DA:161,0 +DA:162,0 +DA:164,0 DA:165,0 +DA:166,0 DA:168,0 -DA:173,0 DA:174,0 -DA:175,0 +DA:176,0 +DA:178,0 +DA:179,0 +DA:180,0 DA:181,0 +DA:182,0 DA:183,0 -DA:185,0 -DA:186,0 -DA:187,0 DA:188,0 -DA:189,0 -DA:194,0 -DA:204,0 -DA:205,0 +DA:198,0 +DA:199,0 +DA:201,0 +DA:202,0 +DA:203,0 +DA:206,0 DA:207,0 -DA:208,0 DA:209,0 -DA:212,0 -DA:213,0 -DA:215,0 +DA:218,0 +DA:220,0 +DA:221,0 +DA:223,0 DA:224,0 +DA:225,0 DA:226,0 DA:227,0 -DA:229,0 -DA:230,0 +DA:228,0 DA:231,0 -DA:233,0 -DA:234,0 -DA:236,0 +DA:232,0 +DA:235,0 +DA:237,0 DA:238,0 -DA:239,0 +DA:240,0 DA:241,0 DA:242,0 DA:243,0 -DA:244,0 -DA:246,0 -DA:248,0 -DA:250,0 +DA:245,0 +DA:247,0 +DA:249,0 +DA:254,0 DA:255,0 DA:256,0 DA:257,0 DA:258,0 -DA:267,0 DA:269,0 DA:271,0 -DA:272,0 DA:273,0 -LF:88 +DA:274,0 +DA:275,0 +LF:91 LH:0 end_of_record SF:lib/src/components/navigation_rail/navigation_rail.dart DA:9,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:62,0 DA:64,0 DA:65,0 DA:66,0 -DA:67,0 DA:68,0 -DA:69,0 DA:70,0 DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 DA:76,0 +DA:77,0 DA:78,0 -DA:79,0 -DA:80,0 -DA:81,0 -DA:82,0 DA:83,0 -DA:84,0 DA:85,0 DA:86,0 DA:87,0 @@ -2806,240 +2881,270 @@ DA:95,0 DA:96,0 DA:97,0 DA:98,0 -DA:113,0 -DA:131,0 -DA:133,0 -DA:134,0 -DA:135,0 -DA:136,0 -DA:138,0 -DA:139,0 -DA:140,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:123,0 DA:141,0 DA:143,0 DA:144,0 DA:146,0 +DA:147,0 DA:148,0 +DA:149,0 +DA:151,0 +DA:152,0 DA:153,0 DA:154,0 -DA:155,0 -DA:160,0 -DA:162,0 -DA:163,0 -DA:164,0 -DA:165,0 +DA:156,0 +DA:157,0 +DA:159,0 +DA:161,0 DA:166,0 DA:167,0 DA:168,0 -DA:169,0 -DA:170,0 DA:173,0 DA:175,0 DA:176,0 +DA:177,0 DA:178,0 DA:179,0 DA:180,0 DA:181,0 DA:182,0 DA:183,0 +DA:186,0 +DA:188,0 +DA:189,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:194,0 +DA:195,0 DA:196,0 -DA:198,0 -DA:200,0 -DA:201,0 -DA:202,0 -DA:203,0 -DA:204,0 -DA:205,0 +DA:210,0 DA:212,0 -LF:80 +DA:214,0 +DA:215,0 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:226,0 +LF:85 LH:0 end_of_record SF:lib/src/components/pagination/pagination.dart DA:23,0 -DA:32,0 -DA:36,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:63,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:77,0 -DA:79,0 -DA:81,0 -DA:82,0 -DA:85,0 -DA:87,0 -DA:88,0 +DA:37,0 +DA:41,0 DA:89,0 DA:90,0 +DA:91,0 +DA:93,0 DA:95,0 DA:96,0 DA:97,0 +DA:98,0 DA:99,0 +DA:100,0 +DA:101,0 DA:102,0 DA:103,0 -DA:105,0 -DA:106,0 -DA:107,0 -DA:111,0 +DA:104,0 DA:112,0 -DA:113,0 DA:114,0 -DA:115,0 +DA:116,0 +DA:117,0 +DA:120,0 DA:122,0 +DA:123,0 DA:124,0 DA:125,0 -DA:126,0 -DA:127,0 -DA:129,0 DA:130,0 DA:131,0 +DA:132,0 +DA:134,0 +DA:137,0 DA:138,0 -DA:139,0 DA:140,0 -DA:143,0 -DA:144,0 -DA:148,0 -DA:149,0 +DA:141,0 +DA:142,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 DA:150,0 -DA:151,0 -DA:154,0 -DA:155,0 DA:157,0 DA:159,0 DA:160,0 +DA:161,0 +DA:162,0 DA:164,0 DA:165,0 DA:166,0 -DA:172,0 DA:173,0 DA:174,0 -DA:176,0 -DA:177,0 +DA:175,0 DA:178,0 DA:179,0 -DA:180,0 DA:183,0 +DA:184,0 DA:185,0 DA:186,0 +DA:189,0 DA:190,0 DA:192,0 -DA:193,0 DA:194,0 -DA:196,0 -DA:197,0 -DA:206,0 +DA:195,0 +DA:199,0 +DA:200,0 +DA:201,0 +DA:207,0 DA:208,0 DA:209,0 -DA:210,0 DA:211,0 +DA:212,0 DA:213,0 +DA:214,0 DA:215,0 -DA:217,0 +DA:218,0 DA:219,0 DA:220,0 -DA:222,0 +DA:223,0 DA:224,0 -DA:225,0 -DA:227,0 DA:228,0 DA:230,0 DA:231,0 -DA:233,0 -DA:236,0 -DA:238,0 -DA:239,0 -DA:241,0 +DA:232,0 +DA:234,0 +DA:235,0 DA:245,0 -DA:246,0 +DA:247,0 DA:248,0 -DA:257,0 +DA:249,0 +DA:250,0 +DA:252,0 +DA:254,0 +DA:256,0 +DA:258,0 +DA:259,0 +DA:260,0 +DA:262,0 +DA:264,0 +DA:265,0 +DA:266,0 +DA:268,0 +DA:269,0 DA:271,0 +DA:272,0 DA:273,0 -DA:274,0 +DA:276,0 DA:278,0 DA:279,0 DA:280,0 -DA:282,0 -DA:283,0 DA:284,0 DA:285,0 -DA:286,0 DA:287,0 -DA:290,0 -DA:291,0 -DA:292,0 -DA:293,0 -DA:297,0 -DA:303,0 -DA:305,0 -DA:306,0 -DA:307,0 -DA:308,0 -DA:309,0 -DA:310,0 -DA:311,0 -DA:313,0 +DA:296,0 +DA:312,0 DA:314,0 -DA:316,0 +DA:315,0 DA:319,0 -DA:329,0 +DA:320,0 +DA:321,0 +DA:323,0 +DA:324,0 +DA:325,0 +DA:326,0 +DA:327,0 +DA:328,0 DA:331,0 +DA:332,0 DA:333,0 DA:334,0 DA:335,0 -DA:336,0 -DA:337,0 -DA:342,26 -DA:344,0 -LF:141 +DA:339,0 +DA:341,0 +DA:342,0 +DA:348,0 +DA:350,0 +DA:351,0 +DA:352,0 +DA:353,0 +DA:354,0 +DA:355,0 +DA:356,0 +DA:358,0 +DA:359,0 +DA:361,0 +DA:364,0 +DA:375,0 +DA:377,0 +DA:379,0 +DA:380,0 +DA:381,0 +DA:382,0 +DA:383,0 +DA:384,0 +DA:389,26 +DA:391,0 +LF:154 LH:1 end_of_record SF:lib/src/components/password/password_input.dart DA:10,2 -DA:56,1 -DA:57,1 -DA:59,1 -DA:61,1 -DA:63,1 -DA:64,2 -DA:66,3 -DA:67,3 -DA:68,3 -DA:69,3 -DA:70,3 -DA:71,3 -DA:72,3 -DA:73,3 -DA:74,3 -DA:81,1 -DA:83,1 +DA:74,1 +DA:75,1 +DA:77,1 +DA:79,1 +DA:81,3 +DA:82,3 +DA:83,3 DA:84,3 -DA:87,1 -DA:89,1 -DA:91,1 -DA:92,2 -DA:94,2 -DA:95,2 -DA:96,2 -DA:97,2 -DA:98,2 -DA:99,2 -DA:100,2 -DA:101,2 -DA:102,2 -DA:103,1 -DA:104,1 -DA:105,2 +DA:85,3 +DA:86,3 +DA:87,3 +DA:88,3 +DA:89,3 +DA:90,3 +DA:91,3 +DA:92,3 +DA:93,3 +DA:100,1 +DA:102,1 +DA:103,3 DA:106,1 -DA:107,2 -DA:108,2 -LF:38 -LH:38 +DA:108,1 +DA:110,1 +DA:111,2 +DA:113,2 +DA:114,2 +DA:115,2 +DA:116,2 +DA:117,2 +DA:118,2 +DA:119,2 +DA:120,2 +DA:121,2 +DA:122,1 +DA:123,2 +DA:124,1 +DA:125,1 +DA:126,5 +DA:127,1 +DA:128,2 +DA:129,1 +DA:130,2 +DA:131,2 +LF:44 +LH:44 end_of_record SF:lib/src/components/phone_input/countries.dart DA:4,26 @@ -3120,162 +3225,170 @@ DA:173,0 DA:183,0 DA:185,0 DA:186,0 -DA:187,0 DA:188,0 +DA:189,0 DA:190,0 -DA:194,0 -DA:204,0 -LF:69 +DA:192,0 +DA:196,0 +DA:207,0 +LF:70 LH:0 end_of_record SF:lib/src/components/phone_input/phone_input.dart DA:12,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:69,0 DA:71,0 DA:72,0 DA:73,0 -DA:74,0 DA:75,0 -DA:76,0 DA:77,0 DA:78,0 DA:79,0 DA:80,0 DA:81,0 DA:82,0 -DA:92,0 -DA:94,0 -DA:95,0 -DA:96,0 -DA:97,0 -DA:98,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 DA:99,0 -DA:100,0 DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 DA:105,0 DA:106,0 DA:107,0 -DA:109,0 -DA:110,0 -DA:111,0 +DA:108,0 +DA:112,0 +DA:113,0 DA:114,0 DA:116,0 DA:117,0 -DA:120,0 +DA:118,0 DA:121,0 -DA:122,0 DA:123,0 -DA:125,0 -DA:126,0 +DA:124,0 DA:127,0 DA:128,0 DA:129,0 DA:130,0 +DA:132,0 +DA:133,0 +DA:134,0 DA:135,0 +DA:136,0 DA:137,0 -DA:138,0 -DA:139,0 -DA:140,0 DA:142,0 -DA:143,0 DA:144,0 +DA:145,0 DA:146,0 -DA:148,0 +DA:147,0 DA:149,0 DA:150,0 -DA:152,0 +DA:151,0 DA:153,0 DA:154,0 DA:155,0 +DA:156,0 +DA:158,0 DA:159,0 -DA:161,0 +DA:160,0 DA:162,0 DA:163,0 -DA:166,0 -DA:167,0 -DA:168,0 -DA:175,0 +DA:164,0 +DA:165,0 +DA:169,0 +DA:171,0 +DA:172,0 +DA:173,0 DA:176,0 DA:177,0 DA:178,0 DA:181,0 +DA:182,0 DA:183,0 -DA:184,0 -DA:185,0 -DA:186,0 -DA:188,0 -DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 DA:193,0 -DA:194,0 +DA:196,0 +DA:198,0 +DA:199,0 +DA:200,0 DA:201,0 DA:203,0 +DA:204,0 DA:208,0 DA:209,0 -DA:210,0 -DA:212,0 -DA:213,0 -DA:214,0 DA:216,0 DA:218,0 -DA:219,0 +DA:223,0 +DA:224,0 DA:225,0 -DA:226,0 -DA:230,0 +DA:227,0 +DA:228,0 +DA:229,0 DA:231,0 DA:233,0 DA:234,0 -DA:235,0 -DA:237,0 -DA:238,0 -DA:239,0 +DA:240,0 DA:241,0 -DA:248,0 +DA:246,0 +DA:247,0 DA:249,0 +DA:250,0 DA:251,0 DA:253,0 DA:254,0 -DA:256,0 +DA:255,0 DA:257,0 -DA:258,0 -DA:259,0 +DA:264,0 +DA:265,0 +DA:267,0 +DA:269,0 DA:270,0 -DA:271,0 DA:272,0 DA:273,0 DA:274,0 DA:275,0 -DA:276,0 -DA:277,0 -DA:278,0 -DA:279,0 -DA:280,0 -DA:281,0 -DA:282,0 -DA:283,0 +DA:286,0 +DA:287,0 +DA:288,0 +DA:289,0 DA:290,0 DA:291,0 +DA:292,0 DA:293,0 DA:294,0 DA:295,0 +DA:296,0 DA:297,0 DA:298,0 -DA:303,0 -DA:304,0 -DA:305,0 +DA:299,0 DA:306,0 -DA:318,0 +DA:307,0 +DA:309,0 +DA:310,0 +DA:311,0 +DA:313,0 +DA:314,0 +DA:319,0 +DA:320,0 +DA:321,0 DA:322,0 -DA:329,0 -DA:332,0 -DA:336,0 -DA:343,0 +DA:335,0 +DA:339,0 DA:346,0 -DA:350,0 -DA:357,0 -LF:146 +DA:349,0 +DA:353,0 +DA:360,0 +DA:363,0 +DA:367,0 +DA:374,0 +LF:153 LH:0 end_of_record SF:lib/src/components/progress/progress.dart @@ -3331,34 +3444,37 @@ DA:85,0 DA:90,0 DA:92,0 DA:93,0 +DA:94,0 DA:95,0 -DA:96,0 DA:97,0 -DA:98,0 DA:99,0 DA:100,0 +DA:101,0 +DA:102,0 DA:103,0 DA:104,0 DA:107,0 DA:108,0 -DA:109,0 DA:111,0 DA:112,0 DA:113,0 -DA:114,0 +DA:115,0 DA:116,0 +DA:117,0 +DA:118,0 DA:120,0 -DA:128,0 -DA:130,0 -DA:131,0 +DA:124,0 DA:133,0 DA:135,0 DA:136,0 -DA:137,0 DA:138,0 -DA:139,0 -DA:146,0 -LF:42 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:151,0 +LF:45 LH:0 end_of_record SF:lib/src/components/progress/progress_circle.dart @@ -3466,9 +3582,9 @@ DA:69,0 DA:70,0 DA:71,0 DA:72,0 -DA:74,0 +DA:73,0 DA:75,0 -DA:77,0 +DA:76,0 DA:78,0 DA:79,0 DA:80,0 @@ -3495,37 +3611,37 @@ DA:100,0 DA:101,0 DA:102,0 DA:103,0 -DA:106,0 +DA:104,0 DA:107,0 DA:108,0 -DA:110,0 -DA:113,0 +DA:109,0 +DA:111,0 DA:114,0 -DA:125,0 -DA:127,0 -DA:131,0 -DA:135,0 +DA:115,0 +DA:126,0 +DA:128,0 +DA:132,0 DA:136,0 -DA:138,0 -DA:141,0 +DA:137,0 +DA:139,0 DA:142,0 -DA:144,0 -DA:146,0 +DA:143,0 +DA:145,0 DA:147,0 DA:148,0 -DA:152,0 -DA:154,0 +DA:149,0 +DA:153,0 DA:155,0 -DA:163,0 -DA:167,0 -DA:169,0 +DA:156,0 +DA:164,0 +DA:168,0 DA:170,0 -DA:173,0 +DA:171,0 DA:174,0 DA:175,0 DA:176,0 DA:177,0 -DA:181,0 +DA:178,0 DA:182,0 DA:183,0 DA:184,0 @@ -3533,518 +3649,545 @@ DA:185,0 DA:186,0 DA:187,0 DA:188,0 -DA:191,0 +DA:189,0 DA:192,0 DA:193,0 -LF:94 +DA:194,0 +LF:95 LH:0 end_of_record SF:lib/src/components/screen_header_bar/screen_header_bar.dart DA:8,0 -DA:25,0 -DA:27,0 -DA:28,0 -DA:30,0 DA:31,0 -DA:32,0 +DA:33,0 +DA:34,0 DA:35,0 +DA:36,0 DA:37,0 -DA:39,0 DA:40,0 DA:41,0 -DA:42,0 +DA:45,0 +DA:47,0 DA:49,0 +DA:50,0 DA:51,0 -DA:53,0 -DA:54,0 -DA:55,0 -LF:18 +DA:52,0 +DA:59,0 +DA:61,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +LF:21 LH:0 end_of_record SF:lib/src/components/search_bar/search_bar.dart DA:8,2 -DA:66,1 -DA:67,1 -DA:69,1 -DA:71,1 -DA:73,3 -DA:74,3 -DA:75,3 -DA:76,3 -DA:77,3 -DA:78,3 -DA:79,3 -DA:80,3 -DA:81,3 -DA:82,3 -DA:83,3 -DA:84,3 -DA:93,1 -DA:95,1 -DA:96,4 +DA:78,1 +DA:79,1 +DA:81,1 +DA:83,1 +DA:85,3 +DA:86,3 +DA:87,3 +DA:88,3 +DA:89,3 +DA:90,3 +DA:91,3 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 DA:97,3 DA:98,3 -DA:101,1 -DA:103,1 -DA:104,3 -DA:105,3 -DA:106,4 -DA:107,4 -DA:111,1 -DA:113,2 -DA:114,1 +DA:107,1 +DA:109,1 +DA:110,4 +DA:111,3 +DA:112,3 +DA:115,1 DA:117,1 -DA:119,1 -DA:120,2 -DA:122,1 -DA:123,3 -DA:124,1 -DA:125,2 -DA:126,2 -DA:127,1 -DA:129,2 -DA:130,2 -DA:131,6 +DA:118,3 +DA:119,3 +DA:120,4 +DA:121,4 +DA:125,1 +DA:127,2 +DA:128,1 +DA:131,1 DA:133,1 -DA:135,1 -DA:137,2 +DA:134,2 +DA:136,1 +DA:137,3 +DA:138,1 DA:139,2 -DA:140,1 -DA:141,7 +DA:140,4 +DA:141,2 +DA:142,1 DA:143,2 -DA:144,1 -DA:146,1 -DA:148,8 -DA:157,1 +DA:144,2 +DA:145,1 +DA:147,2 +DA:148,2 +DA:149,6 +DA:151,1 +DA:153,1 +DA:155,2 +DA:157,2 DA:158,1 -DA:160,1 -DA:161,6 +DA:159,7 +DA:161,2 DA:162,1 -DA:168,1 -DA:169,3 -DA:170,3 -DA:172,1 -DA:174,3 -DA:178,2 -DA:179,1 -DA:181,1 -DA:182,3 -DA:188,1 -DA:190,2 +DA:164,1 +DA:166,8 +DA:175,1 +DA:176,1 +DA:178,1 +DA:179,6 +DA:180,1 +DA:184,2 +DA:185,1 DA:191,1 -DA:197,2 -DA:199,1 -DA:200,3 -DA:202,4 -DA:203,2 -DA:206,1 -DA:220,2 -DA:221,5 -DA:222,2 -DA:223,2 -DA:224,2 -DA:230,1 -DA:231,1 -DA:232,1 -DA:233,1 +DA:192,3 +DA:193,3 +DA:195,1 +DA:197,3 +DA:202,2 +DA:203,1 +DA:205,1 +DA:206,3 +DA:212,2 +DA:213,1 +DA:215,1 +DA:217,2 +DA:220,1 +DA:221,2 +DA:227,2 +DA:229,1 +DA:230,3 +DA:232,4 +DA:233,2 DA:236,1 -DA:237,1 -DA:238,1 -DA:239,1 -DA:242,1 -DA:246,1 -DA:247,1 -DA:248,4 -DA:251,1 -DA:255,1 -DA:256,1 -DA:257,4 -DA:260,1 +DA:250,2 +DA:251,5 +DA:252,2 +DA:253,2 +DA:254,2 DA:261,1 DA:262,1 -LF:100 -LH:100 +DA:263,1 +DA:264,1 +DA:267,1 +DA:268,1 +DA:269,1 +DA:270,1 +DA:273,1 +DA:277,1 +DA:278,1 +DA:279,4 +DA:282,1 +DA:286,1 +DA:287,1 +DA:288,4 +DA:291,1 +DA:292,1 +DA:293,1 +LF:111 +LH:111 end_of_record SF:lib/src/components/segmented_control/segmented_control.dart DA:11,0 -DA:28,0 -DA:29,0 -DA:31,0 -DA:33,0 +DA:34,0 DA:35,0 -DA:36,0 -DA:38,0 +DA:37,0 DA:39,0 -DA:40,0 -DA:63,0 -DA:65,0 -DA:67,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:68,0 DA:70,0 DA:72,0 -DA:74,0 DA:75,0 -DA:76,0 -DA:83,0 -DA:84,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:81,0 DA:88,0 -DA:90,0 -DA:91,0 +DA:89,0 DA:93,0 +DA:95,0 DA:96,0 DA:98,0 DA:101,0 -DA:102,0 -DA:105,0 +DA:103,0 DA:106,0 -DA:109,0 +DA:107,0 DA:110,0 DA:111,0 -DA:112,0 -DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 DA:117,0 -DA:120,0 -DA:121,0 +DA:118,0 +DA:119,0 DA:123,0 -DA:125,0 +DA:126,0 DA:127,0 -DA:128,0 -DA:130,0 +DA:129,0 DA:131,0 +DA:132,0 DA:134,0 -DA:135,0 DA:136,0 DA:137,0 DA:139,0 DA:140,0 -DA:157,0 -DA:172,0 -DA:176,0 -DA:181,0 +DA:143,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:148,0 +DA:149,0 +DA:167,0 DA:182,0 -DA:184,0 -DA:186,0 DA:187,0 -DA:192,0 +DA:193,0 DA:194,0 DA:196,0 DA:198,0 DA:200,0 DA:201,0 -DA:202,0 -DA:204,0 -DA:205,0 DA:206,0 DA:208,0 -DA:209,0 DA:210,0 -DA:212,0 -DA:217,0 -DA:229,0 -DA:245,0 -DA:247,0 +DA:213,0 +DA:214,0 +DA:216,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:222,0 +DA:223,0 +DA:224,0 +DA:226,0 +DA:227,0 +DA:228,0 +DA:230,0 +DA:235,0 DA:248,0 -DA:249,0 -DA:250,0 -DA:251,0 -DA:255,0 -DA:257,0 -DA:259,0 -DA:260,0 -DA:261,0 -DA:262,0 -DA:263,0 +DA:264,0 DA:266,0 -DA:272,0 -DA:273,0 -DA:283,0 -DA:305,0 -DA:307,0 -DA:308,0 -DA:311,0 -DA:313,0 -DA:316,0 -DA:318,0 -DA:319,0 -DA:322,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:270,0 +DA:274,0 +DA:276,0 +DA:278,0 +DA:279,0 +DA:280,0 +DA:281,0 +DA:282,0 +DA:285,0 +DA:291,0 +DA:292,0 +DA:302,0 DA:324,0 +DA:326,0 DA:327,0 -DA:328,0 -DA:329,0 -DA:334,0 -DA:336,0 +DA:330,0 +DA:332,0 +DA:335,0 DA:337,0 -DA:340,0 +DA:338,0 DA:341,0 -DA:342,0 -DA:344,0 +DA:343,0 +DA:346,0 DA:347,0 -DA:349,0 -DA:352,0 +DA:348,0 DA:353,0 -DA:354,0 +DA:355,0 +DA:356,0 DA:359,0 +DA:360,0 DA:361,0 -DA:362,0 -DA:365,0 +DA:363,0 DA:366,0 -DA:367,0 -DA:369,0 +DA:368,0 +DA:371,0 DA:372,0 -DA:374,0 -DA:376,0 -DA:377,0 +DA:373,0 DA:378,0 -DA:379,0 DA:380,0 DA:381,0 -DA:382,0 +DA:384,0 DA:385,0 -DA:387,0 +DA:386,0 DA:388,0 DA:391,0 DA:393,0 +DA:395,0 DA:396,0 DA:397,0 DA:398,0 DA:399,0 +DA:400,0 DA:401,0 -DA:402,0 +DA:404,0 DA:406,0 -DA:411,0 -DA:413,0 +DA:407,0 +DA:410,0 +DA:412,0 DA:415,0 DA:416,0 -DA:419,0 -DA:422,0 +DA:417,0 +DA:418,0 +DA:420,0 +DA:421,0 DA:425,0 -DA:426,0 DA:430,0 -DA:431,0 +DA:432,0 DA:434,0 DA:435,0 -DA:436,0 -DA:439,0 -DA:440,0 +DA:438,0 DA:441,0 +DA:444,0 DA:445,0 -DA:448,0 DA:449,0 DA:450,0 -DA:451,0 -DA:452,0 DA:453,0 -DA:456,0 +DA:454,0 +DA:455,0 DA:458,0 -DA:461,0 -DA:462,0 -DA:466,0 +DA:459,0 +DA:460,0 +DA:464,0 +DA:467,0 DA:468,0 DA:469,0 DA:470,0 DA:471,0 -DA:473,0 +DA:472,0 +DA:475,0 DA:477,0 -DA:478,0 -DA:482,0 -DA:483,0 -DA:484,0 +DA:480,0 +DA:481,0 DA:485,0 DA:487,0 DA:488,0 -DA:491,0 -DA:494,0 +DA:489,0 +DA:490,0 +DA:492,0 DA:496,0 DA:497,0 DA:501,0 +DA:502,0 DA:503,0 DA:504,0 -DA:508,0 -DA:509,0 -DA:512,0 -DA:514,0 +DA:506,0 +DA:507,0 +DA:510,0 +DA:513,0 DA:515,0 -DA:518,0 -DA:519,0 +DA:516,0 +DA:520,0 DA:522,0 -DA:524,0 -DA:525,0 -DA:526,0 -DA:536,0 +DA:523,0 +DA:527,0 +DA:528,0 +DA:531,0 +DA:533,0 +DA:534,0 +DA:537,0 +DA:538,0 DA:541,0 -DA:542,0 +DA:543,0 DA:544,0 -DA:548,0 -DA:549,0 -DA:550,0 -DA:551,0 -DA:552,0 -DA:556,0 -DA:557,0 -DA:558,0 +DA:545,0 +DA:555,0 DA:560,0 -DA:562,0 +DA:561,0 DA:563,0 -DA:565,0 DA:567,0 +DA:568,0 DA:569,0 +DA:570,0 DA:571,0 -DA:572,0 -DA:573,0 DA:575,0 -DA:578,0 +DA:576,0 +DA:577,0 +DA:579,0 +DA:581,0 DA:582,0 -DA:583,0 DA:584,0 -DA:585,0 DA:586,0 +DA:588,0 +DA:590,0 DA:591,0 +DA:592,0 +DA:594,0 DA:597,0 -DA:598,0 DA:601,0 +DA:602,0 DA:603,0 DA:604,0 -DA:607,0 -DA:608,0 -DA:609,0 +DA:605,0 DA:610,0 -DA:613,0 -DA:615,0 -LF:243 +DA:616,0 +DA:617,0 +DA:620,0 +DA:622,0 +DA:623,0 +DA:626,0 +DA:627,0 +DA:628,0 +DA:629,0 +DA:632,0 +DA:634,0 +LF:249 LH:0 end_of_record SF:lib/src/components/select_input/select_input.dart DA:13,0 -DA:61,0 -DA:62,0 -DA:63,0 -DA:65,0 DA:67,0 DA:68,0 DA:69,0 -DA:70,0 DA:71,0 -DA:72,0 DA:73,0 DA:74,0 DA:75,0 -DA:85,0 -DA:87,0 -DA:89,0 -DA:90,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 DA:92,0 -DA:93,0 +DA:94,0 DA:96,0 -DA:98,0 +DA:97,0 DA:99,0 -DA:101,0 -DA:104,0 +DA:100,0 +DA:103,0 DA:105,0 DA:106,0 -DA:109,0 -DA:110,0 +DA:108,0 DA:111,0 DA:112,0 -DA:114,0 +DA:113,0 +DA:116,0 DA:117,0 DA:118,0 DA:119,0 -DA:122,0 -DA:123,0 +DA:121,0 DA:124,0 DA:125,0 -DA:127,0 +DA:126,0 +DA:129,0 DA:130,0 +DA:131,0 DA:132,0 -DA:135,0 -DA:136,0 +DA:134,0 DA:137,0 -DA:138,0 -DA:140,0 +DA:139,0 DA:142,0 +DA:143,0 +DA:144,0 DA:145,0 -DA:146,0 DA:147,0 DA:149,0 -DA:150,0 -DA:151,0 +DA:152,0 DA:153,0 DA:154,0 -DA:155,0 -DA:156,0 DA:157,0 DA:158,0 DA:159,0 -DA:160,0 +DA:161,0 DA:162,0 DA:163,0 +DA:164,0 DA:165,0 +DA:166,0 +DA:167,0 +DA:168,0 DA:170,0 DA:171,0 -DA:172,0 DA:173,0 -DA:174,0 -DA:175,0 -DA:176,0 -DA:177,0 DA:178,0 DA:179,0 DA:180,0 DA:181,0 -LF:77 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:190,0 +LF:79 LH:0 end_of_record SF:lib/src/components/slider/slider.dart -DA:10,0 -DA:30,0 -DA:31,0 +DA:9,0 DA:32,0 +DA:33,0 DA:34,0 DA:36,0 -DA:37,0 DA:38,0 DA:39,0 -DA:46,0 -DA:48,0 -DA:50,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:49,0 DA:51,0 +DA:53,0 +DA:54,0 DA:55,0 DA:56,0 -DA:59,0 +DA:57,0 +DA:61,0 DA:62,0 -DA:63,0 -DA:66,0 -DA:67,0 +DA:65,0 DA:68,0 DA:69,0 -DA:71,0 DA:72,0 +DA:73,0 +DA:74,0 DA:75,0 -DA:76,0 DA:77,0 DA:78,0 -DA:79,0 -DA:80,0 DA:81,0 +DA:82,0 +DA:83,0 DA:84,0 DA:85,0 DA:86,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -DA:98,0 -DA:105,0 -DA:116,0 -DA:118,0 -DA:122,0 -DA:137,0 -DA:139,0 -DA:140,0 -DA:141,0 -DA:144,0 +DA:87,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:113,0 +DA:124,0 +DA:126,0 +DA:130,0 DA:145,0 -DA:146,0 -LF:50 +DA:147,0 +DA:148,0 +DA:149,0 +DA:152,0 +DA:153,0 +DA:154,0 +LF:54 LH:0 end_of_record SF:lib/src/components/snack_bar/snack_bar.dart @@ -4353,80 +4496,83 @@ LH:0 end_of_record SF:lib/src/components/stepper_input/stepper_input.dart DA:19,0 -DA:28,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:55,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:62,0 +DA:30,0 +DA:67,0 +DA:68,0 DA:69,0 DA:71,0 DA:73,0 DA:74,0 DA:75,0 +DA:76,0 DA:77,0 +DA:78,0 +DA:79,0 DA:80,0 -DA:82,0 -DA:83,0 -DA:86,0 DA:87,0 DA:89,0 -DA:90,0 DA:91,0 +DA:92,0 DA:93,0 -DA:97,0 +DA:95,0 DA:98,0 +DA:100,0 +DA:101,0 +DA:104,0 DA:105,0 -DA:106,0 +DA:107,0 DA:108,0 DA:109,0 DA:111,0 -DA:112,0 -DA:114,0 -DA:118,0 -DA:119,0 -DA:120,0 -DA:121,0 +DA:115,0 +DA:116,0 DA:123,0 DA:124,0 -DA:128,0 +DA:126,0 +DA:127,0 DA:129,0 +DA:130,0 DA:132,0 -DA:133,0 -DA:134,0 +DA:136,0 +DA:137,0 +DA:138,0 DA:139,0 DA:141,0 DA:142,0 -DA:143,0 -DA:145,0 +DA:146,0 DA:147,0 DA:148,0 -DA:149,0 DA:151,0 +DA:152,0 DA:153,0 -DA:154,0 -DA:155,0 -DA:157,0 DA:158,0 -DA:159,0 +DA:160,0 DA:161,0 DA:162,0 -DA:163,0 +DA:164,0 DA:166,0 +DA:167,0 DA:168,0 DA:170,0 -DA:171,0 DA:172,0 DA:173,0 DA:174,0 +DA:176,0 +DA:177,0 DA:178,0 -DA:179,0 -LF:74 +DA:180,0 +DA:181,0 +DA:182,0 +DA:185,0 +DA:187,0 +DA:189,0 +DA:190,0 +DA:191,0 +DA:192,0 +DA:193,0 +DA:197,0 +DA:198,0 +LF:77 LH:0 end_of_record SF:lib/src/components/switch/material_switch.dart @@ -5083,12 +5229,14 @@ SF:lib/src/components/tabs/tab.dart DA:7,0 DA:11,0 DA:12,0 +DA:14,0 DA:15,0 -DA:16,0 -DA:21,0 -DA:23,0 -DA:25,0 -LF:8 +DA:18,0 +DA:19,0 +DA:24,0 +DA:26,0 +DA:28,0 +LF:10 LH:0 end_of_record SF:lib/src/components/tabs/tab_bar.dart @@ -5106,21 +5254,13 @@ LH:0 end_of_record SF:lib/src/components/text_input/text_input.dart DA:17,1 -DA:40,1 DA:41,1 DA:42,1 -DA:111,1 -DA:112,1 -DA:113,0 -DA:115,0 -DA:117,0 -DA:118,0 -DA:119,0 -DA:120,0 +DA:43,1 +DA:119,1 +DA:120,1 DA:121,0 -DA:122,0 DA:123,0 -DA:124,0 DA:125,0 DA:126,0 DA:127,0 @@ -5132,287 +5272,301 @@ DA:132,0 DA:133,0 DA:134,0 DA:135,0 -DA:143,4 -DA:150,1 -DA:151,2 -DA:152,0 -DA:154,1 -DA:155,3 -DA:157,2 -DA:160,1 -DA:162,3 -DA:168,1 -DA:169,2 -DA:170,1 -DA:172,0 -DA:173,0 -DA:178,0 -DA:179,0 -DA:180,0 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:140,0 +DA:141,0 +DA:142,0 +DA:143,0 +DA:144,0 +DA:152,4 +DA:159,1 +DA:160,2 +DA:161,0 +DA:163,1 +DA:164,3 +DA:166,2 +DA:169,1 +DA:171,3 +DA:177,1 +DA:178,2 +DA:179,1 DA:181,0 -DA:183,0 -DA:186,1 -DA:188,2 -DA:189,1 -DA:191,0 -DA:193,0 -DA:196,1 -DA:201,1 -DA:202,2 -DA:203,2 -DA:204,0 -DA:205,0 -DA:207,0 -DA:208,0 -DA:211,0 -DA:217,1 -DA:218,4 -DA:219,0 +DA:182,0 +DA:187,0 +DA:188,0 +DA:189,0 +DA:190,0 +DA:192,0 +DA:195,1 +DA:197,2 +DA:198,1 +DA:200,0 +DA:202,0 +DA:205,1 +DA:210,1 +DA:211,2 +DA:212,2 +DA:213,0 +DA:214,0 +DA:216,0 +DA:217,0 DA:220,0 -DA:221,0 -DA:223,0 -DA:224,0 -DA:227,0 -DA:233,2 -DA:235,4 -DA:238,3 -DA:239,4 -DA:242,3 -DA:243,3 -DA:246,1 +DA:226,1 +DA:227,4 +DA:228,0 +DA:229,0 +DA:230,0 +DA:232,0 +DA:233,0 +DA:236,0 +DA:242,2 +DA:244,4 +DA:247,3 DA:248,4 -DA:249,3 -DA:251,2 -DA:252,0 -DA:254,1 -DA:257,1 -DA:259,4 -DA:260,0 +DA:251,3 +DA:252,3 +DA:255,1 +DA:257,4 +DA:258,3 +DA:260,2 DA:261,0 -DA:264,4 -DA:265,0 -DA:267,1 +DA:263,1 +DA:266,1 +DA:268,4 +DA:269,0 DA:270,0 -DA:271,0 -DA:273,0 -DA:275,0 -DA:276,0 -DA:279,1 -DA:281,1 -DA:283,1 -DA:285,1 +DA:273,4 +DA:274,0 +DA:276,1 +DA:279,0 +DA:280,0 +DA:282,0 +DA:284,0 +DA:285,0 DA:288,1 -DA:289,2 -DA:290,0 -DA:291,0 -DA:292,0 -DA:293,0 -DA:297,1 -DA:298,2 -DA:299,0 -DA:300,0 -DA:303,2 +DA:290,1 +DA:292,1 +DA:294,1 +DA:295,4 +DA:296,2 +DA:297,2 +DA:298,1 +DA:301,1 +DA:302,2 +DA:303,0 DA:304,0 DA:305,0 -DA:308,1 -DA:309,2 +DA:306,0 DA:310,1 -DA:311,1 +DA:311,2 DA:312,2 DA:313,1 DA:314,2 -DA:315,4 -DA:317,1 +DA:315,1 +DA:316,1 +DA:317,2 +DA:318,1 DA:319,2 -DA:321,2 +DA:320,4 DA:322,1 -DA:323,2 DA:324,2 -DA:325,1 +DA:326,2 DA:327,1 -DA:329,1 -DA:330,2 -DA:331,1 +DA:328,2 +DA:329,2 +DA:330,1 DA:332,1 -DA:333,1 DA:334,1 -DA:335,1 +DA:335,2 DA:336,1 DA:337,1 DA:338,1 DA:339,1 -DA:340,3 -DA:341,2 +DA:340,1 +DA:341,1 DA:342,1 DA:343,1 +DA:344,1 +DA:345,3 +DA:346,2 +DA:347,1 DA:348,1 -DA:349,2 -DA:351,2 -DA:352,1 -DA:361,0 -DA:371,0 -DA:373,0 -DA:378,0 +DA:353,1 +DA:354,2 +DA:356,2 +DA:357,1 +DA:367,0 +DA:377,0 DA:379,0 -DA:381,0 -DA:383,0 DA:384,0 -DA:386,0 +DA:385,0 DA:387,0 +DA:389,0 +DA:390,0 DA:392,0 DA:393,0 -DA:394,0 -DA:395,0 -DA:396,0 -DA:397,0 +DA:398,0 +DA:399,0 DA:400,0 -DA:405,0 -DA:407,0 -DA:409,0 -DA:410,0 +DA:401,0 +DA:402,0 +DA:403,0 +DA:406,0 DA:411,0 -DA:416,1 -DA:427,1 -DA:429,2 -DA:430,3 -DA:432,3 -DA:434,1 -DA:436,1 -DA:437,0 -DA:439,1 +DA:413,0 +DA:415,0 +DA:416,0 +DA:417,0 +DA:422,1 +DA:433,1 +DA:435,2 +DA:436,3 +DA:438,3 +DA:440,1 DA:442,1 -DA:446,1 -DA:447,1 +DA:443,0 +DA:445,1 DA:448,1 -DA:449,1 +DA:452,1 +DA:453,1 +DA:454,1 +DA:455,1 DA:456,1 -DA:457,1 -DA:459,1 +DA:463,1 DA:464,1 -DA:467,0 -DA:469,0 -DA:471,0 -DA:472,0 -DA:473,0 -DA:474,0 -LF:190 -LH:102 +DA:466,1 +DA:471,1 +DA:475,0 +DA:477,0 +DA:479,0 +DA:480,0 +DA:481,0 +DA:482,0 +LF:192 +LH:107 end_of_record SF:lib/src/components/time_input/time_input.dart DA:19,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:68,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:75,0 DA:76,0 DA:77,0 DA:78,0 -DA:79,0 DA:80,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 DA:94,0 -DA:101,0 -DA:103,0 -DA:106,0 -DA:107,0 +DA:102,0 DA:108,0 -DA:109,0 -DA:110,0 -DA:112,0 -DA:118,0 +DA:115,0 +DA:117,0 DA:120,0 DA:121,0 DA:122,0 +DA:123,0 +DA:124,0 DA:126,0 -DA:127,0 -DA:128,0 -DA:131,0 +DA:132,0 DA:134,0 +DA:135,0 DA:136,0 -DA:138,0 +DA:140,0 DA:141,0 DA:142,0 -DA:143,0 -DA:144,0 -DA:146,0 -DA:149,0 +DA:145,0 +DA:148,0 DA:150,0 DA:152,0 -DA:153,0 DA:155,0 DA:156,0 -DA:159,0 +DA:157,0 +DA:158,0 DA:160,0 -DA:162,0 DA:163,0 DA:164,0 -DA:165,0 DA:166,0 DA:167,0 -DA:168,0 DA:169,0 DA:170,0 -DA:171,0 -DA:172,0 -DA:175,0 +DA:173,0 +DA:174,0 +DA:176,0 +DA:177,0 DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 DA:185,0 DA:186,0 -DA:193,0 -DA:197,0 +DA:189,0 +DA:192,0 DA:199,0 DA:200,0 -DA:201,0 -DA:202,0 -DA:204,0 -DA:205,0 -DA:208,0 -DA:209,0 +DA:207,0 DA:211,0 DA:213,0 DA:214,0 DA:215,0 -DA:217,0 +DA:216,0 DA:218,0 DA:219,0 -DA:220,0 -DA:221,0 DA:222,0 DA:223,0 -DA:224,0 DA:225,0 -DA:226,0 DA:227,0 DA:228,0 -DA:230,0 +DA:229,0 +DA:231,0 DA:232,0 DA:233,0 DA:234,0 +DA:235,0 DA:236,0 +DA:237,0 +DA:238,0 DA:239,0 DA:240,0 +DA:241,0 +DA:242,0 DA:244,0 -DA:245,0 DA:246,0 -DA:249,0 +DA:247,0 +DA:248,0 DA:250,0 -DA:251,0 DA:253,0 DA:254,0 -DA:255,0 -DA:256,0 DA:258,0 +DA:259,0 DA:260,0 -DA:261,0 -DA:262,0 DA:263,0 -LF:113 +DA:264,0 +DA:265,0 +DA:267,0 +DA:268,0 +DA:269,0 +DA:270,0 +DA:271,0 +DA:273,0 +DA:275,0 +DA:276,0 +DA:277,0 +DA:278,0 +DA:279,0 +LF:117 LH:0 end_of_record SF:lib/src/components/tooltip/tooltip.dart @@ -5427,78 +5581,81 @@ DA:82,1 DA:83,1 DA:84,1 DA:85,1 -DA:87,1 -DA:88,2 +DA:86,1 +DA:88,1 DA:89,1 -DA:90,1 DA:91,1 +DA:92,2 DA:93,1 -DA:98,1 -DA:100,1 -DA:101,2 +DA:94,1 +DA:95,1 +DA:97,1 DA:102,1 -DA:103,1 DA:104,1 +DA:105,2 DA:106,1 -DA:111,1 -DA:112,1 -DA:113,3 +DA:107,1 +DA:108,1 +DA:110,1 DA:115,1 DA:116,1 -DA:118,1 +DA:117,3 +DA:119,1 DA:120,1 -DA:121,1 -DA:126,1 -DA:127,1 -DA:128,1 -DA:129,2 +DA:122,1 +DA:124,1 +DA:125,1 +DA:130,1 +DA:131,1 DA:132,1 -DA:137,2 -DA:138,1 -DA:139,1 -DA:140,1 +DA:133,2 +DA:136,1 +DA:141,2 DA:142,1 -DA:149,2 -DA:150,1 -DA:151,1 -DA:152,1 +DA:143,1 +DA:144,1 +DA:146,1 +DA:153,2 DA:154,1 -DA:166,1 -DA:168,1 -DA:170,3 -DA:171,3 -DA:172,3 -DA:173,3 -DA:174,3 -DA:175,3 -DA:180,1 -DA:188,1 -DA:190,1 -DA:191,1 -DA:192,2 -DA:193,1 -DA:194,2 -DA:195,3 -DA:196,2 -DA:197,3 -DA:198,3 +DA:155,1 +DA:156,1 +DA:158,1 +DA:173,1 +DA:175,1 +DA:177,3 +DA:178,3 +DA:179,3 +DA:180,3 +DA:181,3 +DA:182,3 +DA:187,1 +DA:195,1 +DA:197,1 +DA:198,1 DA:199,2 -DA:200,2 -DA:201,3 +DA:200,1 +DA:201,2 DA:202,3 DA:203,2 -DA:204,2 -DA:205,2 -DA:206,4 -DA:207,1 -DA:208,2 -DA:209,4 +DA:204,3 +DA:205,3 +DA:206,2 +DA:207,2 +DA:208,3 +DA:209,3 DA:210,2 -DA:211,1 -DA:213,1 -DA:216,0 -LF:81 -LH:80 +DA:211,2 +DA:212,2 +DA:213,4 +DA:214,1 +DA:215,2 +DA:216,4 +DA:217,2 +DA:218,1 +DA:220,1 +DA:223,0 +LF:84 +LH:83 end_of_record SF:lib/src/components/top_app_bar/extended_top_app_bar.dart DA:17,0 @@ -5628,31 +5785,29 @@ end_of_record SF:lib/src/components/top_app_bar/top_app_bar.dart DA:13,0 DA:29,0 -DA:46,0 -DA:93,0 -DA:94,0 +DA:47,0 +DA:95,0 DA:96,0 DA:98,0 DA:100,0 DA:102,0 -DA:103,0 DA:104,0 DA:105,0 DA:106,0 DA:107,0 DA:108,0 DA:109,0 -DA:116,0 +DA:110,0 +DA:111,0 DA:118,0 -DA:119,0 -DA:122,0 -DA:123,0 -DA:126,0 -DA:129,0 +DA:120,0 +DA:121,0 +DA:124,0 +DA:125,0 +DA:128,0 DA:131,0 -DA:132,0 -DA:135,0 -DA:136,0 +DA:133,0 +DA:134,0 DA:137,0 DA:138,0 DA:139,0 @@ -5667,58 +5822,60 @@ DA:147,0 DA:148,0 DA:149,0 DA:150,0 -DA:154,0 -DA:158,0 -DA:159,0 -DA:164,0 -DA:165,0 +DA:151,0 +DA:152,0 +DA:156,0 +DA:160,0 +DA:161,0 DA:166,0 DA:167,0 DA:168,0 DA:169,0 +DA:170,0 DA:171,0 DA:173,0 -DA:174,0 DA:175,0 DA:176,0 -DA:179,0 -DA:180,0 +DA:177,0 +DA:178,0 +DA:181,0 DA:182,0 DA:184,0 -DA:185,0 -DA:193,0 -DA:196,0 +DA:186,0 +DA:187,0 +DA:195,0 DA:198,0 DA:200,0 -DA:201,0 +DA:202,0 DA:203,0 -DA:204,0 DA:205,0 DA:206,0 DA:207,0 DA:208,0 DA:209,0 -DA:214,0 -DA:215,0 +DA:210,0 +DA:211,0 +DA:216,0 DA:217,0 DA:219,0 -DA:220,0 +DA:221,0 DA:222,0 -DA:227,0 -DA:228,0 +DA:224,0 DA:229,0 DA:230,0 DA:231,0 DA:232,0 DA:233,0 +DA:234,0 DA:235,0 -DA:238,0 +DA:237,0 DA:240,0 -DA:241,0 +DA:242,0 DA:243,0 -DA:244,0 DA:245,0 DA:246,0 +DA:247,0 +DA:248,0 LF:93 LH:0 end_of_record @@ -5756,8 +5913,8 @@ DA:63,1 DA:64,1 DA:65,1 DA:66,7 -DA:75,56 -DA:78,57 +DA:75,58 +DA:78,60 DA:81,3 DA:94,1 DA:96,1 @@ -5832,15 +5989,15 @@ DA:77,18 DA:80,18 DA:83,24 DA:86,18 -DA:89,22 +DA:89,24 DA:92,18 DA:95,48 DA:98,16 -DA:106,38 +DA:106,40 DA:112,4 DA:118,16 DA:124,8 -DA:130,4 +DA:130,8 DA:136,4 DA:142,20 DA:148,4 @@ -5871,64 +6028,64 @@ LF:50 LH:50 end_of_record SF:lib/src/theme/color_scheme.dart -DA:29,19 -DA:95,19 -DA:151,19 -DA:152,18 -DA:153,18 +DA:29,20 +DA:95,20 +DA:151,20 +DA:152,19 +DA:153,19 DA:154,19 -DA:155,18 -DA:156,18 -DA:157,19 -DA:158,19 -DA:159,19 -DA:160,19 -DA:161,19 -DA:162,19 -DA:163,19 -DA:164,19 -DA:165,19 -DA:166,19 -DA:167,19 -DA:168,19 -DA:169,19 -DA:170,19 -DA:171,19 -DA:172,19 -DA:173,19 -DA:174,19 -DA:175,19 -DA:176,19 -DA:177,19 -DA:178,19 -DA:179,19 -DA:180,19 -DA:181,19 -DA:182,19 -DA:183,19 -DA:184,19 -DA:185,19 -DA:186,19 -DA:187,19 -DA:188,19 -DA:189,19 -DA:190,19 -DA:191,19 -DA:192,19 -DA:193,19 -DA:194,19 -DA:195,19 -DA:196,19 +DA:155,19 +DA:156,19 +DA:157,20 +DA:158,20 +DA:159,20 +DA:160,20 +DA:161,20 +DA:162,20 +DA:163,20 +DA:164,20 +DA:165,20 +DA:166,20 +DA:167,20 +DA:168,20 +DA:169,20 +DA:170,20 +DA:171,20 +DA:172,20 +DA:173,20 +DA:174,20 +DA:175,20 +DA:176,20 +DA:177,20 +DA:178,20 +DA:179,20 +DA:180,20 +DA:181,20 +DA:182,20 +DA:183,20 +DA:184,20 +DA:185,20 +DA:186,20 +DA:187,20 +DA:188,20 +DA:189,20 +DA:190,20 +DA:191,20 +DA:192,20 +DA:193,20 +DA:194,20 +DA:195,20 +DA:196,20 DA:200,1 DA:202,1 DA:204,3 DA:205,3 -DA:208,18 -DA:211,2 -DA:212,2 -DA:213,6 -DA:214,6 -DA:215,6 +DA:208,19 +DA:211,3 +DA:212,3 +DA:213,9 +DA:214,9 +DA:215,9 DA:217,1 DA:218,7 LF:60 @@ -5977,11 +6134,11 @@ DA:169,1 DA:172,1 DA:176,1 DA:180,1 -DA:276,54 +DA:276,57 DA:285,6 DA:292,6 DA:301,6 -DA:308,6 +DA:308,9 DA:317,3 DA:324,6 DA:333,3 @@ -5990,7 +6147,7 @@ DA:343,3 DA:348,9 DA:353,3 DA:358,6 -DA:363,9 +DA:363,12 DA:368,3 DA:373,3 DA:378,3 @@ -6055,17 +6212,17 @@ DA:653,8 DA:660,21 DA:663,42 DA:664,3 -DA:670,18 -DA:671,72 -DA:672,72 -DA:673,18 -DA:674,18 -DA:676,18 -DA:678,18 -DA:680,18 -DA:681,18 -DA:682,18 -DA:683,18 +DA:670,19 +DA:671,76 +DA:672,76 +DA:673,19 +DA:674,19 +DA:676,19 +DA:678,19 +DA:680,19 +DA:681,19 +DA:682,19 +DA:683,19 DA:690,6 DA:691,6 DA:692,6 @@ -6080,8 +6237,8 @@ DA:700,6 DA:701,6 DA:702,6 DA:703,6 -DA:741,36 -DA:744,2 +DA:741,38 +DA:744,4 DA:751,1 DA:752,4 DA:759,1 @@ -6102,8 +6259,8 @@ DA:848,1 DA:849,4 DA:855,1 DA:856,4 -DA:863,18 -DA:864,55 +DA:863,19 +DA:864,59 DA:871,1 DA:872,4 DA:879,5 @@ -6123,49 +6280,49 @@ DA:961,2 DA:973,2 DA:983,2 DA:993,2 -DA:995,1 -DA:997,1 +DA:995,2 +DA:997,2 DA:998,3 -DA:999,1 +DA:999,2 DA:1000,3 -DA:1001,1 +DA:1001,2 DA:1002,3 -DA:1003,1 +DA:1003,2 DA:1004,3 -DA:1005,1 +DA:1005,2 DA:1006,4 -DA:1007,1 +DA:1007,2 DA:1008,4 -DA:1009,1 +DA:1009,2 DA:1010,4 -DA:1011,1 +DA:1011,2 DA:1012,4 -DA:1013,1 +DA:1013,2 DA:1014,3 -DA:1015,1 +DA:1015,2 DA:1016,3 -DA:1017,1 +DA:1017,2 DA:1018,3 -DA:1019,1 +DA:1019,2 DA:1020,3 -DA:1021,1 +DA:1021,2 DA:1022,3 -DA:1023,1 +DA:1023,2 DA:1024,3 -DA:1025,1 +DA:1025,2 DA:1026,3 -DA:1027,1 +DA:1027,2 DA:1028,3 -DA:1029,1 +DA:1029,2 DA:1030,4 -DA:1031,1 +DA:1031,2 DA:1032,4 -DA:1033,1 +DA:1033,2 DA:1034,4 -DA:1035,1 +DA:1035,2 DA:1036,4 -DA:1037,1 -DA:1038,4 +DA:1037,2 +DA:1038,8 DA:1039,1 DA:1040,4 DA:1041,1 @@ -6244,7 +6401,7 @@ LF:46 LH:46 end_of_record SF:lib/src/utils/nothing.dart -DA:6,339 +DA:6,313 DA:8,2 LF:2 LH:2 @@ -6334,7 +6491,7 @@ DA:297,8 DA:298,8 DA:299,8 DA:300,8 -DA:301,4 +DA:301,8 DA:302,2 DA:303,3 DA:304,3 @@ -6354,10 +6511,10 @@ DA:330,2 DA:331,1 DA:332,3 DA:333,1 -DA:339,0 -DA:340,0 -DA:341,0 -DA:342,0 +DA:339,1 +DA:340,2 +DA:341,1 +DA:342,1 DA:346,1 DA:347,1 DA:348,3 @@ -6369,24 +6526,105 @@ DA:358,1 DA:360,3 DA:361,3 DA:362,3 -DA:367,17 -DA:376,0 -DA:378,0 -DA:380,0 -DA:382,0 -DA:383,0 -DA:385,0 -DA:386,0 -DA:388,0 -DA:389,0 -DA:390,0 -DA:391,0 -DA:395,17 -DA:399,17 -DA:400,17 -DA:402,17 -DA:405,0 -DA:406,17 -LF:137 -LH:121 +DA:367,18 +DA:375,1 +DA:378,1 +DA:380,1 +DA:382,7 +DA:384,3 +DA:385,1 +DA:386,1 +DA:387,1 +DA:388,1 +DA:389,2 +DA:390,4 +DA:391,1 +DA:392,1 +DA:394,4 +DA:395,1 +DA:396,4 +DA:397,3 +DA:399,1 +DA:400,1 +DA:401,1 +DA:402,1 +DA:403,1 +DA:404,1 +DA:405,1 +DA:406,1 +DA:407,1 +DA:408,1 +DA:409,1 +DA:410,1 +DA:411,1 +DA:412,1 +DA:413,1 +DA:414,1 +DA:415,1 +DA:416,1 +DA:417,1 +DA:418,1 +DA:419,1 +DA:420,1 +DA:421,1 +DA:422,1 +DA:423,1 +DA:424,1 +DA:425,1 +DA:426,1 +DA:427,1 +DA:428,1 +DA:429,1 +DA:430,1 +DA:431,1 +DA:432,1 +DA:433,1 +DA:434,1 +DA:435,1 +DA:436,1 +DA:437,1 +DA:438,1 +DA:439,1 +DA:440,1 +DA:441,1 +DA:442,1 +DA:443,1 +DA:444,1 +DA:445,1 +DA:446,1 +DA:447,1 +DA:448,1 +DA:449,1 +DA:450,1 +DA:451,1 +DA:452,1 +DA:453,1 +DA:454,1 +DA:455,1 +DA:456,1 +DA:457,1 +DA:458,1 +DA:459,1 +DA:460,1 +DA:461,1 +DA:462,1 +DA:463,1 +DA:464,1 +DA:465,1 +DA:466,1 +DA:467,1 +DA:468,1 +DA:469,1 +DA:470,1 +DA:471,1 +DA:472,1 +DA:473,1 +DA:476,18 +DA:480,18 +DA:481,18 +DA:483,18 +DA:486,3 +DA:487,18 +LF:218 +LH:218 end_of_record diff --git a/example/lib/pages/components/chat_item_example.dart b/example/lib/pages/components/chat_item_example.dart index f1e4f039..8c76d190 100644 --- a/example/lib/pages/components/chat_item_example.dart +++ b/example/lib/pages/components/chat_item_example.dart @@ -2,20 +2,15 @@ import 'package:flutter/material.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -class ChatItemExample extends StatefulWidget { - static const String name = 'ChatItem'; +class ChatItemExample extends StatelessWidget { + static const String name = 'Chat Item'; const ChatItemExample({Key? key}) : super(key: key); - @override - State createState() => _ChatItemExampleState(); -} - -class _ChatItemExampleState extends State { @override Widget build(BuildContext context) { return ExampleScaffold( - name: 'Chat Item', + name: name, child: SingleChildScrollView( child: Column( children: [ diff --git a/example/lib/pages/components/chip_example.dart b/example/lib/pages/components/chip_example.dart index 2294e231..44231c66 100644 --- a/example/lib/pages/components/chip_example.dart +++ b/example/lib/pages/components/chip_example.dart @@ -24,7 +24,7 @@ class _ChipExampleState extends State { ZetaInputChip( label: 'Label', leading: const ZetaIcon(ZetaIcons.user), - trailing: ZetaIcon(ZetaIcons.close), + trailing: IconButton(icon: Icon(ZetaIcons.close), onPressed: () {}), ), ]); diff --git a/example/lib/pages/components/contact_item_example.dart b/example/lib/pages/components/contact_item_example.dart index cc566218..06fec413 100644 --- a/example/lib/pages/components/contact_item_example.dart +++ b/example/lib/pages/components/contact_item_example.dart @@ -16,11 +16,21 @@ class _ContactItemExampleState extends State { Widget build(BuildContext context) { return ExampleScaffold( name: ContactItemExample.name, - child: ZetaContactItem( - onTap: () {}, - leading: ZetaAvatar(size: ZetaAvatarSize.s), - title: Text("Contact / Group Name"), - subtitle: Text("Store Associate - Bakery Dept."), + child: Column( + children: [ + ZetaContactItem( + onTap: () {}, + leading: ZetaAvatar(size: ZetaAvatarSize.s), + title: Text("Contact / Group Name"), + subtitle: Text("Store Associate - Bakery Dept."), + ), + ZetaContactItem( + onTap: () {}, + leading: ZetaAvatar(size: ZetaAvatarSize.s), + title: Text("Contact / Group Name"), + subtitle: Text("Store Associate - Bakery Dept."), + ), + ], ), ); } diff --git a/example/lib/pages/components/dialog_example.dart b/example/lib/pages/components/dialog_example.dart index 25072683..aa286591 100644 --- a/example/lib/pages/components/dialog_example.dart +++ b/example/lib/pages/components/dialog_example.dart @@ -80,7 +80,7 @@ class DialogExample extends StatelessWidget { secondaryButtonLabel: 'Cancel', ), child: Text( - 'Show dialog with header to the left\nand sharp buttons', + 'Show dialog with header to the left', textAlign: TextAlign.center, ), ), diff --git a/example/lib/pages/components/dialpad_example.dart b/example/lib/pages/components/dialpad_example.dart index d77d76e6..09a5c783 100644 --- a/example/lib/pages/components/dialpad_example.dart +++ b/example/lib/pages/components/dialpad_example.dart @@ -24,67 +24,68 @@ class _DialPadExampleState extends State { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - width: constraints.maxWidth, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const SizedBox(width: _paddingSize), - SizedBox( - width: constraints.maxWidth - (_paddingSize * 2), - child: Text( - number, + SingleChildScrollView( + child: SizedBox( + width: constraints.maxWidth, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(width: _paddingSize), + SizedBox( + child: Text( + number, + style: ZetaTextStyles.heading3, + maxLines: 1, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + ), + ), + IconButton( + icon: ZetaIcon(Icons.backspace), + onPressed: () => number.length == 0 + ? null + : setState( + () => number = number.substring(0, (number.length - 1)), + ), + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Nothing(), + Text( + text, style: ZetaTextStyles.heading3, maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, ), - ), - IconButton( - icon: ZetaIcon(Icons.backspace), - onPressed: () => number.length == 0 - ? null - : setState( - () => number = number.substring(0, (number.length - 1)), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - const Nothing(), - Text( - text, - style: ZetaTextStyles.heading3, - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - ), - IconButton( - icon: ZetaIcon(Icons.backspace), - onPressed: () => text.length == 0 - ? null - : setState( - () => text = text.substring(0, text.length - 1), - ), - ) - ], - ), - ZetaDialPad( - onNumber: (value) => setState(() => number += value), - onText: (value) => setState(() => text += value), - ), - ZetaButton.primary( - label: 'Clear', - borderType: ZetaWidgetBorder.full, - onPressed: () => setState(() => number = text = ''), - ) - ].divide(const SizedBox(height: ZetaSpacing.xl_2)).toList(), + IconButton( + icon: ZetaIcon(Icons.backspace), + onPressed: () => text.length == 0 + ? null + : setState( + () => text = text.substring(0, text.length - 1), + ), + ) + ], + ), + ZetaDialPad( + onNumber: (value) => setState(() => number += value), + onText: (value) => setState(() => text += value), + ), + ZetaButton.primary( + label: 'Clear', + borderType: ZetaWidgetBorder.full, + onPressed: () => setState(() => number = text = ''), + ) + ].divide(const SizedBox(height: ZetaSpacing.xl_2)).toList(), + ), ), ), ], diff --git a/example/lib/pages/components/dropdown_example.dart b/example/lib/pages/components/dropdown_example.dart index 04a7e314..5ba039f2 100644 --- a/example/lib/pages/components/dropdown_example.dart +++ b/example/lib/pages/components/dropdown_example.dart @@ -33,7 +33,7 @@ class _DropdownExampleState extends State { name: "Dropdown", child: Column( crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ZetaDropdown( items: items, diff --git a/example/lib/pages/components/filter_selection_example.dart b/example/lib/pages/components/filter_selection_example.dart index 49d8e006..e79cfaff 100644 --- a/example/lib/pages/components/filter_selection_example.dart +++ b/example/lib/pages/components/filter_selection_example.dart @@ -24,6 +24,7 @@ class _FilterSelectionExampleState extends State { children: [ const SizedBox(height: ZetaSpacing.large), ZetaFilterSelection( + buttonSemanticLabel: 'Filter', items: [ for (int i = 0; i < items.length; i++) ZetaFilterChip( diff --git a/example/lib/pages/components/list_example.dart b/example/lib/pages/components/list_example.dart index 2c188a23..1f74c4bd 100644 --- a/example/lib/pages/components/list_example.dart +++ b/example/lib/pages/components/list_example.dart @@ -2,11 +2,18 @@ import 'package:flutter/material.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -class ListExample extends StatelessWidget { +class ListExample extends StatefulWidget { static const name = 'List'; const ListExample({super.key}); + @override + State createState() => _ListExampleState(); +} + +class _ListExampleState extends State { + List dropdownSelected = []; + @override Widget build(BuildContext context) { return ExampleScaffold( @@ -23,15 +30,24 @@ class ListExample extends StatelessWidget { items: [ ZetaListItem.checkbox( primaryText: 'Dropdown Item 1', - onChanged: (_) {}, + onChanged: (_) { + setState(() => dropdownSelected.contains(1) ? dropdownSelected.remove(1) : dropdownSelected = [1]); + }, + value: dropdownSelected.contains(1), ), ZetaListItem.checkbox( primaryText: 'Dropdown Item 2', - onChanged: (_) {}, + onChanged: (_) { + setState(() => dropdownSelected.contains(2) ? dropdownSelected.remove(2) : dropdownSelected = [2]); + }, + value: dropdownSelected.contains(2), ), ZetaListItem.checkbox( primaryText: 'Dropdown Item 3', - onChanged: (_) {}, + onChanged: (_) { + setState(() => dropdownSelected.contains(3) ? dropdownSelected.remove(3) : dropdownSelected = [3]); + }, + value: dropdownSelected.contains(3), ), ], ), diff --git a/example/lib/pages/components/notification_list_example.dart b/example/lib/pages/components/notification_list_example.dart index 5b908b70..c675051b 100644 --- a/example/lib/pages/components/notification_list_example.dart +++ b/example/lib/pages/components/notification_list_example.dart @@ -2,26 +2,17 @@ import 'package:flutter/material.dart'; import 'package:zeta_example/widgets.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -class NotificationListItemExample extends StatefulWidget { +class NotificationListItemExample extends StatelessWidget { + const NotificationListItemExample({Key? key}) : super(key: key); static const String name = 'NotificationListItem'; - const NotificationListItemExample({super.key}); - - @override - State createState() => _NotificationListItemExampleState(); -} - -class _NotificationListItemExampleState extends State { @override Widget build(BuildContext context) { return ExampleScaffold( - name: "NotificationListItem", - child: SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 400), - child: ZetaNotificationListItem( + name: name, + child: Column( + children: [ + ZetaNotificationListItem( body: Text( "New urgent" * 300, maxLines: 2, @@ -35,20 +26,9 @@ class _NotificationListItemExampleState extends State passwordInputExampleRow(ZetaWidgetSize size) { return [ ZetaPasswordInput( size: size, - hintText: 'Password', - placeholder: 'Password', + semanticLabel: 'Enter password', + showSemanticLabel: 'Show password', + obscureSemanticLabel: 'Hide password', ), SizedBox(height: 20), ZetaPasswordInput( @@ -83,7 +84,6 @@ List passwordInputExampleRow(ZetaWidgetSize size) { SizedBox(height: 20), ZetaPasswordInput( size: size, - label: 'Label', placeholder: 'Password', hintText: 'Default hint text', ), diff --git a/example/lib/pages/components/phone_input_example.dart b/example/lib/pages/components/phone_input_example.dart index cd0ab5cd..337b94fe 100644 --- a/example/lib/pages/components/phone_input_example.dart +++ b/example/lib/pages/components/phone_input_example.dart @@ -33,6 +33,7 @@ class _PhoneInputExampleState extends State { print(value); }, countries: ['US', 'GB', 'DE', 'AT', 'FR', 'IT', 'BG'], + selectCountrySemanticLabel: 'Choose country code', ), ), Divider(color: Colors.grey[200]), diff --git a/example/lib/pages/components/search_bar_example.dart b/example/lib/pages/components/search_bar_example.dart index afaf0520..691bcaab 100644 --- a/example/lib/pages/components/search_bar_example.dart +++ b/example/lib/pages/components/search_bar_example.dart @@ -44,17 +44,6 @@ class _SearchBarExampleState extends State { onSpeechToText: () async => 'I wanted to say...', ), ), - Padding( - padding: const EdgeInsets.only(top: 20), - child: Text('Sharp', style: ZetaTextStyles.titleMedium), - ), - Padding( - padding: const EdgeInsets.all(20), - child: ZetaSearchBar( - initialValue: 'Initial value', - shape: ZetaWidgetBorder.sharp, - ), - ), Padding( padding: const EdgeInsets.only(top: 20), child: Text('Disabled', style: ZetaTextStyles.titleMedium), diff --git a/example/lib/pages/components/segmented_control_example.dart b/example/lib/pages/components/segmented_control_example.dart index ef036160..ac69b3a4 100644 --- a/example/lib/pages/components/segmented_control_example.dart +++ b/example/lib/pages/components/segmented_control_example.dart @@ -30,6 +30,7 @@ class _SegmentedControlExampleState extends State { Padding( padding: const EdgeInsets.all(ZetaSpacing.xl_4), child: ZetaSegmentedControl( + semanticLabel: 'Segmented Control', segments: [ for (final value in _textSegments) ZetaButtonSegment( diff --git a/example/lib/pages/components/select_input_example.dart b/example/lib/pages/components/select_input_example.dart index 621310fa..9b7f850a 100644 --- a/example/lib/pages/components/select_input_example.dart +++ b/example/lib/pages/components/select_input_example.dart @@ -46,6 +46,7 @@ class _SelectInputExampleState extends State { placeholder: 'Placeholder', initialValue: "Item 1", items: items, + dropdownSemantics: 'Open dropdown', ), ZetaSelectInput( label: 'Medium', diff --git a/example/lib/pages/components/snackbar_example.dart b/example/lib/pages/components/snackbar_example.dart index 83f0a86c..25d79864 100644 --- a/example/lib/pages/components/snackbar_example.dart +++ b/example/lib/pages/components/snackbar_example.dart @@ -17,13 +17,13 @@ class SnackBarExample extends StatelessWidget { children: [ Column( children: [ - // Standard Rounded + // Standard Row( children: [ Padding( padding: const EdgeInsets.only(top: ZetaSpacing.large), child: ZetaButton.primary( - label: "Standard Rounded SnackBar", + label: "Standard SnackBar", onPressed: () { ScaffoldMessenger.of(context).showSnackBar( ZetaSnackBar( @@ -41,26 +41,6 @@ class SnackBarExample extends StatelessWidget { ], ), - // Standard Sharp - Padding( - padding: const EdgeInsets.only(top: ZetaSpacing.large), - child: ZetaButton.primary( - label: "Standard Sharp SnackBar", - onPressed: () { - ScaffoldMessenger.of(context).showSnackBar( - ZetaSnackBar( - context: context, - onPressed: () { - ScaffoldMessenger.of(context).hideCurrentSnackBar(); - }, - actionLabel: "Action", - content: Text('This is a snackbar'), - ), - ); - }, - ), - ), - // Default Padding( padding: const EdgeInsets.only(top: ZetaSpacing.large), diff --git a/example/lib/pages/components/time_input_example.dart b/example/lib/pages/components/time_input_example.dart index 24aee780..6c55299f 100644 --- a/example/lib/pages/components/time_input_example.dart +++ b/example/lib/pages/components/time_input_example.dart @@ -34,6 +34,8 @@ class TimeInputExample extends StatelessWidget { errorText: 'Oops! Error hint text', size: ZetaWidgetSize.large, initialValue: TimeOfDay.now(), + clearSemanticLabel: 'Clear', + timePickerSemanticLabel: 'Open time picker', ), ZetaTimeInput( label: 'Medium', diff --git a/lib/src/components/badges/label.dart b/lib/src/components/badges/label.dart index 285f0109..07c8f1b9 100644 --- a/lib/src/components/badges/label.dart +++ b/lib/src/components/badges/label.dart @@ -17,6 +17,7 @@ class ZetaLabel extends ZetaStatelessWidget { super.key, required this.label, this.status = ZetaWidgetStatus.info, + this.semanticLabel, }); /// {@template zeta-component-badge-status} @@ -29,20 +30,30 @@ class ZetaLabel extends ZetaStatelessWidget { /// Label of the badge. final String label; + /// The value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override Widget build(BuildContext context) { final Color backgroundColor = status.labelBackgroundColor(context); - return Container( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.minimum, vertical: ZetaSpacingBase.x0_5), - decoration: BoxDecoration( - color: backgroundColor, - borderRadius: context.rounded ? ZetaRadius.minimal : ZetaRadius.none, - ), - child: Text( - label, - style: ZetaTextStyles.labelSmall.apply(color: backgroundColor.onColor), - overflow: TextOverflow.ellipsis, + return Semantics( + label: semanticLabel ?? label, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.minimum, vertical: ZetaSpacingBase.x0_5), + decoration: BoxDecoration( + color: backgroundColor, + borderRadius: context.rounded ? ZetaRadius.minimal : ZetaRadius.none, + ), + child: Text( + label, + style: ZetaTextStyles.labelSmall.apply(color: backgroundColor.onColor), + overflow: TextOverflow.ellipsis, + ), ), ); } @@ -53,7 +64,8 @@ class ZetaLabel extends ZetaStatelessWidget { properties ..add(StringProperty('label', label)) ..add(EnumProperty('status', status)) - ..add(DiagnosticsProperty('rounded', rounded)); + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/badges/priority_pill.dart b/lib/src/components/badges/priority_pill.dart index 70db13f6..186a6970 100644 --- a/lib/src/components/badges/priority_pill.dart +++ b/lib/src/components/badges/priority_pill.dart @@ -58,6 +58,7 @@ class ZetaPriorityPill extends ZetaStatelessWidget { this.type = ZetaPriorityPillType.urgent, this.size = ZetaPriorityPillSize.large, this.customColor, + this.semanticLabel, }); /// Leading number / character in component. Will be truncated to single character. @@ -94,61 +95,72 @@ class ZetaPriorityPill extends ZetaStatelessWidget { /// Color override final ZetaColorSwatch? customColor; + /// The value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override Widget build(BuildContext context) { final ZetaColorSwatch color = customColor ?? type.color(context); final size = this.size == ZetaPriorityPillSize.small ? ZetaSpacing.xl_1 : ZetaSpacing.xl_3; - final label = this.label ?? priority; + final label = (this.label ?? priority) ?? type.name.capitalize(); final rounded = context.rounded; - return DecoratedBox( - decoration: BoxDecoration( - borderRadius: rounded ? ZetaRadius.full : ZetaRadius.none, - color: color.shade10, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - alignment: Alignment.center, - height: size, - width: size, - decoration: BoxDecoration( - shape: rounded ? BoxShape.circle : BoxShape.rectangle, - color: color, - ), - child: Text( - (index?.isEmpty ?? true) - ? (type == ZetaPriorityPillType.urgent - ? type.name.substring(0, 1).capitalize() - : type.index.toString()) - : index!.substring(0, 1).capitalize(), - style: this.size == ZetaPriorityPillSize.small - ? ZetaTextStyles.labelSmall.copyWith( - fontSize: 10, - height: 13 / 10, - color: color.onColor, - ) - : ZetaTextStyles.labelMedium.apply(color: color.onColor), - ), - ), - if (!isBadge) - Padding( - padding: const EdgeInsets.symmetric( - horizontal: ZetaSpacing.small, - vertical: ZetaSpacing.minimum, + + return Semantics( + value: semanticLabel ?? label, + child: DecoratedBox( + decoration: BoxDecoration( + borderRadius: rounded ? ZetaRadius.full : ZetaRadius.none, + color: color.shade10, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + alignment: Alignment.center, + height: size, + width: size, + decoration: BoxDecoration( + shape: rounded ? BoxShape.circle : BoxShape.rectangle, + color: color, ), child: Text( - (label?.isEmpty ?? true) ? type.name.capitalize() : label!, + (index?.isEmpty ?? true) + ? (type == ZetaPriorityPillType.urgent + ? type.name.substring(0, 1).capitalize() + : type.index.toString()) + : index!.substring(0, 1).capitalize(), style: this.size == ZetaPriorityPillSize.small - ? ZetaTextStyles.bodyXSmall.copyWith( + ? ZetaTextStyles.labelSmall.copyWith( fontSize: 10, height: 13 / 10, + color: color.onColor, ) - : ZetaTextStyles.bodySmall, - overflow: TextOverflow.ellipsis, + : ZetaTextStyles.labelMedium.apply(color: color.onColor), ), ), - ], + if (!isBadge) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: ZetaSpacing.small, + vertical: ZetaSpacing.minimum, + ), + child: Text( + label, + style: this.size == ZetaPriorityPillSize.small + ? ZetaTextStyles.bodyXSmall.copyWith( + fontSize: 10, + height: 13 / 10, + ) + : ZetaTextStyles.bodySmall, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), ), ); } @@ -164,6 +176,7 @@ class ZetaPriorityPill extends ZetaStatelessWidget { ..add(EnumProperty('size', size)) ..add(StringProperty('label', label)) ..add(ColorProperty('customColor', customColor)) - ..add(StringProperty('priority', priority)); + ..add(StringProperty('priority', priority)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/badges/status_label.dart b/lib/src/components/badges/status_label.dart index 46d3d6e8..d085b824 100644 --- a/lib/src/components/badges/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -14,6 +14,7 @@ class ZetaStatusLabel extends ZetaStatelessWidget { required this.label, this.status = ZetaWidgetStatus.info, this.customIcon, + this.semanticLabel, }); /// {@macro zeta-component-badge-status} @@ -25,33 +26,43 @@ class ZetaStatusLabel extends ZetaStatelessWidget { /// Optional custom icon. If null, default circle icon is used. final IconData? customIcon; + /// The value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override Widget build(BuildContext context) { final ZetaColorSwatch colors = status.colorSwatch(context); - return DecoratedBox( - decoration: BoxDecoration( - color: colors.shade10, - border: Border.all(color: colors.border), - borderRadius: context.rounded ? ZetaRadius.full : ZetaRadius.none, - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.small, vertical: ZetaSpacingBase.x0_5), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - ZetaIcon( - customIcon ?? Icons.circle, - size: customIcon != null ? ZetaSpacing.xl_1 : ZetaSpacing.small, - color: colors.icon, - ), - const SizedBox(width: ZetaSpacing.small), - Text( - label, - style: ZetaTextStyles.bodyMedium.apply(color: colors.shade10.onColor), - overflow: TextOverflow.ellipsis, - ), - ], + return Semantics( + value: semanticLabel ?? label, + child: DecoratedBox( + decoration: BoxDecoration( + color: colors.shade10, + border: Border.all(color: colors.border), + borderRadius: context.rounded ? ZetaRadius.full : ZetaRadius.none, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.small, vertical: ZetaSpacingBase.x0_5), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + customIcon ?? Icons.circle, + size: customIcon != null ? ZetaSpacing.xl_1 : ZetaSpacing.small, + color: colors.icon, + ), + const SizedBox(width: ZetaSpacing.small), + Text( + label, + style: ZetaTextStyles.bodyMedium.apply(color: colors.shade10.onColor), + overflow: TextOverflow.ellipsis, + ), + ], + ), ), ), ); @@ -64,6 +75,7 @@ class ZetaStatusLabel extends ZetaStatelessWidget { ..add(StringProperty('label', label)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('customIcon', customIcon)) - ..add(EnumProperty('status', status)); + ..add(EnumProperty('status', status)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/badges/tag.dart b/lib/src/components/badges/tag.dart index 4541243c..d7a80815 100644 --- a/lib/src/components/badges/tag.dart +++ b/lib/src/components/badges/tag.dart @@ -20,13 +20,16 @@ class ZetaTag extends ZetaStatelessWidget { super.rounded, this.direction = ZetaTagDirection.left, required this.label, + this.semanticLabel, }); /// Constructs left facing [ZetaTag]. - const ZetaTag.left({super.key, super.rounded, required this.label}) : direction = ZetaTagDirection.left; + const ZetaTag.left({super.key, super.rounded, required this.label, this.semanticLabel}) + : direction = ZetaTagDirection.left; ///Constructs right facing [ZetaTag]. - const ZetaTag.right({super.key, super.rounded, required this.label}) : direction = ZetaTagDirection.right; + const ZetaTag.right({super.key, super.rounded, required this.label, this.semanticLabel}) + : direction = ZetaTagDirection.right; ///Determines the direction of the tag /// @@ -36,36 +39,46 @@ class ZetaTag extends ZetaStatelessWidget { ///tag label final String label; + /// The value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + /// Fixed container size static const Size _containerSize = Size(ZetaSpacing.xl_5, ZetaSpacing.xl_3); @override Widget build(BuildContext context) { - return Row( - children: [ - if (direction == ZetaTagDirection.left) _buildCustomPaint(context), - Container( - decoration: BoxDecoration( - color: Zeta.of(context).colors.surfaceHover, - borderRadius: _getBorderRadius(context), - ), - height: _containerSize.height, - constraints: BoxConstraints(minWidth: _containerSize.width), - child: Center( - child: FittedBox( - child: Padding( - padding: const EdgeInsets.fromLTRB(ZetaSpacing.small, 1, ZetaSpacing.small, 1), - child: Text( - label, - style: ZetaTextStyles.bodyMedium, - overflow: TextOverflow.ellipsis, + return Semantics( + value: semanticLabel ?? label, + child: Row( + children: [ + if (direction == ZetaTagDirection.left) _buildCustomPaint(context), + Container( + decoration: BoxDecoration( + color: Zeta.of(context).colors.surfaceHover, + borderRadius: _getBorderRadius(context), + ), + height: _containerSize.height, + constraints: BoxConstraints(minWidth: _containerSize.width), + child: Center( + child: FittedBox( + child: Padding( + padding: const EdgeInsets.fromLTRB(ZetaSpacing.small, 1, ZetaSpacing.small, 1), + child: Text( + label, + style: ZetaTextStyles.bodyMedium, + overflow: TextOverflow.ellipsis, + ), ), ), ), ), - ), - if (direction == ZetaTagDirection.right) _buildCustomPaint(context), - ], + if (direction == ZetaTagDirection.right) _buildCustomPaint(context), + ], + ), ); } @@ -101,7 +114,8 @@ class ZetaTag extends ZetaStatelessWidget { properties ..add(EnumProperty('direction', direction)) ..add(StringProperty('label', label)) - ..add(DiagnosticsProperty('rounded', rounded)); + ..add(DiagnosticsProperty('rounded', rounded)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/banner/banner.dart b/lib/src/components/banner/banner.dart index ed290e87..e27762e3 100644 --- a/lib/src/components/banner/banner.dart +++ b/lib/src/components/banner/banner.dart @@ -37,12 +37,29 @@ class ZetaBanner extends MaterialBanner { ZetaBanner({ super.key, required BuildContext context, + + /// The title of the banner. required String title, + + /// The leading icon for the banner. IconData? leadingIcon, + + /// The type of banner. See [ZetaBannerStatus]. ZetaBannerStatus type = ZetaBannerStatus.primary, + + /// Whether the title should be centered. bool titleStart = false, + + /// The trailing widget for the banner. Widget? trailing, + + /// {@macro zeta-component-rounded} bool? rounded, + + /// The semantic label for the banner. + /// + /// If this is null, the title will be used. + String? semanticLabel, }) : super( dividerColor: Colors.transparent, content: Builder( @@ -64,25 +81,28 @@ class ZetaBanner extends MaterialBanner { return ZetaRoundedScope( rounded: rounded ?? context.rounded, - child: DefaultTextStyle( - style: ZetaTextStyles.labelLarge.copyWith( - color: foregroundColor, - overflow: TextOverflow.ellipsis, - ), - child: Row( - mainAxisAlignment: titleStart ? MainAxisAlignment.center : MainAxisAlignment.start, - children: [ - if (leadingIcon != null) - Padding( - padding: const EdgeInsets.only(right: ZetaSpacing.small), - child: ZetaIcon( - leadingIcon, - color: foregroundColor, - size: ZetaSpacing.xl_2, + child: Semantics( + label: semanticLabel ?? title, + child: DefaultTextStyle( + style: ZetaTextStyles.labelLarge.copyWith( + color: foregroundColor, + overflow: TextOverflow.ellipsis, + ), + child: Row( + mainAxisAlignment: titleStart ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + if (leadingIcon != null) + Padding( + padding: const EdgeInsets.only(right: ZetaSpacing.small), + child: Icon( + leadingIcon, + color: foregroundColor, + size: ZetaSpacing.xl_2, + ), ), - ), - Flexible(child: Text(title)), - ], + Flexible(child: Text(title)), + ], + ), ), ), ); diff --git a/lib/src/components/breadcrumbs/breadcrumbs.dart b/lib/src/components/breadcrumbs/breadcrumbs.dart index a7d33afe..5b6bfa8c 100644 --- a/lib/src/components/breadcrumbs/breadcrumbs.dart +++ b/lib/src/components/breadcrumbs/breadcrumbs.dart @@ -124,6 +124,7 @@ class ZetaBreadCrumb extends StatefulWidget { this.isSelected = false, required this.onPressed, this.activeIcon, + this.semanticLabel, }); /// [ZetaBreadCrumb] label. @@ -141,6 +142,13 @@ class ZetaBreadCrumb extends StatefulWidget { /// Active icon for [ZetaBreadCrumb] final IconData? activeIcon; + /// Label passed to wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override State createState() => _ZetaBreadCrumbState(); @@ -152,7 +160,8 @@ class ZetaBreadCrumb extends StatefulWidget { ..add(StringProperty('label', label)) ..add(DiagnosticsProperty('icon', icon)) ..add(DiagnosticsProperty('isSelected', isSelected)) - ..add(DiagnosticsProperty('activeIcon', activeIcon)); + ..add(DiagnosticsProperty('activeIcon', activeIcon)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -172,29 +181,33 @@ class _ZetaBreadCrumbState extends State { @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return InkWell( - statesController: controller, - onTap: widget.onPressed, - enableFeedback: false, - splashColor: Colors.transparent, - overlayColor: WidgetStateProperty.resolveWith((states) { - return Colors.transparent; - }), - child: Row( - children: [ - if (widget.isSelected) - ZetaIcon( - widget.activeIcon ?? ZetaIcons.star, - color: getColor(controller.value, colors), + return Semantics( + label: widget.semanticLabel ?? widget.label, + selected: widget.isSelected, + child: InkWell( + statesController: controller, + onTap: widget.onPressed, + enableFeedback: false, + splashColor: Colors.transparent, + overlayColor: WidgetStateProperty.resolveWith((states) { + return Colors.transparent; + }), + child: Row( + children: [ + if (widget.isSelected) + Icon( + widget.activeIcon ?? ZetaIcons.star_round, + color: getColor(controller.value, colors), + ), + const SizedBox( + width: ZetaSpacing.small, + ), + Text( + widget.label, + style: ZetaTextStyles.bodySmall.apply(color: getColor(controller.value, colors)), ), - const SizedBox( - width: ZetaSpacing.small, - ), - Text( - widget.label, - style: ZetaTextStyles.bodySmall.apply(color: getColor(controller.value, colors)), - ), - ], + ], + ), ), ); } @@ -226,13 +239,24 @@ class BreadCrumbsTruncated extends StatefulWidget { const BreadCrumbsTruncated({ super.key, required this.children, + this.semanticLabel = 'More breadcrumbs', }); ///Breadcrumb children final List children; + /// Label passed to wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + final String semanticLabel; + @override State createState() => _BreadCrumbsTruncatedState(); + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(StringProperty('semanticLabel', semanticLabel)); + } } class _BreadCrumbsTruncatedState extends State { @@ -245,56 +269,60 @@ class _BreadCrumbsTruncatedState extends State { return _expanded ? expandedBreadcrumb() - : FilledButton( - onPressed: () { - setState(() { - _expanded = true; - }); - }, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.hovered)) { - return colors.surfaceHover; - } - if (states.contains(WidgetState.pressed)) { - return colors.primary.shade10; - } - if (states.contains(WidgetState.disabled)) { - return colors.surfaceDisabled; - } - return colors.warm.shade10; - }), - foregroundColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.disabled)) { - return colors.textDisabled; - } - return colors.textDefault; - }), - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: (rounded ? ZetaRadius.minimal : ZetaRadius.none), + : Semantics( + label: widget.semanticLabel, + button: true, + child: FilledButton( + onPressed: () { + setState(() { + _expanded = true; + }); + }, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.hovered)) { + return colors.surfaceHover; + } + if (states.contains(WidgetState.pressed)) { + return colors.primary.shade10; + } + if (states.contains(WidgetState.disabled)) { + return colors.surfaceDisabled; + } + return colors.warm.shade10; + }), + foregroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return colors.textDisabled; + } + return colors.textDefault; + }), + shape: WidgetStatePropertyAll( + RoundedRectangleBorder( + borderRadius: (rounded ? ZetaRadius.minimal : ZetaRadius.none), + ), ), + side: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.focused)) { + return BorderSide( + width: ZetaSpacingBase.x0_5, + color: colors.primary.shade100, + ); + } + if (states.isEmpty) { + return BorderSide(color: colors.borderDefault, width: 0.5); + } + return null; + }), + padding: WidgetStateProperty.all(EdgeInsets.zero), + minimumSize: WidgetStateProperty.all(Size.zero), + elevation: const WidgetStatePropertyAll(ZetaSpacing.none), ), - side: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.focused)) { - return BorderSide( - width: ZetaSpacingBase.x0_5, - color: colors.primary.shade100, - ); - } - if (states.isEmpty) { - return BorderSide(color: colors.borderDefault, width: 0.5); - } - return null; - }), - padding: WidgetStateProperty.all(EdgeInsets.zero), - minimumSize: WidgetStateProperty.all(Size.zero), - elevation: const WidgetStatePropertyAll(ZetaSpacing.none), + child: Icon( + rounded ? ZetaIcons.more_horizontal_round : ZetaIcons.more_horizontal_sharp, + size: ZetaSpacing.large, + ).paddingHorizontal(ZetaSpacing.small).paddingVertical(ZetaSpacing.minimum), ), - child: const ZetaIcon( - ZetaIcons.more_horizontal, - size: ZetaSpacing.large, - ).paddingHorizontal(ZetaSpacing.small).paddingVertical(ZetaSpacing.minimum), ); } diff --git a/lib/src/components/button_group/button_group.dart b/lib/src/components/button_group/button_group.dart index 2c53fad4..ae433c38 100644 --- a/lib/src/components/button_group/button_group.dart +++ b/lib/src/components/button_group/button_group.dart @@ -73,6 +73,7 @@ class ZetaGroupButton extends ZetaStatefulWidget { this.onPressed, this.label, this.icon, + this.semanticLabel, }) : isFinal = false, isInitial = false, isInverse = false, @@ -95,17 +96,19 @@ class ZetaGroupButton extends ZetaStatefulWidget { this.icon, this.onPressed, this.items, + this.semanticLabel, }); /// Constructs dropdown group button const ZetaGroupButton.dropdown({ + super.key, + super.rounded, required this.items, this.onChange, this.initialValue, this.icon, this.label, - super.key, - super.rounded, + this.semanticLabel, }) : isFinal = false, isInitial = false, isInverse = false, @@ -119,6 +122,7 @@ class ZetaGroupButton extends ZetaStatefulWidget { required this.icon, this.onPressed, this.label, + this.semanticLabel, }) : isFinal = false, isInitial = false, isInverse = false, @@ -162,6 +166,13 @@ class ZetaGroupButton extends ZetaStatefulWidget { /// If [ZetaGroupButton] is inverse. final bool isInverse; + /// Semantic label for [ZetaGroupButton]. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If this property is null, [label] will be used instead. + final String? semanticLabel; + @override State createState() => _ZetaGroupButtonState(); @@ -172,6 +183,7 @@ class ZetaGroupButton extends ZetaStatefulWidget { bool? isLarge, bool? rounded, bool? isInverse, + String? semanticLabel, }) { return ZetaGroupButton._( key: key, @@ -186,6 +198,7 @@ class ZetaGroupButton extends ZetaStatefulWidget { isLarge: isLarge ?? this.isLarge, rounded: rounded ?? this.rounded, isInverse: isInverse ?? this.isInverse, + semanticLabel: semanticLabel ?? this.semanticLabel, ); } @@ -202,17 +215,18 @@ class ZetaGroupButton extends ZetaStatefulWidget { ..add(DiagnosticsProperty('isInverse', isInverse)) ..add(IterableProperty>('dropdownItems', items)) ..add(ObjectFlagProperty selectedItem)?>.has('onChange', onChange)) - ..add(DiagnosticsProperty('initialValue', initialValue)); + ..add(DiagnosticsProperty('initialValue', initialValue)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } class _ZetaGroupButtonState extends State { - WidgetStatesController controller = WidgetStatesController(); + final WidgetStatesController _controller = WidgetStatesController(); @override void dispose() { super.dispose(); - controller.dispose(); + _controller.dispose(); } @override @@ -229,10 +243,10 @@ class _ZetaGroupButtonState extends State { ZetaColors colors, bool finalButton, ) { - if (controller.value.contains(WidgetState.focused)) { + if (_controller.value.contains(WidgetState.focused)) { return BorderSide(color: colors.blue.shade50, width: ZetaSpacingBase.x0_5); } - if (controller.value.contains(WidgetState.disabled)) { + if (_controller.value.contains(WidgetState.disabled)) { return BorderSide(color: colors.cool.shade40); } return BorderSide( @@ -256,39 +270,6 @@ class _ZetaGroupButtonState extends State { return ZetaRadius.none; } - ButtonStyle getStyle(ZetaWidgetBorder borderType, ZetaColors colors) { - return ButtonStyle( - shape: WidgetStateProperty.all( - RoundedRectangleBorder( - borderRadius: _getRadius(borderType), - ), - ), - backgroundColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.disabled)) { - return colors.surfaceDisabled; - } - if (states.contains(WidgetState.pressed)) { - return widget.isInverse ? colors.cool.shade100 : colors.primary.shade10; - } - if (states.contains(WidgetState.hovered)) { - return widget.isInverse ? colors.cool.shade90 : colors.cool.shade20; - } - if (widget.isInverse) return colors.cool.shade100; - - return colors.surfacePrimary; - }), - foregroundColor: WidgetStateProperty.resolveWith((states) { - if (states.contains(WidgetState.disabled)) { - return colors.textDisabled; - } - if (widget.isInverse) return colors.cool.shade100.onColor; - return colors.textDefault; - }), - elevation: const WidgetStatePropertyAll(ZetaSpacing.none), - padding: WidgetStateProperty.all(EdgeInsets.zero), - ); - } - Widget _getButton( VoidCallback? onPressed, { bool dropdownOpen = false, @@ -327,7 +308,7 @@ class _ZetaGroupButtonState extends State { top: borderSide, left: borderSide, bottom: borderSide, - right: controller.value.contains(WidgetState.focused) + right: _controller.value.contains(WidgetState.focused) ? BorderSide(color: colors.blue.shade50, width: 2) : (widget.isFinal) ? borderSide @@ -336,23 +317,54 @@ class _ZetaGroupButtonState extends State { borderRadius: _getRadius(borderType), ), padding: EdgeInsets.zero, - child: FilledButton( - statesController: controller, - onPressed: onPressed, - style: getStyle(borderType, colors), - child: SelectionContainer.disabled( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - leadingIcon ?? const Nothing(), - Text(selectedItem?.label ?? widget.label ?? '', style: ZetaTextStyles.labelMedium), - if (widget.items != null) - ZetaIcon( - dropdownIcon, - size: ZetaSpacing.xl_1, - ), - ].divide(const SizedBox(width: ZetaSpacing.minimum)).toList(), - ).paddingAll(_padding), + child: ExcludeSemantics( + child: FilledButton( + statesController: _controller, + onPressed: onPressed, + style: ButtonStyle( + shape: WidgetStateProperty.all( + RoundedRectangleBorder( + borderRadius: _getRadius(borderType), + ), + ), + backgroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return colors.surfaceDisabled; + } + if (states.contains(WidgetState.pressed)) { + return widget.isInverse ? colors.cool.shade100 : colors.primary.shade10; + } + if (states.contains(WidgetState.hovered)) { + return widget.isInverse ? colors.cool.shade90 : colors.cool.shade20; + } + if (widget.isInverse) return colors.cool.shade100; + + return colors.surfacePrimary; + }), + foregroundColor: WidgetStateProperty.resolveWith((states) { + if (states.contains(WidgetState.disabled)) { + return colors.textDisabled; + } + if (widget.isInverse) return colors.cool.shade100.onColor; + return colors.textDefault; + }), + elevation: const WidgetStatePropertyAll(ZetaSpacing.none), + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + child: SelectionContainer.disabled( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + leadingIcon ?? const Nothing(), + Text(selectedItem?.label ?? widget.label ?? '', style: ZetaTextStyles.labelMedium), + if (widget.items != null) + Icon( + dropdownIcon, + size: ZetaSpacing.xl_1, + ), + ].divide(const SizedBox(width: ZetaSpacing.minimum)).toList(), + ).paddingAll(_padding), + ), ), ), ); @@ -368,7 +380,6 @@ class _ZetaGroupButtonState extends State { child = ZetaDropdown( items: widget.items!, onChange: widget.onChange, - onDismissed: () => setState(() {}), value: widget.initialValue, rounded: rounded, builder: (context, selectedItem, controller) { @@ -383,12 +394,20 @@ class _ZetaGroupButtonState extends State { child = _getButton(widget.onPressed); } - return child; + // TODO(thelukewalton): Selected prop in semantics does not work as expected. + + return Semantics( + label: widget.semanticLabel ?? widget.label, + button: true, + enabled: (widget.onPressed != null) || (widget.items != null), + selected: (widget.items != null) ? _controller.value.contains(WidgetState.selected) : null, + child: child, + ); } @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(DiagnosticsProperty('controller', controller)); + properties.add(DiagnosticsProperty('controller', _controller)); } } diff --git a/lib/src/components/buttons/button.dart b/lib/src/components/buttons/button.dart index 2cc2afd8..08546384 100644 --- a/lib/src/components/buttons/button.dart +++ b/lib/src/components/buttons/button.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; ///Zeta Button -class ZetaButton extends StatelessWidget { +class ZetaButton extends ZetaStatelessWidget { ///Constructs [ZetaButton] const ZetaButton({ super.key, @@ -16,6 +16,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }); /// Constructs [ZetaButton] with Primary theme. @@ -28,6 +29,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.primary; /// Constructs [ZetaButton] with Secondary theme. @@ -40,6 +42,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.secondary; /// Constructs [ZetaButton] with Positive theme. @@ -52,6 +55,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.positive; /// Constructs [ZetaButton] with Negative theme. @@ -64,6 +68,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.negative; /// Constructs [ZetaButton] with Outline theme. @@ -76,6 +81,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.outline; /// Constructs [ZetaButton] with Outline Subtle theme. @@ -88,6 +94,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.outlineSubtle; /// Constructs [ZetaButton] with text theme. @@ -100,6 +107,7 @@ class ZetaButton extends StatelessWidget { this.leadingIcon, this.trailingIcon, this.focusNode, + this.semanticLabel, }) : type = ZetaButtonType.text; /// Button label @@ -129,6 +137,13 @@ class ZetaButton extends StatelessWidget { /// {@macro flutter.widgets.Focus.focusNode} final FocusNode? focusNode; + /// The semantic label of the button. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If this property is null, [label] will be used instead. + final String? semanticLabel; + /// Creates a clone. ZetaButton copyWith({ String? label, @@ -155,44 +170,50 @@ class ZetaButton extends StatelessWidget { @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return ConstrainedBox( - constraints: BoxConstraints(minHeight: _minConstraints, minWidth: _minConstraints), - child: FilledButton( - focusNode: focusNode, - onPressed: onPressed, - style: buttonStyle( - colors, - borderType ?? (context.rounded ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp), - type, - null, - ), - child: SelectionContainer.disabled( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (leadingIcon != null) - ZetaIcon( - leadingIcon, - size: _iconSize, - ), - if (label.isNotEmpty) - Text( - label, - style: _textStyle, - ), - if (trailingIcon != null) - ZetaIcon( - trailingIcon, - size: _iconSize, - ), - ] - .divide( - const SizedBox( - width: ZetaSpacing.small, + return Semantics( + button: true, + enabled: onPressed != null, + label: semanticLabel ?? label, + excludeSemantics: true, + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: _minConstraints, minWidth: _minConstraints), + child: FilledButton( + focusNode: focusNode, + onPressed: onPressed, + style: buttonStyle( + colors, + borderType ?? (context.rounded ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp), + type, + null, + ), + child: SelectionContainer.disabled( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (leadingIcon != null) + Icon( + leadingIcon, + size: _iconSize, + ), + if (label.isNotEmpty) + Text( + label, + style: _textStyle, + ), + if (trailingIcon != null) + Icon( + trailingIcon, + size: _iconSize, ), - ) - .toList(), - ).paddingHorizontal(_textPadding), + ] + .divide( + const SizedBox( + width: ZetaSpacing.small, + ), + ) + .toList(), + ).paddingHorizontal(_textPadding), + ), ), ), ); @@ -247,6 +268,7 @@ class ZetaButton extends StatelessWidget { ..add(EnumProperty('size', size)) ..add(DiagnosticsProperty('leadingIcon', leadingIcon)) ..add(DiagnosticsProperty('trailingIcon', trailingIcon)) - ..add(DiagnosticsProperty('focusNode', focusNode)); + ..add(DiagnosticsProperty('focusNode', focusNode)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/buttons/icon_button.dart b/lib/src/components/buttons/icon_button.dart index a09d33ee..25296527 100644 --- a/lib/src/components/buttons/icon_button.dart +++ b/lib/src/components/buttons/icon_button.dart @@ -8,74 +8,90 @@ class ZetaIconButton extends ZetaStatelessWidget { /// Constructor for [ZetaIconButton] const ZetaIconButton({ super.key, + super.rounded, this.onPressed, this.borderType, this.type = ZetaButtonType.primary, this.size = ZetaWidgetSize.medium, this.icon = ZetaIcons.more_horizontal, + this.semanticLabel, }); /// Constructs [ZetaIconButton] with Primary theme. const ZetaIconButton.primary({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.primary; /// Constructs [ZetaIconButton] with Secondary theme. const ZetaIconButton.secondary({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.secondary; /// Constructs [ZetaIconButton] with Positive theme. const ZetaIconButton.positive({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.positive; /// Constructs [ZetaIconButton] with Negative theme. const ZetaIconButton.negative({ + super.key, + super.rounded, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, required this.icon, - super.key, + this.semanticLabel, }) : type = ZetaButtonType.negative; /// Constructs [ZetaIconButton] with Outline theme. const ZetaIconButton.outline({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.outline; /// Constructs [ZetaIconButton] with Outline Subtle theme. const ZetaIconButton.outlineSubtle({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.outlineSubtle; /// Constructs [ZetaIconButton] with text theme. const ZetaIconButton.text({ super.key, + super.rounded, required this.icon, this.onPressed, this.size = ZetaWidgetSize.medium, this.borderType, + this.semanticLabel, }) : type = ZetaButtonType.text; /// Button icon. @@ -96,19 +112,29 @@ class ZetaIconButton extends ZetaStatelessWidget { /// Size of the button. Defaults to large. final ZetaWidgetSize size; + /// A semantic description of the button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return FilledButton( - onPressed: onPressed, - style: buttonStyle( - colors, - borderType ?? (context.rounded ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp), - type, - null, + return MergeSemantics( + child: Semantics( + label: semanticLabel, + child: FilledButton( + onPressed: onPressed, + style: buttonStyle( + colors, + borderType ?? (context.rounded ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp), + type, + null, + ), + child: SelectionContainer.disabled(child: ZetaIcon(icon, size: _iconSize).paddingAll(_iconPadding)), + ), ), - child: SelectionContainer.disabled(child: ZetaIcon(icon, size: _iconSize).paddingAll(_iconPadding)), ); } @@ -142,6 +168,7 @@ class ZetaIconButton extends ZetaStatelessWidget { ..add(EnumProperty('borderType', borderType)) ..add(DiagnosticsProperty('icon', icon)) ..add(ObjectFlagProperty.has('onPressed', onPressed)) - ..add(EnumProperty('type', type)); + ..add(EnumProperty('type', type)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/buttons/input_icon_button.dart b/lib/src/components/buttons/input_icon_button.dart index 515e0566..54762d4b 100644 --- a/lib/src/components/buttons/input_icon_button.dart +++ b/lib/src/components/buttons/input_icon_button.dart @@ -13,6 +13,7 @@ class InputIconButton extends StatelessWidget { required this.disabled, required this.size, required this.color, + this.semanticLabel, }); /// The icon @@ -32,6 +33,11 @@ class InputIconButton extends StatelessWidget { /// The color of the icon final Color color; + /// The semantic label of the icon. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + double get _iconSize { switch (size) { case ZetaWidgetSize.large: @@ -47,18 +53,24 @@ class InputIconButton extends StatelessWidget { Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return IconButton( - padding: EdgeInsets.all(_iconSize / 2), - constraints: BoxConstraints( - maxHeight: _iconSize * 2, - maxWidth: _iconSize * 2, - minHeight: _iconSize * 2, - minWidth: _iconSize * 2, + return Semantics( + button: true, + label: semanticLabel, + enabled: !disabled, + excludeSemantics: true, + child: IconButton( + padding: EdgeInsets.all(_iconSize / 2), + constraints: BoxConstraints( + maxHeight: _iconSize * 2, + maxWidth: _iconSize * 2, + minHeight: _iconSize * 2, + minWidth: _iconSize * 2, + ), + color: !disabled ? color : colors.iconDisabled, + onPressed: disabled ? null : onTap, + iconSize: _iconSize, + icon: ZetaIcon(icon), ), - color: !disabled ? color : colors.iconDisabled, - onPressed: disabled ? null : onTap, - iconSize: _iconSize, - icon: ZetaIcon(icon), ); } @@ -70,6 +82,7 @@ class InputIconButton extends StatelessWidget { ..add(ObjectFlagProperty.has('onTap', onTap)) ..add(DiagnosticsProperty('disabled', disabled)) ..add(ColorProperty('color', color)) - ..add(EnumProperty('size', size)); + ..add(EnumProperty('size', size)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/checkbox/checkbox.dart b/lib/src/components/checkbox/checkbox.dart index 4edd887a..441aadac 100644 --- a/lib/src/components/checkbox/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -20,6 +20,7 @@ class ZetaCheckbox extends FormField { this.rounded, this.useIndeterminate = false, this.focusNode, + this.semanticLabel, super.validator, super.autovalidateMode, super.restorationId, @@ -40,6 +41,7 @@ class ZetaCheckbox extends FormField { error: !field.isValid, disabled: onChanged == null, focusNode: focusNode, + semanticLabel: semanticLabel, ); }, ); @@ -66,6 +68,13 @@ class ZetaCheckbox extends FormField { /// {@macro flutter.widgets.Focus.focusNode} final FocusNode? focusNode; + /// Value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override ZetaCheckboxFormFieldState createState() => ZetaCheckboxFormFieldState(); @override @@ -77,7 +86,8 @@ class ZetaCheckbox extends FormField { ..add(DiagnosticsProperty('useIndeterminate', useIndeterminate)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(ObjectFlagProperty?>.has('onChanged', onChanged)) - ..add(DiagnosticsProperty('focusNode', focusNode)); + ..add(DiagnosticsProperty('focusNode', focusNode)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -101,6 +111,7 @@ class ZetaInternalCheckbox extends ZetaStatefulWidget { this.useIndeterminate = false, this.error = false, this.focusNode, + this.semanticLabel, super.rounded, }); @@ -127,6 +138,13 @@ class ZetaInternalCheckbox extends ZetaStatefulWidget { /// {@macro flutter.widgets.Focus.focusNode} final FocusNode? focusNode; + /// Value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override State createState() => _CheckboxState(); @override @@ -140,7 +158,8 @@ class ZetaInternalCheckbox extends ZetaStatefulWidget { ..add(DiagnosticsProperty('error', error)) ..add(DiagnosticsProperty('disabled', disabled)) ..add(ObjectFlagProperty>.has('onChanged', onChanged)) - ..add(DiagnosticsProperty('focusNode', focusNode)); + ..add(DiagnosticsProperty('focusNode', focusNode)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -160,17 +179,21 @@ class _CheckboxState extends State { @override Widget build(BuildContext context) { - return Material( - color: Colors.transparent, - child: InkWell( - onTap: !widget.disabled ? () => widget.onChanged.call(!_checked) : null, - borderRadius: ZetaRadius.full, - child: Padding( - padding: const EdgeInsets.all(ZetaSpacing.medium), - child: Semantics( - mixed: widget.useIndeterminate, - enabled: !widget.disabled, - focusable: true, + return Semantics( + mixed: widget.useIndeterminate, + enabled: !widget.disabled, + focusable: true, + container: true, + excludeSemantics: true, + checked: !widget.useIndeterminate && _checked, + label: widget.semanticLabel ?? widget.label, + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: !widget.disabled ? () => widget.onChanged.call(!_checked) : null, + borderRadius: ZetaRadius.full, + child: Padding( + padding: const EdgeInsets.all(ZetaSpacing.medium), child: MouseRegion( cursor: !widget.disabled ? SystemMouseCursors.click : SystemMouseCursors.forbidden, onEnter: (event) => _setHovered(true), diff --git a/lib/src/components/chips/assist_chip.dart b/lib/src/components/chips/assist_chip.dart index 58e93c58..df5adcb0 100644 --- a/lib/src/components/chips/assist_chip.dart +++ b/lib/src/components/chips/assist_chip.dart @@ -12,13 +12,14 @@ import '../../../zeta_flutter.dart'; class ZetaAssistChip extends ZetaChip { /// Creates a [ZetaAssistChip]. const ZetaAssistChip({ - super.key, required super.label, + super.key, super.leading, super.rounded, super.draggable = false, super.data, super.onDragCompleted, super.onTap, + super.semanticLabel, }); } diff --git a/lib/src/components/chips/chip.dart b/lib/src/components/chips/chip.dart index 06749934..3d77ba7e 100644 --- a/lib/src/components/chips/chip.dart +++ b/lib/src/components/chips/chip.dart @@ -26,6 +26,7 @@ class ZetaChip extends ZetaStatefulWidget { this.data, this.onDragCompleted, this.onToggle, + this.semanticLabel, }); /// The label on the [ZetaChip] @@ -61,6 +62,13 @@ class ZetaChip extends ZetaStatefulWidget { /// * [Draggable] final VoidCallback? onDragCompleted; + /// The value passed into wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + /// + /// If null, [label] is used. + final String? semanticLabel; + @override State createState() => _ZetaChipState(); @override @@ -74,7 +82,8 @@ class ZetaChip extends ZetaStatefulWidget { ..add(DiagnosticsProperty('data', data)) ..add(ObjectFlagProperty.has('onDragCompleted', onDragCompleted)) ..add(ObjectFlagProperty.has('onTap', onTap)) - ..add(ObjectFlagProperty>.has('onToggle', onToggle)); + ..add(ObjectFlagProperty>.has('onToggle', onToggle)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -105,23 +114,52 @@ class _ZetaChipState extends State { return ZetaRoundedScope( rounded: context.rounded, - child: SelectionContainer.disabled( - child: widget.draggable - ? Draggable( - feedback: Material( - color: Colors.transparent, - child: child(colors, foregroundColor, isDragging: true), - ), - childWhenDragging: const Nothing(), - data: widget.data, - onDragCompleted: widget.onDragCompleted, - child: child(colors, foregroundColor), - ) - : child(colors, foregroundColor), + child: Semantics( + selected: selected, + button: widget.onTap != null, + label: widget.semanticLabel, + child: SelectionContainer.disabled( + child: widget.draggable + ? Draggable( + feedback: Material( + color: Colors.transparent, + child: child(colors, foregroundColor, isDragging: true), + ), + childWhenDragging: const Nothing(), + data: widget.data, + onDragCompleted: widget.onDragCompleted, + child: child(colors, foregroundColor), + ) + : child(colors, foregroundColor), + ), ), ); } + Widget? get trailing { + if (widget.trailing != null) { + if (widget.trailing.runtimeType == IconButton) { + final t = widget.trailing! as IconButton; + return IconButton( + icon: Icon((t.icon as Icon).icon, color: t.color), + onPressed: t.onPressed, + visualDensity: VisualDensity.compact, + ); + } + } + return widget.trailing; + } + + double get _trailingPadding { + if (widget.trailing != null) { + if (widget.trailing.runtimeType == IconButton) { + return ZetaSpacing.none; + } + return ZetaSpacingBase.x2_5; + } + return ZetaSpacing.medium; + } + ValueListenableBuilder> child(ZetaColors colors, Color foregroundColor, {bool isDragging = false}) { return ValueListenableBuilder( valueListenable: _controller, @@ -145,7 +183,7 @@ class _ZetaChipState extends State { padding: EdgeInsets.fromLTRB( widget.leading != null ? ZetaSpacingBase.x2_5 : ZetaSpacing.medium, 0, - widget.trailing != null ? ZetaSpacingBase.x2_5 : ZetaSpacing.medium, + _trailingPadding, 0, ), decoration: BoxDecoration( @@ -205,7 +243,7 @@ class _ZetaChipState extends State { const SizedBox.square(dimension: ZetaSpacing.small), IconTheme( data: IconThemeData(color: foregroundColor, size: ZetaSpacing.xl_1), - child: widget.trailing!, + child: trailing!, ), ], ], diff --git a/lib/src/components/chips/filter_chip.dart b/lib/src/components/chips/filter_chip.dart index 712bbfe3..3fa411e8 100644 --- a/lib/src/components/chips/filter_chip.dart +++ b/lib/src/components/chips/filter_chip.dart @@ -12,13 +12,14 @@ import '../../../zeta_flutter.dart'; class ZetaFilterChip extends ZetaChip { /// Creates a [ZetaFilterChip]. const ZetaFilterChip({ - super.key, required super.label, + super.key, super.rounded, super.selected, super.draggable = false, super.data, super.onDragCompleted, + super.semanticLabel, ValueSetter? onTap, }) : super(onToggle: onTap); diff --git a/lib/src/components/chips/input_chip.dart b/lib/src/components/chips/input_chip.dart index 5fe66318..ffd305a0 100644 --- a/lib/src/components/chips/input_chip.dart +++ b/lib/src/components/chips/input_chip.dart @@ -8,11 +8,12 @@ import '../../../zeta_flutter.dart'; class ZetaInputChip extends ZetaChip { /// Creates a [ZetaInputChip]. const ZetaInputChip({ - super.key, required super.label, + super.key, super.leading, super.rounded, super.trailing, super.onTap, + super.semanticLabel, }); } diff --git a/lib/src/components/contact_item/contact_item.dart b/lib/src/components/contact_item/contact_item.dart index c595e1dd..22039949 100644 --- a/lib/src/components/contact_item/contact_item.dart +++ b/lib/src/components/contact_item/contact_item.dart @@ -6,19 +6,20 @@ import '../../../zeta_flutter.dart'; class ZetaContactItem extends ZetaStatelessWidget { /// Constructs [ZetaContactItem]. const ZetaContactItem({ + super.key, + super.rounded, required this.title, required this.leading, required this.subtitle, this.enabledDivider = true, this.onTap, - super.key, - super.rounded, + this.explicitChildNodes = true, }); /// The main text to be displayed on the top. final Widget title; - /// Normally an Avatar + /// Normally a [ZetaAvatar]. final Widget leading; /// Text to be displayed under [title]. @@ -30,62 +31,68 @@ class ZetaContactItem extends ZetaStatelessWidget { /// Whether to display a divider at the bottom. final bool enabledDivider; + /// Whether to use explicit child nodes for [Semantics]. + final bool explicitChildNodes; + @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; return ZetaRoundedScope( rounded: context.rounded, - child: DecoratedBox( - decoration: BoxDecoration( - color: colors.surfacePrimary, - border: enabledDivider - ? Border( - bottom: BorderSide(color: colors.borderDisabled), - ) - : null, - ), - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.only( - top: ZetaSpacing.small, - bottom: ZetaSpacing.small, - left: ZetaSpacing.xl_2, + child: Semantics( + button: true, + child: SelectionContainer.disabled( + child: Material( + color: colors.surfacePrimary, + child: DecoratedBox( + decoration: BoxDecoration( + border: enabledDivider ? Border(bottom: BorderSide(color: colors.borderDisabled)) : null, ), - child: Row( - children: [ - leading, - Flexible( - child: Padding( - padding: const EdgeInsets.only(left: ZetaSpacing.medium), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - DefaultTextStyle( - style: ZetaTextStyles.bodyMedium.copyWith( - color: colors.textDefault, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - child: title, - ), - DefaultTextStyle( - style: ZetaTextStyles.bodySmall.copyWith( - color: colors.textSubtle, + child: InkWell( + onTap: onTap, + child: Semantics( + explicitChildNodes: explicitChildNodes, + child: Padding( + padding: const EdgeInsets.only( + top: ZetaSpacing.small, + bottom: ZetaSpacing.small, + left: ZetaSpacing.xl_2, + ), + child: Row( + children: [ + leading, + Flexible( + child: Padding( + padding: const EdgeInsets.only(left: ZetaSpacing.medium), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + DefaultTextStyle( + style: ZetaTextStyles.bodyMedium.copyWith( + color: colors.textDefault, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + child: title, + ), + DefaultTextStyle( + style: ZetaTextStyles.bodySmall.copyWith( + color: colors.textSubtle, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + child: subtitle, + ), + ], ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - child: subtitle, ), - ], - ), + ), + ], ), ), - ], + ), ), ), ), @@ -99,6 +106,7 @@ class ZetaContactItem extends ZetaStatelessWidget { super.debugFillProperties(properties); properties ..add(ObjectFlagProperty.has('onTap', onTap)) - ..add(DiagnosticsProperty('enabledDivider', enabledDivider)); + ..add(DiagnosticsProperty('enabledDivider', enabledDivider)) + ..add(DiagnosticsProperty('explicitChildNodes', explicitChildNodes)); } } diff --git a/lib/src/components/date_input/date_input.dart b/lib/src/components/date_input/date_input.dart index 6ef19e1e..5a2b3991 100644 --- a/lib/src/components/date_input/date_input.dart +++ b/lib/src/components/date_input/date_input.dart @@ -29,6 +29,8 @@ class ZetaDateInput extends ZetaFormField { this.minDate, this.maxDate, this.pickerInitialEntryMode, + this.datePickerSemanticLabel, + this.clearSemanticLabel, }) : assert((minDate == null || maxDate == null) || minDate.isBefore(maxDate), 'minDate cannot be after maxDate'); /// The label for the input. @@ -68,6 +70,16 @@ class ZetaDateInput extends ZetaFormField { /// However, if [validator] catches any of these conditions, the return value of [validator] will be shown. final String? Function(DateTime? value)? validator; + /// The semantic label for the clear button. + /// + /// {@macro zeta-widget-semantic-label} + final String? clearSemanticLabel; + + /// The semantic label for the calendar button. + /// + /// {@macro zeta-widget-semantic-label} + final String? datePickerSemanticLabel; + @override State createState() => ZetaDateInputState(); @override @@ -86,7 +98,9 @@ class ZetaDateInput extends ZetaFormField { ..add(StringProperty('dateFormat', dateFormat)) ..add(DiagnosticsProperty('minDate', minDate)) ..add(DiagnosticsProperty('maxDate', maxDate)) - ..add(EnumProperty('pickerInitialEntryMode', pickerInitialEntryMode)); + ..add(EnumProperty('pickerInitialEntryMode', pickerInitialEntryMode)) + ..add(StringProperty('semanticCalendar', datePickerSemanticLabel)) + ..add(StringProperty('semanticClear', clearSemanticLabel)); } } @@ -253,6 +267,7 @@ class ZetaDateInputState extends State implements ZetaFormFieldSt disabled: widget.disabled, size: widget.size, color: _colors.iconSubtle, + semanticLabel: widget.clearSemanticLabel, ), InputIconButton( icon: ZetaIcons.calendar, @@ -260,6 +275,7 @@ class ZetaDateInputState extends State implements ZetaFormFieldSt disabled: widget.disabled, size: widget.size, color: _colors.iconDefault, + semanticLabel: widget.datePickerSemanticLabel, ), ], ), diff --git a/lib/src/components/dial_pad/dial_pad.dart b/lib/src/components/dial_pad/dial_pad.dart index bd85c779..89be568f 100644 --- a/lib/src/components/dial_pad/dial_pad.dart +++ b/lib/src/components/dial_pad/dial_pad.dart @@ -188,6 +188,7 @@ class ZetaDialPadButton extends StatelessWidget { button: true, value: primary, excludeSemantics: true, + label: secondary, child: AnimatedContainer( duration: Durations.short2, width: ZetaSpacing.xl_9, diff --git a/lib/src/components/dropdown/dropdown.dart b/lib/src/components/dropdown/dropdown.dart index 09b655cb..f7311f9d 100644 --- a/lib/src/components/dropdown/dropdown.dart +++ b/lib/src/components/dropdown/dropdown.dart @@ -64,6 +64,8 @@ class ZetaDropdown extends ZetaStatefulWidget { this.builder, this.onDismissed, this.onOpen, + this.semanticDropdownLabel, + this.disableButtonSemantics = false, }); /// {@template dropdown-items} @@ -104,6 +106,16 @@ class ZetaDropdown extends ZetaStatefulWidget { /// Called when the dropdown is opened. final VoidCallback? onOpen; + /// A semantic label for the dropdown. + /// + /// If null, the label will be set to the selected item's label. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticDropdownLabel; + + /// If true, [Semantics] will not include the button variable. + final bool disableButtonSemantics; + /// A custom builder for the child of the dropdown. /// /// Provides a build context, the currently selected item in the dropdown and a controller which can be used to open/close the dropdown. @@ -135,7 +147,9 @@ class ZetaDropdown extends ZetaStatefulWidget { )?>.has('builder', builder), ) ..add(DiagnosticsProperty('offset', offset)) - ..add(ObjectFlagProperty.has('onOpen', onOpen)); + ..add(ObjectFlagProperty.has('onOpen', onOpen)) + ..add(StringProperty('semanticDropdownLabel', semanticDropdownLabel)) + ..add(DiagnosticsProperty('disableButtonSemantics', disableButtonSemantics)); } } @@ -280,6 +294,7 @@ class ZetaDropDownState extends State> { value: _selectedItem ?? widget.items.first, allocateLeadingSpace: widget.type == ZetaDropdownMenuType.standard && _selectedItem?.icon != null, key: _childKey, + explicitChildNodes: false, ); if (widget.size == ZetaDropdownSize.mini) { child = IntrinsicWidth( @@ -290,54 +305,60 @@ class ZetaDropDownState extends State> { return CompositedTransformTarget( link: _link, - child: OverlayPortal( - controller: _dropdownController.overlayPortalController, - overlayChildBuilder: (BuildContext context) { - return CompositedTransformFollower( - link: _link, - targetAnchor: _menuPosition == _MenuPosition.up - ? Alignment.topLeft - : Alignment.bottomLeft, // Align overlay dropdown in its correct position - followerAnchor: _menuPosition == _MenuPosition.up ? Alignment.bottomLeft : Alignment.topLeft, - offset: widget.offset, - child: Align( - alignment: - _menuPosition == _MenuPosition.up ? AlignmentDirectional.bottomStart : AlignmentDirectional.topStart, - child: TapRegion( - onTapOutside: (event) { - final headerBox = _childKey.currentContext!.findRenderObject()! as RenderBox; - - final headerPosition = headerBox.localToGlobal(Offset.zero); - final inHeader = _isInHeader( - headerPosition, - headerBox.size, - event.position, - ); - if (!inHeader) { - _dropdownController.close(); - widget.onDismissed?.call(); - } - }, - child: _ZetaDropDownMenu( - items: widget.items, - selected: _selectedItem?.value, - allocateLeadingSpace: _allocateLeadingSpace, - menuSize: _menuSize, - key: _menuKey, - menuType: widget.type, - onSelected: (item) { - setState(() { - _selectedItem = item; - }); - widget.onChange?.call(item); - _dropdownController.close(); + child: Semantics( + button: !widget.disableButtonSemantics && true, + selected: isOpen, + label: widget.semanticDropdownLabel ?? _selectedItem?.label, + child: OverlayPortal( + controller: _dropdownController.overlayPortalController, + overlayChildBuilder: (BuildContext context) { + return CompositedTransformFollower( + link: _link, + targetAnchor: _menuPosition == _MenuPosition.up + ? Alignment.topLeft + : Alignment.bottomLeft, // Align overlay dropdown in its correct position + followerAnchor: _menuPosition == _MenuPosition.up ? Alignment.bottomLeft : Alignment.topLeft, + offset: widget.offset, + child: Align( + alignment: _menuPosition == _MenuPosition.up + ? AlignmentDirectional.bottomStart + : AlignmentDirectional.topStart, + child: TapRegion( + onTapOutside: (event) { + final headerBox = _childKey.currentContext!.findRenderObject()! as RenderBox; + + final headerPosition = headerBox.localToGlobal(Offset.zero); + final inHeader = _isInHeader( + headerPosition, + headerBox.size, + event.position, + ); + if (!inHeader) { + _dropdownController.close(); + widget.onDismissed?.call(); + } }, + child: _ZetaDropDownMenu( + items: widget.items, + selected: _selectedItem?.value, + allocateLeadingSpace: _allocateLeadingSpace, + menuSize: _menuSize, + key: _menuKey, + menuType: widget.type, + onSelected: (item) { + setState(() { + _selectedItem = item; + }); + widget.onChange?.call(item); + _dropdownController.close(); + }, + ), ), ), - ), - ); - }, - child: child, + ); + }, + child: child, + ), ), ); } @@ -357,35 +378,40 @@ class ZetaDropDownState extends State> { } /// Class for [_DropdownItem] -class _DropdownItem extends StatefulWidget { +class _DropdownItem extends ZetaStatefulWidget { ///Public constructor for [_DropdownItem] const _DropdownItem({ super.key, + super.rounded, required this.value, required this.allocateLeadingSpace, this.selected = false, this.menuType = ZetaDropdownMenuType.standard, this.itemKey, this.onPress, + this.explicitChildNodes = true, }); final bool allocateLeadingSpace; - /// If [_DropdownItem] is selected + /// If [_DropdownItem] is selected. final bool selected; /// Value of [_DropdownItem] final ZetaDropdownItem value; - /// Handles clicking for [_DropdownItem] + /// Handles clicking for [_DropdownItem]. final VoidCallback? onPress; /// If checkbox is to be shown, the type of it. final ZetaDropdownMenuType menuType; - /// Key for item + /// Key for item. final GlobalKey? itemKey; + /// If child nodes are explicitly defined. + final bool explicitChildNodes; + @override State<_DropdownItem> createState() => _DropdownItemState(); @override @@ -402,7 +428,8 @@ class _DropdownItem extends StatefulWidget { ), ) ..add(DiagnosticsProperty('allocateLeadingSpace', allocateLeadingSpace)) - ..add(DiagnosticsProperty>('value', value)); + ..add(DiagnosticsProperty>('value', value)) + ..add(DiagnosticsProperty('explicitChildNodes', explicitChildNodes)); } } @@ -438,29 +465,29 @@ class _DropdownItemState extends State<_DropdownItem> { ); } - return DefaultTextStyle( - style: ZetaTextStyles.bodyMedium, - child: OutlinedButton( - key: widget.itemKey, - onPressed: widget.onPress, - statesController: controller, - style: _getStyle(colors), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: ZetaSpacingBase.x2_5, - horizontal: ZetaSpacing.medium, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (leading != null) leading, - Expanded( - child: Text( - widget.value.label, - ), - ), - ], + return ExcludeSemantics( + excluding: !widget.explicitChildNodes, + child: DefaultTextStyle( + style: ZetaTextStyles.bodyMedium, + child: OutlinedButton( + key: widget.itemKey, + onPressed: widget.onPress, + statesController: controller, + style: _getStyle(colors), + child: Padding( + padding: widget.menuType == ZetaDropdownMenuType.radio + ? const EdgeInsets.only(right: ZetaSpacing.medium) + : const EdgeInsets.symmetric( + vertical: ZetaSpacingBase.x2_5, + horizontal: ZetaSpacing.medium, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (leading != null) leading, + Expanded(child: Text(widget.value.label)), + ], + ), ), ), ), @@ -478,7 +505,7 @@ class _DropdownItemState extends State<_DropdownItem> { }, ); case ZetaDropdownMenuType.radio: - return Radio( + return ZetaRadio( value: widget.selected, groupValue: true, onChanged: (val) { @@ -500,7 +527,7 @@ class _DropdownItemState extends State<_DropdownItem> { return colors.surfaceSelected; } if (states.contains(WidgetState.pressed)) { - return colors.surfaceSelected; + return colors.surfaceSelectedHover; } if (states.contains(WidgetState.hovered)) { return colors.surfaceHover; @@ -527,7 +554,6 @@ class _DropdownItemState extends State<_DropdownItem> { }), padding: const WidgetStatePropertyAll(EdgeInsets.zero), elevation: const WidgetStatePropertyAll(0), - overlayColor: const WidgetStatePropertyAll(Colors.transparent), ); } diff --git a/lib/src/components/fabs/fab.dart b/lib/src/components/fabs/fab.dart index 86b6f417..7b60126d 100644 --- a/lib/src/components/fabs/fab.dart +++ b/lib/src/components/fabs/fab.dart @@ -120,12 +120,12 @@ class _ZetaFABState extends State { if (states.contains(WidgetState.disabled)) { return Zeta.of(context).colors.surfaceDisabled; } - if (states.contains(WidgetState.hovered)) { - return colors.hover; - } if (states.contains(WidgetState.pressed)) { return colors.selected; } + if (states.contains(WidgetState.hovered)) { + return colors.hover; + } return backgroundColor; }), side: WidgetStateProperty.resolveWith( diff --git a/lib/src/components/filter_selection/filter_selection.dart b/lib/src/components/filter_selection/filter_selection.dart index 471e0f09..d6aa3103 100644 --- a/lib/src/components/filter_selection/filter_selection.dart +++ b/lib/src/components/filter_selection/filter_selection.dart @@ -11,6 +11,7 @@ class ZetaFilterSelection extends ZetaStatelessWidget { super.rounded, required this.items, this.onPressed, + this.buttonSemanticLabel, }); /// The filter items - list of [ZetaFilterChip]. @@ -19,33 +20,42 @@ class ZetaFilterSelection extends ZetaStatelessWidget { /// Called on filter button pressed. final VoidCallback? onPressed; + /// Value passed into semantic label for the button. + /// + /// {@macro zeta-widget-semantic-label} + final String? buttonSemanticLabel; + @override Widget build(BuildContext context) { return SizedBox( height: ZetaSpacing.xl_7, child: Row( children: [ - Container( - height: ZetaSpacing.xl_7, - color: Zeta.of(context).colors.surfaceDefault, - child: IconButton( - visualDensity: VisualDensity.compact, - onPressed: onPressed, - icon: const ZetaIcon( - ZetaIcons.filter, - size: ZetaSpacing.xl_2, + Semantics( + button: true, + label: buttonSemanticLabel, + excludeSemantics: true, + enabled: onPressed != null, + child: Container( + height: ZetaSpacing.xl_7, + color: Zeta.of(context).colors.surfaceDefault, + child: IconButton( + visualDensity: VisualDensity.compact, + onPressed: onPressed, + icon: const ZetaIcon( + ZetaIcons.filter, + size: ZetaSpacing.xl_2, + ), ), ), ), Expanded( - child: ListView( + child: ListView.builder( shrinkWrap: true, scrollDirection: Axis.horizontal, padding: const EdgeInsets.all(ZetaSpacing.minimum), - children: items - .map((e) => e.copyWith(rounded: rounded)) - .divide(const SizedBox(width: ZetaSpacing.small)) - .toList(), + itemCount: items.length, + itemBuilder: (context, index) => items[index].paddingHorizontal(ZetaSpacing.minimum), ), ), ], @@ -58,6 +68,7 @@ class ZetaFilterSelection extends ZetaStatelessWidget { super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('rounded', rounded)) - ..add(ObjectFlagProperty.has('onPressed', onPressed)); + ..add(ObjectFlagProperty.has('onPressed', onPressed)) + ..add(StringProperty('buttonSemanticLabel', buttonSemanticLabel)); } } diff --git a/lib/src/components/list_item/dropdown_list_item.dart b/lib/src/components/list_item/dropdown_list_item.dart index 9f1eabb8..c6528539 100644 --- a/lib/src/components/list_item/dropdown_list_item.dart +++ b/lib/src/components/list_item/dropdown_list_item.dart @@ -8,14 +8,15 @@ import 'list_scope.dart'; class ZetaDropdownListItem extends ZetaStatefulWidget { /// Creates a new [ZetaDropdownListItem] const ZetaDropdownListItem({ + super.key, + super.rounded, required this.primaryText, required this.items, this.secondaryText, this.expanded = false, this.leading, this.showDivider, - super.key, - super.rounded, + this.semanticLabel, }); /// The list of [ZetaListItem]s contained within the dropdown. @@ -38,6 +39,11 @@ class ZetaDropdownListItem extends ZetaStatefulWidget { /// {@macro list-item-show-divider} final bool? showDivider; + /// Value passed into semantic label for the button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State createState() => _ZetaDropdownListItemState(); @override @@ -49,7 +55,8 @@ class ZetaDropdownListItem extends ZetaStatefulWidget { ..add(StringProperty('secondaryText', secondaryText)) ..add(DiagnosticsProperty('expanded', expanded)) ..add(DiagnosticsProperty('rounded', rounded)) - ..add(DiagnosticsProperty('showDivider', showDivider)); + ..add(DiagnosticsProperty('showDivider', showDivider)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -110,47 +117,54 @@ class _ZetaDropdownListItemState extends State with Single return ZetaRoundedScope( rounded: context.rounded, - // DecoratedBox does not correctly animated the border when the widget expands. - // ignore: use_decorated_box - child: Container( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: divide ? colors.borderDefault : Colors.transparent, + child: Semantics( + button: true, + selected: _expanded, + label: widget.semanticLabel ?? (widget.primaryText + (widget.secondaryText ?? '')), + // DecoratedBox does not correctly animated the border when the widget expands. + // ignore: use_decorated_box + child: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: divide ? colors.borderDefault : Colors.transparent, + ), ), ), - ), - child: Column( - children: [ - ZetaListItem( - primaryText: widget.primaryText, - secondaryText: widget.secondaryText, - leading: widget.leading, - onTap: _onTap, - showDivider: false, - trailing: IconButton( - icon: AnimatedRotation( - turns: _expanded ? 0.5 : 0, - duration: ZetaAnimationLength.fast, - child: ZetaIcon( - ZetaIcons.expand_more, - color: colors.iconSubtle, + child: Column( + children: [ + ExcludeSemantics( + child: ZetaListItem( + primaryText: widget.primaryText, + secondaryText: widget.secondaryText, + leading: widget.leading, + onTap: _onTap, + showDivider: false, + trailing: IconButton( + icon: AnimatedRotation( + turns: _expanded ? 0.5 : 0, + duration: ZetaAnimationLength.fast, + child: ZetaIcon( + ZetaIcons.expand_more, + color: colors.iconSubtle, + ), + ), + onPressed: _onTap, ), ), - onPressed: _onTap, ), - ), - ListScope( - showDivider: false, - indentItems: true, - child: SizeTransition( - sizeFactor: _animation, - child: Column( - children: widget.items, + ListScope( + showDivider: false, + indentItems: true, + child: SizeTransition( + sizeFactor: _animation, + child: Column( + children: widget.items, + ), ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/src/components/list_item/list_item.dart b/lib/src/components/list_item/list_item.dart index ffb140a6..447d1b0d 100644 --- a/lib/src/components/list_item/list_item.dart +++ b/lib/src/components/list_item/list_item.dart @@ -32,6 +32,7 @@ class ZetaList extends ZetaStatelessWidget { child: ListView.builder( itemBuilder: (context, i) => items[i], itemCount: items.length, + addSemanticIndexes: false, ), ), ); @@ -163,67 +164,72 @@ class ZetaListItem extends ZetaStatelessWidget { final Widget? leadingWidget = leading ?? ((listScope?.indentItems ?? false) ? const SizedBox(width: ZetaSpacing.xl_2) : null); - return Material( - color: Zeta.of(context).colors.surfaceDefault, - child: InkWell( - onTap: onTap, - child: Container( - constraints: const BoxConstraints(minHeight: ZetaSpacing.xl_9), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: divide ? colors.borderDefault : Colors.transparent, + return SelectionContainer.disabled( + child: MergeSemantics( + child: Material( + color: Zeta.of(context).colors.surfaceDefault, + child: InkWell( + onTap: onTap, + excludeFromSemantics: true, + child: Container( + constraints: const BoxConstraints(minHeight: ZetaSpacing.xl_9), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: divide ? colors.borderDefault : Colors.transparent, + ), + ), ), - ), - ), - child: Padding( - padding: const EdgeInsets.only( - left: ZetaSpacing.large, - right: ZetaSpacing.small, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: Row( - children: [ - if (leadingWidget != null) - Padding( - padding: const EdgeInsets.only( - right: ZetaSpacing.small, - ), - child: leadingWidget, - ), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - primaryText, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - if (secondaryText != null && secondaryText!.isNotEmpty) - Text( - secondaryText!, - style: ZetaTextStyles.bodySmall, - maxLines: 1, - overflow: TextOverflow.ellipsis, + child: Padding( + padding: const EdgeInsets.only( + left: ZetaSpacing.large, + right: ZetaSpacing.small, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + children: [ + if (leadingWidget != null) + Padding( + padding: const EdgeInsets.only( + right: ZetaSpacing.small, ), - ], + child: leadingWidget, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + primaryText, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + if (secondaryText != null && secondaryText!.isNotEmpty) + Text( + secondaryText!, + style: ZetaTextStyles.bodySmall, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ), + ), + if (trailing != null) + Padding( + padding: const EdgeInsets.only( + left: ZetaSpacing.large, ), + child: trailing, ), - ], - ), + ], ), - if (trailing != null) - Padding( - padding: const EdgeInsets.only( - left: ZetaSpacing.large, - ), - child: trailing, - ), - ], + ), ), ), ), diff --git a/lib/src/components/list_item/notification_list_item.dart b/lib/src/components/list_item/notification_list_item.dart index 842733ee..cb279a8d 100644 --- a/lib/src/components/list_item/notification_list_item.dart +++ b/lib/src/components/list_item/notification_list_item.dart @@ -16,6 +16,7 @@ class ZetaNotificationListItem extends ZetaStatefulWidget { this.notificationTime, required this.action, this.showDivider = false, + this.semanticLabel, }); /// Notification Badge to indicate type of notification or who it's coming from @@ -39,30 +40,14 @@ class ZetaNotificationListItem extends ZetaStatefulWidget { /// Pass in a action widget to handle action functionality. final Widget action; + /// Semantic label for the notification list item. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State createState() => _ZetaNotificationListItemState(); - /// Function that returns copy of a notification item with altered fields - ZetaNotificationListItem copyWith({ - ZetaNotificationBadge? leading, - Widget? body, - String? title, - String? notificationTime, - String? linkText, - VoidCallback? linkOnClick, - Widget? action, - bool? showDivider, - }) { - return ZetaNotificationListItem( - leading: leading ?? this.leading, - body: body ?? this.body, - title: title ?? this.title, - notificationTime: notificationTime ?? this.notificationTime, - action: action ?? this.action, - showDivider: showDivider ?? this.showDivider, - ); - } - @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); @@ -70,7 +55,8 @@ class ZetaNotificationListItem extends ZetaStatefulWidget { ..add(StringProperty('notificationTime', notificationTime)) ..add(StringProperty('title', title)) ..add(DiagnosticsProperty('notificationRead', notificationRead)) - ..add(DiagnosticsProperty('showDivider', showDivider)); + ..add(DiagnosticsProperty('showDivider', showDivider)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -80,66 +66,74 @@ class _ZetaNotificationListItemState extends State { final colors = Zeta.of(context).colors; return ZetaRoundedScope( rounded: context.rounded, - child: DecoratedBox( - decoration: _getStyle(colors), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - widget.leading, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - if (!widget.notificationRead) - ZetaIndicator( - color: colors.blue, - size: ZetaWidgetSize.small, - ), - Text( - widget.title, - style: ZetaTextStyles.labelLarge, + child: Semantics( + explicitChildNodes: true, + label: widget.semanticLabel, + button: true, + child: DecoratedBox( + decoration: _getStyle(colors), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + widget.leading, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + MergeSemantics( + child: Row( + children: [ + if (!widget.notificationRead) + ZetaIndicator( + color: colors.blue, + size: ZetaWidgetSize.small, + ), + Text( + widget.title, + style: ZetaTextStyles.labelLarge, + ), + ], ), - ], - ), - Row( - children: [ - if (widget.notificationTime != null) - Text( - widget.notificationTime!, - style: ZetaTextStyles.bodySmall.apply(color: colors.textDisabled), - ), - Container( - padding: const EdgeInsets.all(2), - decoration: BoxDecoration(color: colors.surfaceNegative, borderRadius: ZetaRadius.full), - child: ZetaIcon( - ZetaIcons.important_notification, - color: colors.white, - size: ZetaSpacing.medium, + ), + Row( + children: [ + if (widget.notificationTime != null) + Text( + widget.notificationTime!, + style: ZetaTextStyles.bodySmall.apply(color: colors.textDisabled), + ), + Container( + padding: const EdgeInsets.all(2), + decoration: + BoxDecoration(color: colors.surfaceNegative, borderRadius: ZetaRadius.full), + child: ZetaIcon( + ZetaIcons.important_notification, + color: colors.white, + size: ZetaSpacing.medium, + ), ), - ), - ].gap(ZetaSpacing.minimum), - ), - ], - ), - widget.body, - ].gap(ZetaSpacing.minimum), + ].gap(ZetaSpacing.minimum), + ), + ], + ), + widget.body, + ].gap(ZetaSpacing.minimum), + ), ), - ), - ].gap(ZetaSpacing.small), - ), - Container(alignment: Alignment.centerRight, child: widget.action), - ], - ).paddingAll(ZetaSpacing.small), + ].gap(ZetaSpacing.small), + ), + Container(alignment: Alignment.centerRight, child: widget.action), + ], + ).paddingAll(ZetaSpacing.small), + ), ), ); } diff --git a/lib/src/components/navigation bar/navigation_bar.dart b/lib/src/components/navigation bar/navigation_bar.dart index 5365949c..2b45e7e2 100644 --- a/lib/src/components/navigation bar/navigation_bar.dart +++ b/lib/src/components/navigation bar/navigation_bar.dart @@ -28,14 +28,15 @@ class ZetaNavigationBarItem { class ZetaNavigationBar extends ZetaStatelessWidget { /// Creates a new [ZetaNavigationBar]. const ZetaNavigationBar({ + super.key, + super.rounded, required this.items, this.currentIndex, this.onTap, this.splitItems = false, this.dividerIndex, this.action, - super.key, - super.rounded, + this.semanticLabel, }) : assert( items.length >= 2 && items.length <= 6, 'The number of items should be between 2 and 6', @@ -43,52 +44,40 @@ class ZetaNavigationBar extends ZetaStatelessWidget { /// Creates a [ZetaNavigationBar] with a divider after the item at the given index. const ZetaNavigationBar.divided({ - required List items, - required int? dividerIndex, - int? currentIndex, - void Function(int value)? onTap, - Key? key, - bool? rounded, - }) : this( - items: items, - currentIndex: currentIndex, - onTap: onTap, - splitItems: false, - dividerIndex: dividerIndex, - key: key, - rounded: rounded, - ); + super.rounded, + super.key, + required this.items, + this.currentIndex, + this.onTap, + this.dividerIndex, + this.semanticLabel, + }) : splitItems = false, + action = null; /// Creates a [ZetaNavigationBar] and splits the items in half. + const ZetaNavigationBar.split({ - required List items, - int? currentIndex, - void Function(int value)? onTap, - Key? key, - bool? rounded, - }) : this( - items: items, - currentIndex: currentIndex, - onTap: onTap, - splitItems: true, - key: key, - rounded: rounded, - ); + super.rounded, + super.key, + required this.items, + this.currentIndex, + this.onTap, + this.dividerIndex, + this.semanticLabel, + }) : splitItems = true, + action = null; /// Creates a [ZetaNavigationBar] with an action. const ZetaNavigationBar.action({ - required List items, - required Widget action, - int? currentIndex, - void Function(int value)? onTap, - Key? key, - }) : this( - items: items, - currentIndex: currentIndex, - onTap: onTap, - action: action, - key: key, - ); + super.key, + super.rounded, + required this.items, + required this.action, + this.currentIndex, + this.onTap, + this.semanticLabel, + }) : dividerIndex = null, + splitItems = false; /// The items displayed on the navigation bar. final List items; @@ -108,6 +97,11 @@ class ZetaNavigationBar extends ZetaStatelessWidget { /// The action shown on the navigation bar. final Widget? action; + /// Value passed to the [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + Row _generateNavigationItemRow(List items) { return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, @@ -166,15 +160,14 @@ class ZetaNavigationBar extends ZetaStatelessWidget { } return Container( - padding: const EdgeInsets.only( - left: ZetaSpacing.medium, - right: ZetaSpacing.medium, - ), + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.medium), decoration: BoxDecoration( color: colors.surfacePrimary, border: Border(top: BorderSide(color: colors.borderSubtle)), ), - child: child, + child: Semantics( + child: child, + ), ); } @@ -186,11 +179,12 @@ class ZetaNavigationBar extends ZetaStatelessWidget { ..add(IntProperty('currentIndex', currentIndex)) ..add(ObjectFlagProperty.has('onTap', onTap)) ..add(DiagnosticsProperty('splitItems', splitItems)) - ..add(IntProperty('dividerIndex', dividerIndex)); + ..add(IntProperty('dividerIndex', dividerIndex)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } -class _NavigationItem extends StatelessWidget { +class _NavigationItem extends ZetaStatelessWidget { const _NavigationItem({ required this.selected, required this.item, @@ -229,35 +223,43 @@ class _NavigationItem extends StatelessWidget { return Material( color: colors.surfacePrimary, child: InkWell( - borderRadius: ZetaRadius.rounded, + borderRadius: context.rounded ? ZetaRadius.rounded : ZetaRadius.none, onTap: onTap, - child: Container( - padding: const EdgeInsets.only(left: ZetaSpacing.small, right: ZetaSpacing.small, bottom: ZetaSpacing.small), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: ZetaSpacing.xl_7, - height: ZetaSpacing.xl_4 - _navigationItemBorderWidth, - child: Stack( - children: [ - Positioned( - left: ZetaSpacingBase.x2_5, - top: ZetaSpacing.small - _navigationItemBorderWidth, - right: ZetaSpacingBase.x2_5, - child: ZetaIcon(item.icon, color: elementColor, size: ZetaSpacing.xl_2), - ), - if (item.badge != null) _getBadge(colors), - ], - ), - ), - const SizedBox(height: ZetaSpacing.small), - if (item.label != null) - Text( - item.label!, - style: Theme.of(context).textTheme.labelSmall?.copyWith(color: elementColor), + child: Semantics( + button: true, + explicitChildNodes: true, + label: item.label, + child: Container( + padding: + const EdgeInsets.only(left: ZetaSpacing.small, right: ZetaSpacing.small, bottom: ZetaSpacing.small), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: ZetaSpacing.xl_7, + height: ZetaSpacing.xl_4 - _navigationItemBorderWidth, + child: Stack( + children: [ + Positioned( + left: ZetaSpacingBase.x2_5, + top: ZetaSpacing.small - _navigationItemBorderWidth, + right: ZetaSpacingBase.x2_5, + child: ZetaIcon(item.icon, color: elementColor, size: ZetaSpacing.xl_2), + ), + if (item.badge != null) _getBadge(colors), + ], + ), ), - ], + const SizedBox(height: ZetaSpacing.small), + if (item.label != null) + ExcludeSemantics( + child: Text( + item.label!, + style: Theme.of(context).textTheme.labelSmall?.copyWith(color: elementColor), + ), + ), + ], + ), ), ), ), diff --git a/lib/src/components/navigation_rail/navigation_rail.dart b/lib/src/components/navigation_rail/navigation_rail.dart index 81bf6d6c..729fc32e 100644 --- a/lib/src/components/navigation_rail/navigation_rail.dart +++ b/lib/src/components/navigation_rail/navigation_rail.dart @@ -16,6 +16,7 @@ class ZetaNavigationRail extends ZetaStatefulWidget { this.itemSpacing = const EdgeInsets.only(bottom: ZetaSpacing.minimum), this.itemPadding, this.wordWrap, + this.semanticLabel, }); /// Required list of navigation items. @@ -55,6 +56,11 @@ class ZetaNavigationRail extends ZetaStatefulWidget { /// Default is `true`. final bool? wordWrap; + /// Value passed to the wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State createState() => _ZetaNavigationRailState(); @override @@ -68,7 +74,8 @@ class ZetaNavigationRail extends ZetaStatefulWidget { ..add(DiagnosticsProperty('margin', margin)) ..add(DiagnosticsProperty('itemSpacing', itemSpacing)) ..add(DiagnosticsProperty('itemPadding', itemPadding)) - ..add(DiagnosticsProperty('wordWrap', wordWrap)); + ..add(DiagnosticsProperty('wordWrap', wordWrap)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -77,31 +84,34 @@ class _ZetaNavigationRailState extends State { Widget build(BuildContext context) { return ZetaRoundedScope( rounded: context.rounded, - child: Padding( - padding: widget.margin, - child: IntrinsicWidth( - child: Column( - children: [ - for (int i = 0; i < widget.items.length; i++) - Row( - children: [ - Expanded( - child: Padding( - padding: widget.itemSpacing, - child: _ZetaNavigationRailItemContent( - label: widget.items[i].label, - icon: widget.items[i].icon, - selected: widget.selectedIndex == i, - disabled: widget.items[i].disabled, - onTap: () => widget.onSelect?.call(i), - padding: widget.itemPadding, - wordWrap: widget.wordWrap, + child: Semantics( + label: widget.semanticLabel, + child: Padding( + padding: widget.margin, + child: IntrinsicWidth( + child: Column( + children: [ + for (int i = 0; i < widget.items.length; i++) + Row( + children: [ + Expanded( + child: Padding( + padding: widget.itemSpacing, + child: _ZetaNavigationRailItemContent( + label: widget.items[i].label, + icon: widget.items[i].icon, + selected: widget.selectedIndex == i, + disabled: widget.items[i].disabled, + onTap: () => widget.onSelect?.call(i), + padding: widget.itemPadding, + wordWrap: widget.wordWrap, + ), ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), @@ -109,7 +119,7 @@ class _ZetaNavigationRailState extends State { } } -class _ZetaNavigationRailItemContent extends StatelessWidget { +class _ZetaNavigationRailItemContent extends ZetaStatelessWidget { const _ZetaNavigationRailItemContent({ required this.label, this.icon, @@ -131,59 +141,63 @@ class _ZetaNavigationRailItemContent extends StatelessWidget { @override Widget build(BuildContext context) { final zeta = Zeta.of(context); - return MouseRegion( - cursor: disabled ? SystemMouseCursors.forbidden : SystemMouseCursors.click, - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: disabled ? null : onTap, - child: DecoratedBox( - decoration: BoxDecoration( - color: disabled - ? null - : selected - ? zeta.colors.blue.shade10 - : null, - borderRadius: context.rounded ? ZetaRadius.rounded : null, - ), - child: ConstrainedBox( - constraints: const BoxConstraints( - minWidth: ZetaSpacing.xl_9, - minHeight: ZetaSpacing.xl_9, + return Semantics( + button: true, + enabled: !disabled, + child: MouseRegion( + cursor: disabled ? SystemMouseCursors.forbidden : SystemMouseCursors.click, + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: disabled ? null : onTap, + child: DecoratedBox( + decoration: BoxDecoration( + color: disabled + ? null + : selected + ? zeta.colors.blue.shade10 + : null, + borderRadius: context.rounded ? ZetaRadius.rounded : null, ), - child: SelectionContainer.disabled( - child: Padding( - padding: padding ?? - const EdgeInsets.symmetric( - horizontal: ZetaSpacing.small, - vertical: ZetaSpacing.medium, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (icon != null) - IconTheme( - data: IconThemeData( + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: ZetaSpacing.xl_9, + minHeight: ZetaSpacing.xl_9, + ), + child: SelectionContainer.disabled( + child: Padding( + padding: padding ?? + const EdgeInsets.symmetric( + horizontal: ZetaSpacing.small, + vertical: ZetaSpacing.medium, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (icon != null) + IconTheme( + data: IconThemeData( + color: disabled + ? zeta.colors.cool.shade50 + : selected + ? zeta.colors.textDefault + : zeta.colors.cool.shade70, + size: ZetaSpacing.xl_2, + ), + child: icon!, + ), + Text( + (wordWrap ?? true) ? label.replaceAll(' ', '\n') : label, + textAlign: TextAlign.center, + style: ZetaTextStyles.titleSmall.copyWith( color: disabled ? zeta.colors.cool.shade50 : selected ? zeta.colors.textDefault : zeta.colors.cool.shade70, - size: ZetaSpacing.xl_2, ), - child: icon!, - ), - Text( - (wordWrap ?? true) ? label.replaceAll(' ', '\n') : label, - textAlign: TextAlign.center, - style: ZetaTextStyles.titleSmall.copyWith( - color: disabled - ? zeta.colors.cool.shade50 - : selected - ? zeta.colors.textDefault - : zeta.colors.cool.shade70, ), - ), - ], + ], + ), ), ), ), diff --git a/lib/src/components/pagination/pagination.dart b/lib/src/components/pagination/pagination.dart index d716d541..c9dc406b 100644 --- a/lib/src/components/pagination/pagination.dart +++ b/lib/src/components/pagination/pagination.dart @@ -21,13 +21,18 @@ enum ZetaPaginationType { class ZetaPagination extends ZetaStatefulWidget { /// Creates a new [ZetaPagination] const ZetaPagination({ + super.rounded, + super.key, required this.pages, this.type = ZetaPaginationType.standard, this.onChange, this.currentPage = 1, @Deprecated('Set onChange to null. ' 'Disabled is deprecated as of 0.11.0') bool disabled = false, - super.rounded, - super.key, + this.semanticFirst, + this.semanticPrevious, + this.semanticNext, + this.semanticLast, + this.semanticDropdown, }) : assert( pages > 0, 'Pages must be greater than zero', @@ -56,6 +61,31 @@ class ZetaPagination extends ZetaStatefulWidget { /// Default to [ZetaPaginationType.standard] final ZetaPaginationType type; + /// Semantic value passed to the first button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticFirst; + + /// Semantic value passed to the previous button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticPrevious; + + /// Semantic value passed to the next button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticNext; + + /// Semantic value passed to the last button. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLast; + + /// Semantic value passed to the dropdown. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticDropdown; + @override State createState() => _ZetaPaginationState(); @override @@ -66,7 +96,12 @@ class ZetaPagination extends ZetaStatefulWidget { ..add(IntProperty('currentPage', currentPage)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(ObjectFlagProperty.has('onChange', onChange)) - ..add(EnumProperty('type', type)); + ..add(EnumProperty('type', type)) + ..add(StringProperty('semanticLast', semanticLast)) + ..add(StringProperty('semanticFirst', semanticFirst)) + ..add(StringProperty('semanticPrevious', semanticPrevious)) + ..add(StringProperty('semanticNext', semanticNext)) + ..add(StringProperty('semanticDropdown', semanticDropdown)); } } @@ -180,24 +215,28 @@ class _ZetaPaginationState extends State { child: Text((i + 1).toString()), ), ); - return Container( - height: ZetaSpacing.xl_6, - decoration: BoxDecoration( - border: Border.all(color: colors.borderSubtle), - borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, - ), - // TODO(mikecoomber): Replace with Zeta Dropdown - child: DropdownButton( - items: items, - onChanged: (val) => _onItemPressed(val!), - value: _currentPage, - icon: const ZetaIcon(ZetaIcons.expand_more).paddingStart(ZetaSpacing.small), - underline: const Nothing(), - style: Theme.of(context).textTheme.bodyLarge?.copyWith( - color: colors.textSubtle, - ), - padding: const EdgeInsets.symmetric( - horizontal: ZetaSpacing.medium, + return Semantics( + label: widget.semanticDropdown, + child: Container( + height: ZetaSpacing.xl_6, + + decoration: BoxDecoration( + border: Border.all(color: colors.borderSubtle), + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + ), + // TODO(mikecoomber): Replace with Zeta Dropdown + child: DropdownButton( + items: items, + onChanged: (val) => _onItemPressed(val!), + value: _currentPage, + icon: const ZetaIcon(ZetaIcons.expand_more).paddingStart(ZetaSpacing.small), + underline: const Nothing(), + style: Theme.of(context).textTheme.bodyLarge?.copyWith( + color: colors.textSubtle, + ), + padding: const EdgeInsets.symmetric( + horizontal: ZetaSpacing.medium, + ), ), ), ); @@ -217,28 +256,28 @@ class _ZetaPaginationState extends State { _PaginationItem( icon: ZetaIcons.first_page, onPressed: () => _onItemPressed(1), - disabled: _disabled, + disabled: _disabled || _currentPage == 1, + semanticLabel: widget.semanticFirst, ), _PaginationItem( icon: ZetaIcons.chevron_left, onPressed: () => _onItemPressed(max(1, _currentPage - 1)), - disabled: _disabled, + disabled: _disabled || _currentPage == 1, + semanticLabel: widget.semanticPrevious, ), if (!showDropdown) ...numberedPaginationItems else paginationDropdown, _PaginationItem( icon: ZetaIcons.chevron_right, - onPressed: () => _onItemPressed( - min(widget.pages, _currentPage + 1), - ), - disabled: _disabled, + onPressed: () => _onItemPressed(min(widget.pages, _currentPage + 1)), + disabled: _disabled || _currentPage == widget.pages, + semanticLabel: widget.semanticNext, ), if (!showDropdown) _PaginationItem( icon: ZetaIcons.last_page, - onPressed: () => _onItemPressed( - widget.pages, - ), - disabled: _disabled, + onPressed: () => _onItemPressed(widget.pages), + disabled: _disabled || _currentPage == widget.pages, + semanticLabel: widget.semanticLast, ), ]; @@ -253,13 +292,14 @@ class _ZetaPaginationState extends State { } } -class _PaginationItem extends StatelessWidget { +class _PaginationItem extends ZetaStatelessWidget { const _PaginationItem({ required this.onPressed, required this.disabled, this.selected = false, this.value, this.icon, + this.semanticLabel, }); final VoidCallback onPressed; @@ -267,6 +307,7 @@ class _PaginationItem extends StatelessWidget { final IconData? icon; final bool disabled; final bool selected; + final String? semanticLabel; @override Widget build(BuildContext context) { @@ -291,35 +332,40 @@ class _PaginationItem extends StatelessWidget { child = ZetaIcon( icon, color: disabled ? colors.iconDisabled : colors.iconDefault, + semanticLabel: semanticLabel, ); } - return ConstrainedBox( - constraints: const BoxConstraints( - minHeight: _itemHeight, - maxHeight: _itemHeight, - minWidth: _itemWidth, - ), - child: Material( - borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, - color: disabled - ? colors.surfaceDisabled - : selected - ? colors.cool[100] - : colors.surfacePrimary, - child: InkWell( - onTap: disabled ? null : onPressed, + return Semantics( + button: true, + enabled: !disabled, + child: ConstrainedBox( + constraints: const BoxConstraints( + minHeight: _itemHeight, + maxHeight: _itemHeight, + minWidth: _itemWidth, + ), + child: Material( borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, - highlightColor: selected ? colors.cool[100] : colors.surfaceSelected, - hoverColor: selected ? colors.cool[100] : colors.surfaceHover, - enableFeedback: false, - child: Container( - alignment: Alignment.center, - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.minimum), - decoration: BoxDecoration( - borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + color: disabled + ? colors.surfaceDisabled + : selected + ? colors.cool[100] + : colors.surfacePrimary, + child: InkWell( + onTap: disabled ? null : onPressed, + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + highlightColor: selected ? colors.cool[100] : colors.surfaceSelected, + hoverColor: selected ? colors.cool[100] : colors.surfaceHover, + enableFeedback: false, + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.minimum), + decoration: BoxDecoration( + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + ), + child: child, ), - child: child, ), ), ), @@ -334,7 +380,8 @@ class _PaginationItem extends StatelessWidget { ..add(IntProperty('value', value)) ..add(DiagnosticsProperty('icon', icon)) ..add(DiagnosticsProperty('disabled', disabled)) - ..add(DiagnosticsProperty('selected', selected)); + ..add(DiagnosticsProperty('selected', selected)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } diff --git a/lib/src/components/password/password_input.dart b/lib/src/components/password/password_input.dart index 97e6eb6c..4d1860d5 100644 --- a/lib/src/components/password/password_input.dart +++ b/lib/src/components/password/password_input.dart @@ -8,22 +8,25 @@ import '../../interfaces/form_field.dart'; class ZetaPasswordInput extends ZetaFormField { ///Constructs [ZetaPasswordInput] const ZetaPasswordInput({ + super.key, + super.rounded, + super.initialValue, + super.requirementLevel = ZetaFormFieldRequirement.none, + super.onChange, + super.disabled = false, this.size = ZetaWidgetSize.large, this.validator, - super.onChange, this.onSubmit, this.obscureText = true, @Deprecated('Use disabled instead. ' 'This property has been renamed as of 0.11.2') bool enabled = true, - super.disabled = false, this.controller, this.hintText, this.errorText, this.label, this.placeholder, - super.rounded, - super.key, - super.initialValue, - super.requirementLevel = ZetaFormFieldRequirement.none, + this.semanticLabel, + this.obscureSemanticLabel, + this.showSemanticLabel, }); /// {@macro text-input-controller} @@ -53,6 +56,21 @@ class ZetaPasswordInput extends ZetaFormField { /// {@macro text-input-on-submit} final void Function(String? val)? onSubmit; + /// Value passed to the wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + + /// Semantic value on button to obscure text. + /// + /// {@macro zeta-widget-semantic-label} + final String? obscureSemanticLabel; + + /// Semantic value on button to show text. + /// + /// {@macro zeta-widget-semantic-label} + final String? showSemanticLabel; + @override State createState() => _ZetaPasswordInputState(); @@ -60,9 +78,7 @@ class ZetaPasswordInput extends ZetaFormField { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add( - DiagnosticsProperty('controller', controller), - ) + ..add(DiagnosticsProperty('controller', controller)) ..add(DiagnosticsProperty('obscureText', obscureText)) ..add(StringProperty('hintText', hintText)) ..add(StringProperty('label', label)) @@ -71,7 +87,10 @@ class ZetaPasswordInput extends ZetaFormField { ..add(EnumProperty('size', size)) ..add(StringProperty('placeholder', placeholder)) ..add(ObjectFlagProperty.has('onSubmit', onSubmit)) - ..add(StringProperty('errorText', errorText)); + ..add(StringProperty('errorText', errorText)) + ..add(StringProperty('semanticLabel', semanticLabel)) + ..add(StringProperty('showSemanticLabel', showSemanticLabel)) + ..add(StringProperty('obscureSemanticLabel', obscureSemanticLabel)); } } @@ -101,13 +120,19 @@ class _ZetaPasswordInputState extends State { onSubmit: widget.onSubmit, disabled: widget.disabled, obscureText: _obscureText, - suffix: IconButton( - icon: ZetaIcon(_obscureText ? ZetaIcons.visibility_off : ZetaIcons.visibility), - onPressed: () { - setState(() { - _obscureText = !_obscureText; - }); - }, + semanticLabel: widget.semanticLabel, + suffix: MergeSemantics( + child: Semantics( + label: _obscureText ? widget.showSemanticLabel : widget.obscureSemanticLabel, + child: IconButton( + icon: ZetaIcon(_obscureText ? ZetaIcons.visibility_off : ZetaIcons.visibility), + onPressed: () { + setState(() { + _obscureText = !_obscureText; + }); + }, + ), + ), ), ); } diff --git a/lib/src/components/phone_input/countries_dialog.dart b/lib/src/components/phone_input/countries_dialog.dart index 61d553b4..173aaaa7 100644 --- a/lib/src/components/phone_input/countries_dialog.dart +++ b/lib/src/components/phone_input/countries_dialog.dart @@ -171,7 +171,7 @@ class _CountriesListState extends State<_CountriesList> { padding: const EdgeInsets.only(top: ZetaSpacing.large), child: TextButton( onPressed: () => Navigator.of(context).pop(), - child: const Text('Close'), + child: const Text('Close'), // TODO(UX-1003): Needs localization ), ), ], @@ -183,15 +183,18 @@ class _CountriesListState extends State<_CountriesList> { Widget _listView(BuildContext context) => ListView.builder( shrinkWrap: true, itemCount: _items.length, - itemBuilder: (_, index) => InkWell( - onTap: () { - Navigator.of(context).pop(_items[index].value); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: ZetaSpacing.small, + itemBuilder: (_, index) => Semantics( + button: true, + child: InkWell( + onTap: () { + Navigator.of(context).pop(_items[index].value); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: ZetaSpacing.small, + ), + child: _items[index].child, ), - child: _items[index].child, ), ), ); diff --git a/lib/src/components/phone_input/phone_input.dart b/lib/src/components/phone_input/phone_input.dart index ff8362f9..67f18af7 100644 --- a/lib/src/components/phone_input/phone_input.dart +++ b/lib/src/components/phone_input/phone_input.dart @@ -23,6 +23,7 @@ class ZetaPhoneInput extends ZetaStatefulWidget { this.countries, this.countrySearchHint, this.useRootNavigator = true, + this.selectCountrySemanticLabel, }); /// If provided, displays a label above the input field. @@ -62,6 +63,11 @@ class ZetaPhoneInput extends ZetaStatefulWidget { /// Determines if the root navigator should be used in the [CountriesDialog]. final bool useRootNavigator; + /// The semantic label for the country selection button. + /// + /// {@macro zeta-widget-semantic-label} + final String? selectCountrySemanticLabel; + @override State createState() => _ZetaPhoneInputState(); @override @@ -79,7 +85,8 @@ class ZetaPhoneInput extends ZetaStatefulWidget { ..add(StringProperty('phoneNumber', phoneNumber)) ..add(IterableProperty('countries', countries)) ..add(DiagnosticsProperty('useRootNavigator', useRootNavigator)) - ..add(StringProperty('countrySearchHint', countrySearchHint)); + ..add(StringProperty('countrySearchHint', countrySearchHint)) + ..add(StringProperty('selectCountrySemanticLabel', selectCountrySemanticLabel)); } } @@ -143,175 +150,185 @@ class _ZetaPhoneInputState extends State { : zeta.colors.cool.shade70 : zeta.colors.cool.shade50; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.label != null) - Padding( - padding: const EdgeInsets.only(bottom: 5), - child: Text( - widget.label!, - style: ZetaTextStyles.bodyMedium.copyWith( - color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + return Semantics( + enabled: widget.enabled, + excludeSemantics: !widget.enabled, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.label != null) + Padding( + padding: const EdgeInsets.only(bottom: 5), + child: Text( + widget.label!, + style: ZetaTextStyles.bodyMedium.copyWith( + color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + ), ), ), - ), - SizedBox( - width: double.infinity, - child: Row( - children: [ - SizedBox( - width: ZetaSpacing.xl_9, - height: ZetaSpacing.xl_8, - child: DecoratedBox( - decoration: BoxDecoration( - color: widget.enabled ? zeta.colors.surfacePrimary : zeta.colors.cool.shade30, - borderRadius: rounded - ? const BorderRadius.only( - topLeft: Radius.circular(ZetaSpacing.minimum), - bottomLeft: Radius.circular(ZetaSpacing.minimum), - ) - : ZetaRadius.none, - border: Border( - top: BorderSide(color: zeta.colors.cool.shade40), - bottom: BorderSide(color: zeta.colors.cool.shade40), - left: BorderSide(color: zeta.colors.cool.shade40), - ), - ), - child: CountriesDialog( - zeta: zeta, - useRootNavigator: widget.useRootNavigator, - enabled: widget.enabled, - searchHint: widget.countrySearchHint, - button: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only( - left: ZetaSpacingBase.x2_5, - ), - child: Image.asset( - _selectedCountry.flagUri, - package: 'zeta_flutter', - width: 26, - height: 18, - fit: BoxFit.fitHeight, - ), + SizedBox( + width: double.infinity, + child: Row( + children: [ + Semantics( + button: true, + excludeSemantics: true, + enabled: widget.enabled, + label: widget.selectCountrySemanticLabel, + child: SizedBox( + width: ZetaSpacing.xl_9, + height: ZetaSpacing.xl_8, + child: DecoratedBox( + decoration: BoxDecoration( + color: widget.enabled ? zeta.colors.surfacePrimary : zeta.colors.cool.shade30, + borderRadius: rounded + ? const BorderRadius.only( + topLeft: Radius.circular(ZetaSpacing.minimum), + bottomLeft: Radius.circular(ZetaSpacing.minimum), + ) + : ZetaRadius.none, + border: Border( + top: BorderSide(color: zeta.colors.cool.shade40), + bottom: BorderSide(color: zeta.colors.cool.shade40), + left: BorderSide(color: zeta.colors.cool.shade40), ), - ZetaIcon( - ZetaIcons.expand_more, - color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, - size: ZetaSpacing.xl_1, + ), + child: CountriesDialog( + zeta: zeta, + useRootNavigator: widget.useRootNavigator, + enabled: widget.enabled, + searchHint: widget.countrySearchHint, + button: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: ZetaSpacingBase.x2_5, + ), + child: Image.asset( + _selectedCountry.flagUri, + package: 'zeta_flutter', + width: 26, + height: 18, + fit: BoxFit.fitHeight, + ), + ), + ZetaIcon( + ZetaIcons.expand_more, + color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + size: ZetaSpacing.xl_1, + ), + ], ), - ], - ), - items: _countries - .map( - (country) => CountriesMenuItem( - value: country, - child: Row( - children: [ - SizedBox( - width: 60, - child: Text(country.dialCode), - ), - Expanded( - child: Text(country.name), + items: _countries + .map( + (country) => CountriesMenuItem( + value: country, + child: Row( + children: [ + SizedBox( + width: 60, + child: Text(country.dialCode), + ), + Expanded( + child: Text(country.name), + ), + ], ), - ], - ), - ), - ) - .toList(), - onChanged: (value) => _onChanged(selectedCountry: value), + ), + ) + .toList(), + onChanged: (value) => _onChanged(selectedCountry: value), + ), + ), ), ), - ), - Expanded( - child: TextFormField( - maxLength: 20, - initialValue: widget.phoneNumber, - enabled: widget.enabled, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[\d\s\-]'))], - keyboardType: TextInputType.phone, - onChanged: (value) => _onChanged(phoneNumber: value), - style: ZetaTextStyles.bodyMedium.copyWith( - color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, - ), - decoration: InputDecoration( - counterText: '', - isDense: true, - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 10, - ), - hintStyle: ZetaTextStyles.bodyMedium.copyWith( + Expanded( + child: TextFormField( + maxLength: 20, + initialValue: widget.phoneNumber, + enabled: widget.enabled, + inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[\d\s\-]'))], + keyboardType: TextInputType.phone, + onChanged: (value) => _onChanged(phoneNumber: value), + style: ZetaTextStyles.bodyMedium.copyWith( color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, ), - prefixIcon: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.small), - child: Text( - _selectedCountry.dialCode, - style: ZetaTextStyles.bodyMedium.copyWith( - color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + decoration: InputDecoration( + counterText: '', + isDense: true, + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + hintStyle: ZetaTextStyles.bodyMedium.copyWith( + color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + ), + prefixIcon: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.small), + child: Text( + _selectedCountry.dialCode, + style: ZetaTextStyles.bodyMedium.copyWith( + color: widget.enabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + ), ), ), - ), - ], + ], + ), + prefixIconConstraints: const BoxConstraints( + minHeight: ZetaSpacing.xl_8, + minWidth: ZetaSpacing.xl_6, + ), + filled: true, + fillColor: widget.enabled + ? _hasError + ? zeta.colors.red.shade10 + : zeta.colors.surfacePrimary + : zeta.colors.cool.shade30, + enabledBorder: _hasError + ? _errorInputBorder(zeta, rounded: rounded) + : _defaultInputBorder(zeta, rounded: rounded), + focusedBorder: _hasError + ? _errorInputBorder(zeta, rounded: rounded) + : _focusedInputBorder(zeta, rounded: rounded), + disabledBorder: _defaultInputBorder(zeta, rounded: rounded), + errorBorder: _errorInputBorder(zeta, rounded: rounded), + focusedErrorBorder: _errorInputBorder(zeta, rounded: rounded), ), - prefixIconConstraints: const BoxConstraints( - minHeight: ZetaSpacing.xl_8, - minWidth: ZetaSpacing.xl_6, - ), - filled: true, - fillColor: widget.enabled - ? _hasError - ? zeta.colors.red.shade10 - : zeta.colors.surfacePrimary - : zeta.colors.cool.shade30, - enabledBorder: _hasError - ? _errorInputBorder(zeta, rounded: rounded) - : _defaultInputBorder(zeta, rounded: rounded), - focusedBorder: _hasError - ? _errorInputBorder(zeta, rounded: rounded) - : _focusedInputBorder(zeta, rounded: rounded), - disabledBorder: _defaultInputBorder(zeta, rounded: rounded), - errorBorder: _errorInputBorder(zeta, rounded: rounded), - focusedErrorBorder: _errorInputBorder(zeta, rounded: rounded), ), ), - ), - ], + ], + ), ), - ), - if (widget.hint != null || showError) - Padding( - padding: const EdgeInsets.only(top: 5), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.only(right: ZetaSpacing.small), - child: ZetaIcon( - (showError && widget.enabled) ? ZetaIcons.error : ZetaIcons.info, - size: ZetaSpacing.large, - color: hintErrorColor, - ), - ), - Expanded( - child: Text( - showError && widget.enabled ? widget.errorText! : widget.hint!, - style: ZetaTextStyles.bodyXSmall.copyWith( + if (widget.hint != null || showError) + Padding( + padding: const EdgeInsets.only(top: 5), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(right: ZetaSpacing.small), + child: ZetaIcon( + (showError && widget.enabled) ? ZetaIcons.error : ZetaIcons.info, + size: ZetaSpacing.large, color: hintErrorColor, ), ), - ), - ], + Expanded( + child: Text( + showError && widget.enabled ? widget.errorText! : widget.hint!, + style: ZetaTextStyles.bodyXSmall.copyWith( + color: hintErrorColor, + ), + ), + ), + ], + ), ), - ), - ], + ], + ), ); } diff --git a/lib/src/components/progress/progress_bar.dart b/lib/src/components/progress/progress_bar.dart index 7aa8214e..f4977636 100644 --- a/lib/src/components/progress/progress_bar.dart +++ b/lib/src/components/progress/progress_bar.dart @@ -90,37 +90,42 @@ class _ZetaProgressBarState extends ZetaProgressState { @override Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.label ?? - (widget.label == null && widget.type != ZetaProgressBarType.indeterminate - ? '${(animation.value * 100).toInt()}%' - : ''), - style: ZetaTextStyles.titleMedium, - textAlign: TextAlign.start, - ).paddingBottom(ZetaSpacing.large), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: AnimatedContainer( - duration: ZetaAnimationLength.verySlow, - height: _weight, - child: LinearProgressIndicator( - borderRadius: context.rounded ? ZetaRadius.rounded : ZetaRadius.none, - value: widget.type == ZetaProgressBarType.indeterminate ? null : animation.value, - backgroundColor: - widget.type == ZetaProgressBarType.buffering ? colors.surfaceDisabled : Colors.transparent, + return Semantics( + value: widget.type != ZetaProgressBarType.indeterminate ? '${progress * 100}%' : null, + label: widget.label, + excludeSemantics: true, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.label ?? + (widget.label == null && widget.type != ZetaProgressBarType.indeterminate + ? '${(animation.value * 100).toInt()}%' + : ''), + style: ZetaTextStyles.titleMedium, + textAlign: TextAlign.start, + ).paddingBottom(ZetaSpacing.large), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: AnimatedContainer( + duration: ZetaAnimationLength.verySlow, + height: _weight, + child: LinearProgressIndicator( + borderRadius: context.rounded ? ZetaRadius.rounded : ZetaRadius.none, + value: widget.type == ZetaProgressBarType.indeterminate ? null : animation.value, + backgroundColor: + widget.type == ZetaProgressBarType.buffering ? colors.surfaceDisabled : Colors.transparent, + ), ), ), - ), - if (widget.type == ZetaProgressBarType.buffering) bufferingWidget(colors), - ], - ), - ], + if (widget.type == ZetaProgressBarType.buffering) bufferingWidget(colors), + ], + ), + ], + ), ); } diff --git a/lib/src/components/progress/progress_circle.dart b/lib/src/components/progress/progress_circle.dart index 938a7f5f..175da41f 100644 --- a/lib/src/components/progress/progress_circle.dart +++ b/lib/src/components/progress/progress_circle.dart @@ -89,7 +89,7 @@ class ZetaProgressCircleState extends ZetaProgressState { constraints: BoxConstraints.tight(_getSize()), child: AnimatedBuilder( animation: controller, - builder: (context, child) { + builder: (_, child) { return CustomPaint( size: _getSize(), painter: CirclePainter( diff --git a/lib/src/components/radio/radio.dart b/lib/src/components/radio/radio.dart index c2ec3c18..d245df0a 100644 --- a/lib/src/components/radio/radio.dart +++ b/lib/src/components/radio/radio.dart @@ -66,6 +66,7 @@ class _ZetaRadioState extends State> with TickerProviderStateMix checked: widget._selected, selected: value, excludeSemantics: true, + enabled: !states.contains(WidgetState.disabled), child: MouseRegion( cursor: states.contains(WidgetState.disabled) ? SystemMouseCursors.forbidden : SystemMouseCursors.click, child: SelectionContainer.disabled( diff --git a/lib/src/components/screen_header_bar/screen_header_bar.dart b/lib/src/components/screen_header_bar/screen_header_bar.dart index 5fbf63ad..fdba12ba 100644 --- a/lib/src/components/screen_header_bar/screen_header_bar.dart +++ b/lib/src/components/screen_header_bar/screen_header_bar.dart @@ -11,6 +11,7 @@ class ZetaScreenHeaderBar extends ZetaStatelessWidget { this.title, this.actionButtonLabel, this.onActionButtonPressed, + this.backSemanticLabel, }); /// The title of [ZetaScreenHeaderBar]. Normally a [Text] widget. @@ -22,15 +23,24 @@ class ZetaScreenHeaderBar extends ZetaStatelessWidget { /// Called when the action button is pressed. final VoidCallback? onActionButtonPressed; + /// The semantic label for the back button. + /// + /// {@macro zeta-widget-semantic-label} + final String? backSemanticLabel; + @override Widget build(BuildContext context) { - final bool rounded = context.rounded; return ZetaRoundedScope( - rounded: rounded, + rounded: context.rounded, child: ZetaTopAppBar( - leading: IconButton( - onPressed: () async => Navigator.maybePop(context), - icon: const ZetaIcon(ZetaIcons.chevron_left), + leading: Semantics( + label: backSemanticLabel, + excludeSemantics: true, + button: true, + child: IconButton( + onPressed: () async => Navigator.maybePop(context), + icon: const ZetaIcon(ZetaIcons.chevron_left), + ), ), title: title, titleTextStyle: ZetaTextStyles.titleLarge, @@ -52,6 +62,7 @@ class ZetaScreenHeaderBar extends ZetaStatelessWidget { properties ..add(DiagnosticsProperty('rounded', rounded)) ..add(StringProperty('actionButtonLabel', actionButtonLabel)) - ..add(ObjectFlagProperty.has('onActionButtonPressed', onActionButtonPressed)); + ..add(ObjectFlagProperty.has('onActionButtonPressed', onActionButtonPressed)) + ..add(StringProperty('backSemanticLabel', backSemanticLabel)); } } diff --git a/lib/src/components/search_bar/search_bar.dart b/lib/src/components/search_bar/search_bar.dart index c549b236..4cfc78eb 100644 --- a/lib/src/components/search_bar/search_bar.dart +++ b/lib/src/components/search_bar/search_bar.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '../../../zeta_flutter.dart'; /// ZetaSearchBar provides input field for searching. -class ZetaSearchBar extends StatefulWidget { +class ZetaSearchBar extends ZetaStatefulWidget { /// Constructor for [ZetaSearchBar]. const ZetaSearchBar({ super.key, @@ -20,6 +20,8 @@ class ZetaSearchBar extends StatefulWidget { @Deprecated('Use disabled instead. ' 'enabled is deprecated as of 0.11.0') bool enabled = true, this.focusNode, this.textInputAction, + this.microphoneSemanticLabel, + this.clearSemanticLabel, }); /// Determines the size of the input field. @@ -63,6 +65,16 @@ class ZetaSearchBar extends StatefulWidget { /// A [FocusNode] for the underlying [TextFormField] final FocusNode? focusNode; + /// Label passed to the microphone button for semantic purposes. + /// + /// {@macro zeta-widget-semantic-label} + final String? microphoneSemanticLabel; + + /// Label passed to the clear button for semantic purposes. + /// + /// {@macro zeta-widget-semantic-label} + final String? clearSemanticLabel; + @override State createState() => _ZetaSearchBarState(); @@ -81,7 +93,9 @@ class ZetaSearchBar extends StatefulWidget { ..add(DiagnosticsProperty('showSpeechToText', showSpeechToText)) ..add(DiagnosticsProperty('focusNode', focusNode)) ..add(ObjectFlagProperty.has('onSubmit', onSubmit)) - ..add(EnumProperty('textInputAction', textInputAction)); + ..add(EnumProperty('textInputAction', textInputAction)) + ..add(StringProperty('microphoneSemanticLabel', microphoneSemanticLabel)) + ..add(StringProperty('clearSemanticLabel', clearSemanticLabel)); } } @@ -121,74 +135,90 @@ class _ZetaSearchBarState extends State { return ZetaRoundedScope( rounded: widget.shape != ZetaWidgetBorder.sharp, - child: TextFormField( - focusNode: widget.focusNode, - enabled: !widget.disabled, - controller: _controller, - keyboardType: TextInputType.text, - textInputAction: widget.textInputAction, - onFieldSubmitted: widget.onSubmit, - onChanged: (value) => setState(() => widget.onChanged?.call(value)), - style: ZetaTextStyles.bodyMedium, - decoration: InputDecoration( - isDense: true, - contentPadding: EdgeInsets.symmetric( - horizontal: 10, - vertical: _inputVerticalPadding(_size), - ), - hintText: widget.hint ?? 'Search', - hintStyle: ZetaTextStyles.bodyMedium.copyWith( - color: !widget.disabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, - ), - prefixIcon: widget.showLeadingIcon - ? Padding( - padding: const EdgeInsets.only(left: ZetaSpacingBase.x2_5, right: ZetaSpacing.small), - child: ZetaIcon( - ZetaIcons.search, - color: !widget.disabled ? zeta.colors.cool.shade70 : zeta.colors.cool.shade50, - size: iconSize, - ), - ) - : null, - prefixIconConstraints: const BoxConstraints( - minHeight: ZetaSpacing.xl_2, - minWidth: ZetaSpacing.xl_2, - ), - suffixIcon: IntrinsicHeight( - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (_controller.text.isNotEmpty && !widget.disabled) ...[ - IconButton( - key: const ValueKey('search-clear-btn'), - visualDensity: const VisualDensity( - horizontal: -4, - vertical: -4, - ), - onPressed: () { - setState(_controller.clear); - widget.onChanged?.call(''); - }, - icon: ZetaIcon( - ZetaIcons.cancel, - color: zeta.colors.cool.shade70, + child: Semantics( + excludeSemantics: widget.disabled, + label: widget.disabled ? widget.hint ?? 'Search' : null, // TODO(UX-1003): Localize + enabled: widget.disabled ? false : null, + child: TextFormField( + focusNode: widget.focusNode, + enabled: !widget.disabled, + controller: _controller, + keyboardType: TextInputType.text, + textInputAction: widget.textInputAction, + onFieldSubmitted: widget.onSubmit, + onChanged: (value) => setState(() => widget.onChanged?.call(value)), + style: ZetaTextStyles.bodyMedium, + decoration: InputDecoration( + isDense: true, + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: _inputVerticalPadding(_size), + ), + hintText: widget.hint ?? 'Search', // TODO(UX-1003): Localize + hintStyle: ZetaTextStyles.bodyMedium.copyWith( + color: !widget.disabled ? zeta.colors.textDefault : zeta.colors.cool.shade50, + ), + prefixIcon: widget.showLeadingIcon + ? Padding( + padding: const EdgeInsets.only(left: ZetaSpacingBase.x2_5, right: ZetaSpacing.small), + child: ZetaIcon( + ZetaIcons.search, + color: !widget.disabled ? zeta.colors.cool.shade70 : zeta.colors.cool.shade50, size: iconSize, ), - ), - if (widget.showSpeechToText) - SizedBox( - height: iconSize, - child: VerticalDivider( - color: zeta.colors.cool.shade40, - width: 5, - thickness: 1, + ) + : null, + prefixIconConstraints: const BoxConstraints( + minHeight: ZetaSpacing.xl_2, + minWidth: ZetaSpacing.xl_2, + ), + suffixIcon: IntrinsicHeight( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (_controller.text.isNotEmpty && !widget.disabled) ...[ + Semantics( + container: true, + button: true, + excludeSemantics: true, + label: widget.clearSemanticLabel, + child: IconButton( + key: const ValueKey('search-clear-btn'), + visualDensity: const VisualDensity( + horizontal: -4, + vertical: -4, + ), + onPressed: () { + setState(_controller.clear); + widget.onChanged?.call(''); + }, + icon: ZetaIcon( + ZetaIcons.cancel, + color: zeta.colors.cool.shade70, + size: iconSize, + ), ), ), - ], - Padding( - padding: const EdgeInsets.only(right: ZetaSpacing.minimum), - child: widget.showSpeechToText - ? IconButton( + if (widget.showSpeechToText) + SizedBox( + height: iconSize, + child: VerticalDivider( + color: zeta.colors.cool.shade40, + width: 5, + thickness: 1, + ), + ), + ], + if (widget.showSpeechToText) + Padding( + padding: const EdgeInsets.only(right: ZetaSpacing.minimum), + child: Semantics( + container: true, + label: widget.microphoneSemanticLabel, + excludeSemantics: true, + button: true, + child: IconButton( + tooltip: widget.microphoneSemanticLabel, key: const ValueKey('speech-to-text-btn'), visualDensity: const VisualDensity( horizontal: -4, @@ -207,21 +237,22 @@ class _ZetaSearchBarState extends State { ZetaIcons.microphone, size: iconSize, ), - ) - : const Nothing(), - ), - ], + ), + ), + ), + ], + ), ), + suffixIconConstraints: const BoxConstraints( + minHeight: ZetaSpacing.xl_2, + minWidth: ZetaSpacing.xl_2, + ), + filled: !widget.disabled ? null : true, + fillColor: !widget.disabled ? null : zeta.colors.cool.shade30, + enabledBorder: _defaultInputBorder(zeta, shape: _shape), + focusedBorder: _focusedInputBorder(zeta, shape: _shape), + disabledBorder: _defaultInputBorder(zeta, shape: _shape), ), - suffixIconConstraints: const BoxConstraints( - minHeight: ZetaSpacing.xl_2, - minWidth: ZetaSpacing.xl_2, - ), - filled: !widget.disabled ? null : true, - fillColor: !widget.disabled ? null : zeta.colors.cool.shade30, - enabledBorder: _defaultInputBorder(zeta, shape: _shape), - focusedBorder: _focusedInputBorder(zeta, shape: _shape), - disabledBorder: _defaultInputBorder(zeta, shape: _shape), ), ), ); diff --git a/lib/src/components/segmented_control/segmented_control.dart b/lib/src/components/segmented_control/segmented_control.dart index 45e5eb9a..7da92d6b 100644 --- a/lib/src/components/segmented_control/segmented_control.dart +++ b/lib/src/components/segmented_control/segmented_control.dart @@ -9,11 +9,12 @@ import '../../../zeta_flutter.dart'; class ZetaSegmentedControl extends ZetaStatefulWidget { /// Constructs an segmented control bar. const ZetaSegmentedControl({ + super.rounded, + super.key, required this.segments, required this.onChanged, required this.selected, - super.rounded, - super.key, + this.semanticLabel, }); /// The callback that is called when a new option is tapped. @@ -25,6 +26,11 @@ class ZetaSegmentedControl extends ZetaStatefulWidget { /// Currently selected segment. final T selected; + /// The semantic label for the segmented control. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State> createState() => _ZetaSegmentedControlState(); @@ -32,12 +38,11 @@ class ZetaSegmentedControl extends ZetaStatefulWidget { void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties - ..add( - ObjectFlagProperty.has('onChanged', onChanged), - ) + ..add(ObjectFlagProperty.has('onChanged', onChanged)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(IterableProperty>('segments', segments)) - ..add(DiagnosticsProperty('selected', selected)); + ..add(DiagnosticsProperty('selected', selected)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -109,8 +114,9 @@ class _ZetaSegmentedControlState extends State> children.add( _Segment( key: ValueKey(segment.value), - child: segment.child, onTap: () => widget.onChanged?.call(segment.value), + value: segment.value, + child: segment.child, ), ); @@ -122,27 +128,31 @@ class _ZetaSegmentedControlState extends State> return ZetaRoundedScope( rounded: rounded, - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: SelectionContainer.disabled( - child: Container( - padding: const EdgeInsets.all(ZetaSpacing.minimum), - decoration: BoxDecoration( - color: colors.surfaceDisabled, - borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, - ), - child: AnimatedBuilder( - animation: _thumbScaleAnimation, - builder: (BuildContext context, Widget? child) { - return _SegmentedControlRenderWidget( - highlightedIndex: highlightedIndex, - thumbColor: colors.surfacePrimary, - thumbScale: _thumbScaleAnimation.value, - rounded: rounded, - state: this, - children: children, - ); - }, + child: Semantics( + label: widget.semanticLabel, + container: true, + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: SelectionContainer.disabled( + child: Container( + padding: const EdgeInsets.all(ZetaSpacing.minimum), + decoration: BoxDecoration( + color: colors.surfaceDisabled, + borderRadius: rounded ? ZetaRadius.minimal : ZetaRadius.none, + ), + child: AnimatedBuilder( + animation: _thumbScaleAnimation, + builder: (BuildContext context, Widget? child) { + return _SegmentedControlRenderWidget( + highlightedIndex: highlightedIndex, + thumbColor: colors.surfacePrimary, + thumbScale: _thumbScaleAnimation.value, + rounded: rounded, + state: this, + children: children, + ); + }, + ), ), ), ), @@ -168,15 +178,17 @@ class ZetaButtonSegment { final T value; } -class _Segment extends StatefulWidget { +class _Segment extends ZetaStatefulWidget { const _Segment({ required ValueKey key, required this.child, required this.onTap, + required this.value, }) : super(key: key); final Widget child; final VoidCallback onTap; + final T value; @override _SegmentState createState() => _SegmentState(); @@ -184,7 +196,9 @@ class _Segment extends StatefulWidget { @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); - properties.add(ObjectFlagProperty.has('onTap', onTap)); + properties + ..add(ObjectFlagProperty.has('onTap', onTap)) + ..add(DiagnosticsProperty('value', value)); } } @@ -193,32 +207,37 @@ class _SegmentState extends State<_Segment> with TickerProviderStateMixin< Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return Material( - color: Colors.transparent, - child: InkWell( - splashFactory: NoSplash.splashFactory, - borderRadius: context.rounded ? ZetaRadius.minimal : ZetaRadius.none, - onTap: widget.onTap, - child: IndexedStack( - alignment: Alignment.center, - children: [ - widget.child, - IconTheme( - data: const IconThemeData(size: ZetaSpacing.xl_1), - child: DefaultTextStyle( - style: ZetaTextStyles.labelMedium.copyWith( - color: colors.textDefault, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: ZetaSpacing.xl_4, - vertical: ZetaSpacing.minimum, + return Semantics( + button: true, + excludeSemantics: true, + value: widget.value.toString(), + child: Material( + color: Colors.transparent, + child: InkWell( + splashFactory: NoSplash.splashFactory, + borderRadius: context.rounded ? ZetaRadius.minimal : ZetaRadius.none, + onTap: widget.onTap, + child: IndexedStack( + alignment: Alignment.center, + children: [ + widget.child, + IconTheme( + data: const IconThemeData(size: ZetaSpacing.xl_1), + child: DefaultTextStyle( + style: ZetaTextStyles.labelMedium.copyWith( + color: colors.textDefault, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: ZetaSpacing.xl_4, + vertical: ZetaSpacing.minimum, + ), + child: widget.child, ), - child: widget.child, ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/src/components/select_input/select_input.dart b/lib/src/components/select_input/select_input.dart index 2e397053..2908138d 100644 --- a/lib/src/components/select_input/select_input.dart +++ b/lib/src/components/select_input/select_input.dart @@ -11,6 +11,12 @@ import '../dropdown/dropdown_controller.dart'; class ZetaSelectInput extends ZetaFormField { ///Constructor of [ZetaSelectInput] const ZetaSelectInput({ + super.key, + super.rounded, + super.disabled = false, + super.initialValue, + super.onChange, + super.requirementLevel = ZetaFormFieldRequirement.none, required this.items, this.onTextChanged, this.size = ZetaWidgetSize.medium, @@ -20,12 +26,7 @@ class ZetaSelectInput extends ZetaFormField { this.placeholder, this.validator, this.errorText, - super.key, - super.rounded, - super.disabled = false, - super.initialValue, - super.onChange, - super.requirementLevel = ZetaFormFieldRequirement.none, + this.dropdownSemantics, }); /// Input items as list of [ZetaDropdownItem] @@ -58,6 +59,11 @@ class ZetaSelectInput extends ZetaFormField { /// The placeholder for the input. final String? placeholder; + /// The semantics label for the dropdown button. + /// + /// {@macro zeta-widget-semantic-label} + final String? dropdownSemantics; + @override State> createState() => _ZetaSelectInputState(); @override @@ -72,7 +78,8 @@ class ZetaSelectInput extends ZetaFormField { ..add(StringProperty('errorText', errorText)) ..add(ObjectFlagProperty.has('validator', validator)) ..add(StringProperty('label', label)) - ..add(StringProperty('placeholder', placeholder)); + ..add(StringProperty('placeholder', placeholder)) + ..add(StringProperty('dropdownSemantics', dropdownSemantics)); } } @@ -145,6 +152,7 @@ class _ZetaSelectInputState extends State> { return ZetaRoundedScope( rounded: context.rounded, child: ZetaDropdown( + disableButtonSemantics: true, items: filteredItems, onChange: !widget.disabled ? _onDropdownChanged : null, key: _dropdownKey, @@ -174,6 +182,7 @@ class _ZetaSelectInputState extends State> { hintText: widget.hintText, onChange: (val) => _onInputChanged(controller), suffix: InputIconButton( + semanticLabel: widget.dropdownSemantics, icon: _dropdownOpen ? ZetaIcons.expand_less : ZetaIcons.expand_more, disabled: widget.disabled, size: widget.size, diff --git a/lib/src/components/slider/slider.dart b/lib/src/components/slider/slider.dart index 45df0b65..e767adce 100644 --- a/lib/src/components/slider/slider.dart +++ b/lib/src/components/slider/slider.dart @@ -1,18 +1,18 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import '../../theme/tokens.dart'; -import '../../zeta.dart'; +import '../../../zeta_flutter.dart'; /// Slider component with customized styling -class ZetaSlider extends StatefulWidget { +class ZetaSlider extends ZetaStatefulWidget { /// Default constructor for [ZetaSlider] const ZetaSlider({ super.key, + super.rounded, required this.value, this.onChange, - this.rounded = false, this.divisions, + this.semanticLabel, }); /// Double value to represent slider percentage @@ -21,12 +21,14 @@ class ZetaSlider extends StatefulWidget { /// Callback to handle changing of slider final ValueChanged? onChange; - /// {@macro zeta-component-rounded} - final bool rounded; - /// Number of divisions. final int? divisions; + /// Value passed to the wrapping [Semantics] widget. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State createState() => _ZetaSliderState(); @override @@ -36,7 +38,8 @@ class ZetaSlider extends StatefulWidget { ..add(DiagnosticsProperty('rounded', rounded)) ..add(DoubleProperty('value', value)) ..add(ObjectFlagProperty?>.has('onChange', onChange)) - ..add(IntProperty('divisions', divisions)); + ..add(IntProperty('divisions', divisions)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -47,46 +50,51 @@ class _ZetaSliderState extends State { Widget build(BuildContext context) { final colors = Zeta.of(context).colors; - return SliderTheme( - data: SliderThemeData( - /** TODO: Match with new colors */ - - /// Active Track - activeTrackColor: _activeColor, - disabledActiveTrackColor: colors.surfaceDisabled, - - /// Inactive Track - inactiveTrackColor: colors.surfaceInfoSubtle, - - /// Ticks - activeTickMarkColor: colors.surfaceDefault, - inactiveTickMarkColor: colors.surfaceDefault, - - /// Thumb - thumbColor: colors.surfaceDefaultInverse, - disabledThumbColor: colors.surfaceDisabled, - overlayShape: SliderThumb(size: ZetaSpacing.xl_1, rounded: widget.rounded, color: _activeColor), - thumbShape: SliderThumb( - size: ZetaSpacing.large, - rounded: widget.rounded, - color: _activeColor, + return MergeSemantics( + child: Semantics( + label: widget.semanticLabel, + child: SliderTheme( + data: SliderThemeData( + /** TODO: Match with new colors */ + + /// Active Track + activeTrackColor: _activeColor, + disabledActiveTrackColor: colors.surfaceDisabled, + + /// Inactive Track + inactiveTrackColor: colors.surfaceInfoSubtle, + + /// Ticks + activeTickMarkColor: colors.surfaceDefault, + inactiveTickMarkColor: colors.surfaceDefault, + + /// Thumb + thumbColor: colors.surfaceDefaultInverse, + disabledThumbColor: colors.surfaceDisabled, + overlayShape: SliderThumb(size: ZetaSpacingBase.x2_5, rounded: context.rounded, color: _activeColor), + thumbShape: SliderThumb( + size: ZetaSpacing.small, + rounded: context.rounded, + color: _activeColor, + ), + ), + child: Slider( + value: widget.value, + onChanged: widget.onChange, + divisions: widget.divisions, + onChangeStart: (_) { + setState(() { + _selected = true; + }); + }, + onChangeEnd: (_) { + setState(() { + _selected = false; + }); + }, + ), ), ), - child: Slider( - value: widget.value, - onChanged: widget.onChange, - divisions: widget.divisions, - onChangeStart: (_) { - setState(() { - _selected = true; - }); - }, - onChangeEnd: (_) { - setState(() { - _selected = false; - }); - }, - ), ); } diff --git a/lib/src/components/stepper_input/stepper_input.dart b/lib/src/components/stepper_input/stepper_input.dart index 231488ad..d9674dfd 100644 --- a/lib/src/components/stepper_input/stepper_input.dart +++ b/lib/src/components/stepper_input/stepper_input.dart @@ -24,6 +24,8 @@ class ZetaStepperInput extends ZetaStatefulWidget { this.min, this.max, this.onChange, + this.semanticDecrement, + this.semanticIncrement, }) : assert( (min == null || (initialValue ?? 0) >= min) && (max == null || (initialValue ?? 0) <= max), 'Initial value must be inside given min and max values', @@ -48,6 +50,20 @@ class ZetaStepperInput extends ZetaStatefulWidget { /// {@macro zeta-widget-change-disable} final ValueChanged? onChange; + /// Value used for the semantic label of the decrement button. + /// + /// If null, '-' will be used. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticDecrement; + + /// Value used for the semantic label of the increment button. + /// + /// If null, '+' will be used. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticIncrement; + @override State createState() => _ZetaStepperInputState(); @override @@ -59,7 +75,9 @@ class ZetaStepperInput extends ZetaStatefulWidget { ..add(IntProperty('initialValue', initialValue)) ..add(IntProperty('min', min)) ..add(IntProperty('max', max)) - ..add(ObjectFlagProperty?>.has('onChange', onChange)); + ..add(ObjectFlagProperty?>.has('onChange', onChange)) + ..add(StringProperty('semanticDecrement', semanticDecrement)) + ..add(StringProperty('semanticIncrement', semanticIncrement)); } } @@ -127,6 +145,7 @@ class _ZetaStepperInputState extends State { ZetaIconButton _getButton({bool increase = false}) { return ZetaIconButton( + semanticLabel: increase ? (widget.semanticIncrement ?? '+') : (widget.semanticDecrement ?? '-'), icon: increase ? ZetaIcons.add : ZetaIcons.remove, type: ZetaButtonType.outlineSubtle, size: widget.size == ZetaStepperInputSize.medium ? ZetaWidgetSize.medium : ZetaWidgetSize.large, diff --git a/lib/src/components/tabs/tab.dart b/lib/src/components/tabs/tab.dart index a23c71b3..db5642b6 100644 --- a/lib/src/components/tabs/tab.dart +++ b/lib/src/components/tabs/tab.dart @@ -9,21 +9,26 @@ class ZetaTab extends Tab { String? text, super.key, }) : super( - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (icon != null) ...[ - const SizedBox(width: ZetaSpacing.medium), - icon, - ], - if (text != null) - Padding( - padding: icon != null ? const EdgeInsets.only(left: ZetaSpacing.small) : EdgeInsets.zero, - child: Text(text), - ), - if (icon != null) const SizedBox(width: ZetaSpacing.medium), - ], + child: Semantics( + button: true, + child: SelectionContainer.disabled( + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (icon != null) ...[ + const SizedBox(width: ZetaSpacing.medium), + icon, + ], + if (text != null) + Padding( + padding: icon != null ? const EdgeInsets.only(left: ZetaSpacing.small) : EdgeInsets.zero, + child: Text(text), + ), + if (icon != null) const SizedBox(width: ZetaSpacing.medium), + ], + ), + ), ), ); } diff --git a/lib/src/components/text_input/text_input.dart b/lib/src/components/text_input/text_input.dart index 8523d7c9..209d970e 100644 --- a/lib/src/components/text_input/text_input.dart +++ b/lib/src/components/text_input/text_input.dart @@ -37,6 +37,7 @@ class ZetaTextInput extends ZetaFormField { this.suffixTextStyle, this.onSubmit, this.obscureText = false, + this.semanticLabel, }) : assert(initialValue == null || controller == null, 'Only one of initial value and controller can be accepted.'), assert(prefix == null || prefixText == null, 'Only one of prefix or prefixText can be accepted.'), assert(suffix == null || suffixText == null, 'Only one of suffix or suffixText can be accepted.'); @@ -108,6 +109,13 @@ class ZetaTextInput extends ZetaFormField { /// {@endtemplate} final bool obscureText; + /// Value passed to the wrapping [Semantics] widget. + /// + /// If null, the label will be used. + /// + /// {@macro zeta-widget-semantic-label} + final String? semanticLabel; + @override State createState() => ZetaTextInputState(); @override @@ -132,7 +140,8 @@ class ZetaTextInput extends ZetaFormField { ..add(IterableProperty('inputFormatters', inputFormatters)) ..add(EnumProperty('requirementLevel', requirementLevel)) ..add(ObjectFlagProperty.has('onSubmit', onSubmit)) - ..add(DiagnosticsProperty('obscureText', obscureText)); + ..add(DiagnosticsProperty('obscureText', obscureText)) + ..add(StringProperty('semanticLabel', semanticLabel)); } } @@ -282,76 +291,73 @@ class ZetaTextInputState extends State implements ZetaFormFieldSt return ZetaRoundedScope( rounded: rounded, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (widget.label != null) ...[ - _Label( - label: widget.label!, - requirementLevel: widget.requirementLevel, + child: Semantics( + label: widget.semanticLabel ?? widget.hintText, + enabled: !widget.disabled, + excludeSemantics: widget.disabled, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (widget.label != null) ...[ + _Label( + label: widget.label!, + requirementLevel: widget.requirementLevel, + disabled: widget.disabled, + ), + const SizedBox(height: ZetaSpacing.minimum), + ], + MouseRegion( + onEnter: !widget.disabled ? (_) => setState(() => _hovered = true) : null, + onExit: !widget.disabled ? (_) => setState(() => _hovered = false) : null, + child: TextFormField( + enabled: !widget.disabled, + key: _key, + controller: _controller, + inputFormatters: widget.inputFormatters, + validator: (val) { + setState(() { + _errorText = widget.validator?.call(val); + }); + return _errorText; + }, + onFieldSubmitted: widget.onSubmit, + textAlignVertical: TextAlignVertical.center, + onChanged: widget.onChange, + style: _baseTextStyle, + cursorErrorColor: _colors.error, + obscureText: widget.obscureText, + decoration: InputDecoration( + isDense: true, + contentPadding: _contentPadding, + filled: true, + prefixIcon: _prefix, + prefixIconConstraints: widget.prefixText != null ? _affixConstraints : null, + suffixIcon: _suffix, + suffixIconConstraints: _affixConstraints, + focusColor: _backgroundColor, + hoverColor: _backgroundColor, + fillColor: _backgroundColor, + enabledBorder: _baseBorder(rounded), + disabledBorder: _baseBorder(rounded), + focusedBorder: _focusedBorder(rounded), + focusedErrorBorder: _errorBorder(rounded), + errorBorder: widget.disabled ? _baseBorder(rounded) : _errorBorder(rounded), + hintText: widget.placeholder, + errorText: _errorText, + hintStyle: _baseTextStyle, + errorStyle: const TextStyle(height: 0.001, color: Colors.transparent), + ), + ), + ), + _HintText( disabled: widget.disabled, + rounded: rounded, + hintText: widget.hintText, + errorText: _errorText, ), - const SizedBox(height: ZetaSpacing.minimum), ], - MouseRegion( - onEnter: !widget.disabled - ? (_) => setState(() { - _hovered = true; - }) - : null, - onExit: !widget.disabled - ? (_) => setState(() { - _hovered = false; - }) - : null, - child: TextFormField( - enabled: !widget.disabled, - key: _key, - controller: _controller, - inputFormatters: widget.inputFormatters, - validator: (val) { - setState(() { - _errorText = widget.validator?.call(val); - }); - return _errorText; - }, - onFieldSubmitted: widget.onSubmit, - textAlignVertical: TextAlignVertical.center, - onChanged: widget.onChange, - style: _baseTextStyle, - cursorErrorColor: _colors.error, - obscureText: widget.obscureText, - decoration: InputDecoration( - isDense: true, - contentPadding: _contentPadding, - filled: true, - prefixIcon: _prefix, - prefixIconConstraints: widget.prefixText != null ? _affixConstraints : null, - suffixIcon: _suffix, - suffixIconConstraints: _affixConstraints, - focusColor: _backgroundColor, - hoverColor: _backgroundColor, - fillColor: _backgroundColor, - enabledBorder: _baseBorder(rounded), - disabledBorder: _baseBorder(rounded), - focusedBorder: _focusedBorder(rounded), - focusedErrorBorder: _errorBorder(rounded), - errorBorder: widget.disabled ? _baseBorder(rounded) : _errorBorder(rounded), - hintText: widget.placeholder, - errorText: _errorText, - hintStyle: _baseTextStyle, - errorStyle: const TextStyle(height: 0.001, color: Colors.transparent), - ), - ), - ), - _HintText( - disabled: widget.disabled, - rounded: rounded, - hintText: widget.hintText, - errorText: _errorText, - ), - ], + ), ), ); } @@ -443,25 +449,27 @@ class _HintText extends StatelessWidget { return const Nothing(); } - return Row( - children: [ - ZetaIcon( - errorText != null ? ZetaIcons.error : ZetaIcons.info, - size: ZetaSpacing.large, - color: elementColor, - ), - const SizedBox( - width: ZetaSpacing.minimum, - ), - Expanded( - child: Text( - text, - style: ZetaTextStyles.bodyXSmall.copyWith(color: elementColor), - overflow: TextOverflow.ellipsis, + return ExcludeSemantics( + child: Row( + children: [ + ZetaIcon( + errorText != null ? ZetaIcons.error : ZetaIcons.info, + size: ZetaSpacing.large, + color: elementColor, ), - ), - ], - ).paddingTop(ZetaSpacing.small); + const SizedBox( + width: ZetaSpacing.minimum, + ), + Expanded( + child: Text( + text, + style: ZetaTextStyles.bodyXSmall.copyWith(color: elementColor), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ).paddingTop(ZetaSpacing.small), + ); } @override diff --git a/lib/src/components/time_input/time_input.dart b/lib/src/components/time_input/time_input.dart index 2e1c6052..616bffbd 100644 --- a/lib/src/components/time_input/time_input.dart +++ b/lib/src/components/time_input/time_input.dart @@ -30,6 +30,8 @@ class ZetaTimeInput extends ZetaFormField { this.validator, this.size = ZetaWidgetSize.medium, this.pickerInitialEntryMode, + this.clearSemanticLabel, + this.timePickerSemanticLabel, }); /// Changes the time input to 12 hour time. @@ -61,6 +63,16 @@ class ZetaTimeInput extends ZetaFormField { /// However, if [validator] catches any of these conditions, the return value of [validator] will be shown. final String? Function(TimeOfDay? value)? validator; + /// Semantic label for the clear button. + /// + /// {@macro zeta-widget-semantic-label} + final String? clearSemanticLabel; + + /// Semantic label for the time picker button. + /// + /// {@macro zeta-widget-semantic-label} + final String? timePickerSemanticLabel; + @override State createState() => ZetaTimeInputState(); @override @@ -77,7 +89,9 @@ class ZetaTimeInput extends ZetaFormField { ..add(StringProperty('errorText', errorText)) ..add(EnumProperty('size', size)) ..add(ObjectFlagProperty.has('validator', validator)) - ..add(EnumProperty('pickerInitialEntryMode', pickerInitialEntryMode)); + ..add(EnumProperty('pickerInitialEntryMode', pickerInitialEntryMode)) + ..add(StringProperty('clearSemanticLabel', clearSemanticLabel)) + ..add(StringProperty('timePickerSemanticLabel', timePickerSemanticLabel)); } } @@ -250,6 +264,7 @@ class ZetaTimeInputState extends State implements ZetaFormFieldSt if (_showClearButton) InputIconButton( icon: ZetaIcons.cancel, + semanticLabel: widget.clearSemanticLabel, onTap: reset, disabled: widget.disabled, size: widget.size, @@ -257,6 +272,7 @@ class ZetaTimeInputState extends State implements ZetaFormFieldSt ), InputIconButton( icon: ZetaIcons.clock_outline, + semanticLabel: widget.timePickerSemanticLabel, onTap: _pickTime, disabled: widget.disabled, size: widget.size, diff --git a/lib/src/components/tooltip/tooltip.dart b/lib/src/components/tooltip/tooltip.dart index f65b363a..a307a98d 100644 --- a/lib/src/components/tooltip/tooltip.dart +++ b/lib/src/components/tooltip/tooltip.dart @@ -82,81 +82,88 @@ class ZetaTooltip extends ZetaStatelessWidget { rounded: context.rounded, child: LayoutBuilder( builder: (context, constraints) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (arrowDirection == ZetaTooltipArrowDirection.up) - Center( - child: CustomPaint( - painter: _FilledArrow( - color: color, - direction: arrowDirection, - ), - size: _verticalArrowSize, - ), - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (arrowDirection == ZetaTooltipArrowDirection.left) - Center( - child: CustomPaint( - painter: _FilledArrow( - color: color, - direction: arrowDirection, + return MergeSemantics( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (arrowDirection == ZetaTooltipArrowDirection.up) + Center( + child: CustomPaint( + painter: _FilledArrow( + color: color, + direction: arrowDirection, + ), + size: _verticalArrowSize, ), - size: _horizontalArrowSize, ), - ), - ConstrainedBox( - constraints: BoxConstraints( - maxWidth: maxWidth ?? (constraints.maxWidth - horizontalArrowWidth), - ), - child: DecoratedBox( - decoration: BoxDecoration( - color: color, - borderRadius: context.rounded ? ZetaRadius.minimal : null, - ), - child: Padding( - padding: padding ?? - const EdgeInsets.symmetric( - horizontal: ZetaSpacing.small, - vertical: ZetaSpacing.minimum, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (arrowDirection == ZetaTooltipArrowDirection.left) + Center( + child: CustomPaint( + painter: _FilledArrow( + color: color, + direction: arrowDirection, + ), + size: _horizontalArrowSize, + ), + ), + ConstrainedBox( + constraints: BoxConstraints( + maxWidth: maxWidth ?? (constraints.maxWidth - horizontalArrowWidth), + ), + child: DecoratedBox( + decoration: BoxDecoration( + color: color, + borderRadius: context.rounded ? ZetaRadius.minimal : null, ), - child: DefaultTextStyle( - style: textStyle ?? - ZetaTextStyles.bodyXSmall.copyWith( - color: zeta.colors.textInverse, - fontWeight: FontWeight.w500, + child: Padding( + padding: padding ?? + const EdgeInsets.symmetric( + horizontal: ZetaSpacing.small, + vertical: ZetaSpacing.minimum, + ), + child: DefaultTextStyle( + style: textStyle ?? + ZetaTextStyles.bodyXSmall.copyWith( + color: zeta.colors.textInverse, + fontWeight: FontWeight.w500, + ), + child: child, ), - child: child, + ), + ), ), - ), + if (arrowDirection == ZetaTooltipArrowDirection.right) + Center( + child: CustomPaint( + painter: _FilledArrow( + color: color, + direction: arrowDirection, + ), + size: _horizontalArrowSize, + ), + ), + ], ), - ), - if (arrowDirection == ZetaTooltipArrowDirection.right) - Center( - child: CustomPaint( - painter: _FilledArrow( - color: color, - direction: arrowDirection, + if (arrowDirection == ZetaTooltipArrowDirection.down) + Center( + child: CustomPaint( + painter: _FilledArrow( + color: color, + direction: arrowDirection, + ), + size: _verticalArrowSize, ), - size: _horizontalArrowSize, ), - ), - ], - ), - if (arrowDirection == ZetaTooltipArrowDirection.down) - Center( - child: CustomPaint( - painter: _FilledArrow( - color: color, - direction: arrowDirection, - ), - size: _verticalArrowSize, - ), + ], ), - ], + ], + ), ); }, ), diff --git a/lib/src/components/top_app_bar/top_app_bar.dart b/lib/src/components/top_app_bar/top_app_bar.dart index b908d5b0..00ab17c1 100644 --- a/lib/src/components/top_app_bar/top_app_bar.dart +++ b/lib/src/components/top_app_bar/top_app_bar.dart @@ -11,6 +11,8 @@ export 'search_top_app_bar.dart' show AppBarSearchController; class ZetaTopAppBar extends ZetaStatefulWidget implements PreferredSizeWidget { /// Creates a ZetaTopAppBar. const ZetaTopAppBar({ + super.key, + super.rounded, this.actions, this.automaticallyImplyLeading = true, this.searchController, @@ -21,12 +23,12 @@ class ZetaTopAppBar extends ZetaStatefulWidget implements PreferredSizeWidget { this.onSearch, this.searchHintText = 'Search', this.onSearchMicrophoneIconPressed, - super.key, - super.rounded, }) : shrinks = false; /// Creates a ZetaTopAppBar with centered title. const ZetaTopAppBar.centered({ + super.key, + super.rounded, this.actions, this.automaticallyImplyLeading = true, this.searchController, @@ -36,7 +38,6 @@ class ZetaTopAppBar extends ZetaStatefulWidget implements PreferredSizeWidget { this.onSearch, this.searchHintText = 'Search', this.onSearchMicrophoneIconPressed, - super.key, }) : type = ZetaTopAppBarType.centeredTitle, shrinks = false; @@ -44,6 +45,8 @@ class ZetaTopAppBar extends ZetaStatefulWidget implements PreferredSizeWidget { /// /// This component **must** be placed within a [CustomScrollView]. const ZetaTopAppBar.extended({ + super.key, + super.rounded, this.actions, this.automaticallyImplyLeading = true, this.searchController, @@ -54,7 +57,6 @@ class ZetaTopAppBar extends ZetaStatefulWidget implements PreferredSizeWidget { this.searchHintText = 'Search', this.onSearchMicrophoneIconPressed, this.shrinks = true, - super.key, }) : type = ZetaTopAppBarType.extendedTitle; /// Called when text in the search field is submitted. diff --git a/lib/src/utils/rounded.dart b/lib/src/utils/rounded.dart index 78cdd7f4..952d37bb 100644 --- a/lib/src/utils/rounded.dart +++ b/lib/src/utils/rounded.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -70,7 +68,7 @@ extension Rounded on BuildContext { return (widget as dynamic).rounded as bool; } } catch (e) { - log('Widget(${widget.runtimeType}) does not have rounded \n $e'); + /// Ignore error } return ZetaRoundedScope.of(this)?._rounded ?? Zeta.of(this).rounded; diff --git a/lib/src/zeta_provider.dart b/lib/src/zeta_provider.dart index 690fdfa6..ad6fc4e4 100644 --- a/lib/src/zeta_provider.dart +++ b/lib/src/zeta_provider.dart @@ -372,24 +372,105 @@ ThemeData generateZetaTheme({ ZetaThemeData? zetaThemeData, }) { if (existingTheme != null) { + final baseThemeData = ThemeData(); + // Apply the Zeta styles to the existing theme, ignoring fields that are the same as the default ThemeData. return ThemeData( brightness: brightness, useMaterial3: existingTheme.useMaterial3, fontFamily: fontFamily ?? - (existingTheme.textTheme.bodyMedium?.fontFamily == ThemeData().textTheme.bodyMedium?.fontFamily - ? null + (existingTheme.textTheme.bodyMedium?.fontFamily == baseThemeData.textTheme.bodyMedium?.fontFamily + ? kZetaFontFamily : existingTheme.textTheme.bodyMedium?.fontFamily), - scaffoldBackgroundColor: (existingTheme.colorScheme.surfaceTertiary == ThemeData().colorScheme.surfaceTertiary - ? null - : existingTheme.colorScheme.surfaceTertiary) ?? - colorScheme.surfaceTertiary, + scaffoldBackgroundColor: [ + Colors.grey[850]!, + Colors.grey[50]!, + baseThemeData.scaffoldBackgroundColor, + baseThemeData.colorScheme.surface, + ].any((e) => e == existingTheme.scaffoldBackgroundColor) + ? colorScheme.surfaceTertiary + : existingTheme.scaffoldBackgroundColor, colorScheme: - ((existingTheme.colorScheme == ThemeData().colorScheme ? null : existingTheme.colorScheme) ?? colorScheme) + ((existingTheme.colorScheme == baseThemeData.colorScheme ? null : existingTheme.colorScheme) ?? colorScheme) .copyWith(brightness: brightness), - textTheme: (existingTheme.textTheme == ThemeData().textTheme ? null : existingTheme.textTheme) ?? zetaTextTheme, - iconTheme: (existingTheme.iconTheme == ThemeData().iconTheme ? null : existingTheme.iconTheme) ?? + textTheme: (existingTheme.textTheme == baseThemeData.textTheme ? null : existingTheme.textTheme) ?? zetaTextTheme, + iconTheme: (existingTheme.iconTheme == baseThemeData.iconTheme ? null : existingTheme.iconTheme) ?? const IconThemeData(size: kZetaIconSize), + actionIconTheme: existingTheme.actionIconTheme, + applyElevationOverlayColor: existingTheme.applyElevationOverlayColor, + cupertinoOverrideTheme: existingTheme.cupertinoOverrideTheme, + inputDecorationTheme: existingTheme.inputDecorationTheme, + materialTapTargetSize: existingTheme.materialTapTargetSize, + pageTransitionsTheme: existingTheme.pageTransitionsTheme, + platform: existingTheme.platform, + scrollbarTheme: existingTheme.scrollbarTheme, + splashFactory: existingTheme.splashFactory, + visualDensity: existingTheme.visualDensity, + canvasColor: existingTheme.canvasColor, + cardColor: existingTheme.cardColor, + dialogBackgroundColor: existingTheme.dialogBackgroundColor, + disabledColor: existingTheme.disabledColor, + dividerColor: existingTheme.dividerColor, + focusColor: existingTheme.focusColor, + highlightColor: existingTheme.highlightColor, + hintColor: existingTheme.hintColor, + hoverColor: existingTheme.hoverColor, + indicatorColor: existingTheme.indicatorColor, + primaryColor: existingTheme.primaryColor, + primaryColorDark: existingTheme.primaryColorDark, + primaryColorLight: existingTheme.primaryColorLight, + secondaryHeaderColor: existingTheme.secondaryHeaderColor, + shadowColor: existingTheme.shadowColor, + splashColor: existingTheme.splashColor, + unselectedWidgetColor: existingTheme.unselectedWidgetColor, + primaryIconTheme: existingTheme.primaryIconTheme, + primaryTextTheme: existingTheme.primaryTextTheme, + typography: existingTheme.typography, + appBarTheme: existingTheme.appBarTheme, + badgeTheme: existingTheme.badgeTheme, + bannerTheme: existingTheme.bannerTheme, + bottomAppBarTheme: existingTheme.bottomAppBarTheme, + bottomNavigationBarTheme: existingTheme.bottomNavigationBarTheme, + bottomSheetTheme: existingTheme.bottomSheetTheme, + buttonBarTheme: existingTheme.buttonBarTheme, + buttonTheme: existingTheme.buttonTheme, + cardTheme: existingTheme.cardTheme, + checkboxTheme: existingTheme.checkboxTheme, + chipTheme: existingTheme.chipTheme, + dataTableTheme: existingTheme.dataTableTheme, + datePickerTheme: existingTheme.datePickerTheme, + dialogTheme: existingTheme.dialogTheme, + dividerTheme: existingTheme.dividerTheme, + drawerTheme: existingTheme.drawerTheme, + dropdownMenuTheme: existingTheme.dropdownMenuTheme, + elevatedButtonTheme: existingTheme.elevatedButtonTheme, + expansionTileTheme: existingTheme.expansionTileTheme, + filledButtonTheme: existingTheme.filledButtonTheme, + floatingActionButtonTheme: existingTheme.floatingActionButtonTheme, + iconButtonTheme: existingTheme.iconButtonTheme, + listTileTheme: existingTheme.listTileTheme, + menuBarTheme: existingTheme.menuBarTheme, + menuButtonTheme: existingTheme.menuButtonTheme, + menuTheme: existingTheme.menuTheme, + navigationBarTheme: existingTheme.navigationBarTheme, + navigationDrawerTheme: existingTheme.navigationDrawerTheme, + navigationRailTheme: existingTheme.navigationRailTheme, + outlinedButtonTheme: existingTheme.outlinedButtonTheme, + popupMenuTheme: existingTheme.popupMenuTheme, + progressIndicatorTheme: existingTheme.progressIndicatorTheme, + radioTheme: existingTheme.radioTheme, + searchBarTheme: existingTheme.searchBarTheme, + searchViewTheme: existingTheme.searchViewTheme, + segmentedButtonTheme: existingTheme.segmentedButtonTheme, + sliderTheme: existingTheme.sliderTheme, + snackBarTheme: existingTheme.snackBarTheme, + switchTheme: existingTheme.switchTheme, + tabBarTheme: existingTheme.tabBarTheme, + textButtonTheme: existingTheme.textButtonTheme, + textSelectionTheme: existingTheme.textSelectionTheme, + timePickerTheme: existingTheme.timePickerTheme, + toggleButtonsTheme: existingTheme.toggleButtonsTheme, + tooltipTheme: existingTheme.tooltipTheme, ); } return ThemeData( diff --git a/test/src/components/checkbox/checkbox_test.dart b/test/src/components/checkbox/checkbox_test.dart index c9926017..e921faea 100644 --- a/test/src/components/checkbox/checkbox_test.dart +++ b/test/src/components/checkbox/checkbox_test.dart @@ -118,6 +118,30 @@ void main() { await tester.pump(); }); + testWidgets('ZetaCheckbox UI changes on hover', (WidgetTester tester) async { + await tester.pumpWidget( + TestApp( + home: ZetaCheckbox( + onChanged: (value) {}, + ), + ), + ); + + final checkboxFinder = find.byType(ZetaCheckbox); + + // Hover state + final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + await gesture.addPointer(location: Offset.zero); + addTearDown(gesture.removePointer); + await tester.pump(); + await gesture.moveTo(tester.getCenter(checkboxFinder)); + await tester.pumpAndSettle(); + await expectLater( + checkboxFinder, + matchesGoldenFile(join(getCurrentPath('checkbox'), 'checkbox_hover.png')), + ); + }); + testWidgets('debugFillProperties works correctly', (WidgetTester tester) async { final diagnostics = DiagnosticPropertiesBuilder(); ZetaCheckbox().debugFillProperties(diagnostics); diff --git a/test/src/components/checkbox/golden/checkbox_hover.png b/test/src/components/checkbox/golden/checkbox_hover.png new file mode 100644 index 00000000..bc27d144 Binary files /dev/null and b/test/src/components/checkbox/golden/checkbox_hover.png differ diff --git a/test/src/components/fabs/fab_test.dart b/test/src/components/fabs/fab_test.dart index b87fe1ce..da430aa9 100644 --- a/test/src/components/fabs/fab_test.dart +++ b/test/src/components/fabs/fab_test.dart @@ -41,9 +41,16 @@ void main() { home: ZetaFAB(scrollController: scrollController, label: 'Label', onPressed: () => isPressed = true), ), ); + final TestGesture e = await tester.press(find.byType(ZetaFAB)); - await tester.tap(find.byType(ZetaFAB)); await tester.pumpAndSettle(); + + await expectLater( + find.byType(ZetaFAB), + matchesGoldenFile(join(getCurrentPath('fabs'), 'FAB_pressed.png')), + ); + + await e.up(); expect(isPressed, isTrue); }); }); @@ -144,6 +151,26 @@ void main() { ); }); + testWidgets('Disabled FAB', (WidgetTester tester) async { + final scrollController = ScrollController(); + await tester.pumpWidget( + TestApp( + home: ZetaFAB(scrollController: scrollController, label: 'Disabled'), + ), + ); + + final fabFinder = find.byType(ZetaFAB); + final ZetaFAB fab = tester.firstWidget(fabFinder); + + expect(fab.onPressed, isNull); + expect(fab.type, ZetaFabType.primary); + expect(fab.shape, ZetaWidgetBorder.full); + + await expectLater( + find.byType(ZetaFAB), + matchesGoldenFile(join(getCurrentPath('fabs'), 'FAB_disabled.png')), + ); + }); testWidgets('debugFillProperties works correctly', (WidgetTester tester) async { final diagnostics = DiagnosticPropertiesBuilder(); const ZetaFAB().debugFillProperties(diagnostics); diff --git a/test/src/components/fabs/golden/FAB_disabled.png b/test/src/components/fabs/golden/FAB_disabled.png new file mode 100644 index 00000000..24e1062f Binary files /dev/null and b/test/src/components/fabs/golden/FAB_disabled.png differ diff --git a/test/src/components/fabs/golden/FAB_pressed.png b/test/src/components/fabs/golden/FAB_pressed.png new file mode 100644 index 00000000..10365d11 Binary files /dev/null and b/test/src/components/fabs/golden/FAB_pressed.png differ diff --git a/test/src/components/tooltip/golden/arrow_down.png b/test/src/components/tooltip/golden/arrow_down.png index f7e97880..69aed7ff 100644 Binary files a/test/src/components/tooltip/golden/arrow_down.png and b/test/src/components/tooltip/golden/arrow_down.png differ diff --git a/test/src/components/tooltip/golden/arrow_up.png b/test/src/components/tooltip/golden/arrow_up.png index c7f0165b..a4f04338 100644 Binary files a/test/src/components/tooltip/golden/arrow_up.png and b/test/src/components/tooltip/golden/arrow_up.png differ diff --git a/test/src/zeta_provider_test.dart b/test/src/zeta_provider_test.dart index 38f65a99..ecf19b76 100644 --- a/test/src/zeta_provider_test.dart +++ b/test/src/zeta_provider_test.dart @@ -120,6 +120,23 @@ void main() { ).called(1); }); + testWidgets('updateRounded updates the state correctly', (WidgetTester tester) async { + await tester.pumpWidget( + ZetaProvider( + builder: (context, themeData, themeMode) => Container(), + initialThemeData: initialThemeData, + themeService: mockThemeService, + ), + ); + + tester.state(find.byType(ZetaProvider)).updateRounded(false); + await tester.pump(); + + // Verifying through the public interface of Zeta widget + final zeta = tester.widget(find.byType(Zeta)); + expect(zeta.rounded, false); + }); + testWidgets('didUpdateWidget in ZetaProviderState works correctly with change in ThemeMode', (WidgetTester tester) async { await tester.pumpWidget( @@ -222,6 +239,41 @@ void main() { // Verifying through the public interface of Zeta widget expect(tester.widget(find.byType(Zeta)).themeData.identifier, 'different'); }); + testWidgets('didUpdateWidget in ZetaProviderState works correctly with change rounded', + (WidgetTester tester) async { + await tester.pumpWidget( + ZetaProvider( + initialThemeData: initialThemeData, + builder: (context, themeData, themeMode) => Builder( + builder: (context) { + return Container(); + }, + ), + ), + ); + + await tester.pumpAndSettle(); + + // Verifying through the public interface of Zeta widget + expect(tester.widget(find.byType(Zeta)).rounded, true); + + await tester.pumpWidget( + ZetaProvider( + initialThemeData: initialThemeData, + initialRounded: false, + builder: (context, themeData, themeMode) => Builder( + builder: (context) { + return Container(); + }, + ), + ), + ); + + await tester.pumpAndSettle(const Duration(milliseconds: 250)); + + // Verifying through the public interface of Zeta widget + expect(tester.widget(find.byType(Zeta)).rounded, false); + }); testWidgets('retrieves ZetaProviderState from context', (WidgetTester tester) async { await tester.pumpWidget( @@ -272,6 +324,56 @@ void main() { expect(zeta.brightness, Brightness.dark); }); + testWidgets('generateZetaTheme applies zeta values to existing theme', (WidgetTester tester) async { + final ColorScheme colors = ColorScheme.fromSeed(seedColor: Colors.red); + + final theme = generateZetaTheme( + brightness: Brightness.light, + colorScheme: ZetaColors.light().toScheme(), + existingTheme: ThemeData( + fontFamily: 'Comic Sans', + primaryColor: Colors.red, + useMaterial3: false, + scaffoldBackgroundColor: Colors.blue, + colorScheme: colors, + ), + ); + expect(theme.useMaterial3, false); + expect(theme.brightness, Brightness.light); + expect(theme.primaryColor, Colors.red); + expect(theme.scaffoldBackgroundColor, Colors.blue); + + final theme2 = generateZetaTheme( + brightness: Brightness.light, + colorScheme: colors, + existingTheme: ThemeData( + fontFamily: 'Comic Sans', + primaryColor: Colors.red, + useMaterial3: false, + colorScheme: colors, + ), + ); + expect(theme2.useMaterial3, false); + expect(theme2.brightness, Brightness.light); + expect(theme2.primaryColor, Colors.red); + + expect(theme2.scaffoldBackgroundColor, ZetaColors.light().toScheme().surfaceTertiary); + }); + testWidgets('generateZetaTheme generates a new theme', (WidgetTester tester) async { + final theme = generateZetaTheme(brightness: Brightness.light, colorScheme: ZetaColors.light().toScheme()); + expect(theme.useMaterial3, true); + expect(theme.brightness, Brightness.light); + expect(theme.colorScheme, ZetaColors.light().toScheme()); + + final theme2 = generateZetaTheme( + brightness: Brightness.light, + colorScheme: ZetaColors.light().toScheme(), + zetaThemeData: initialThemeData, + ); + + expect(theme2.iconTheme.color, initialThemeData.colorsLight.iconDefault); + }); + testWidgets('debugFillProperties works correctly', (WidgetTester tester) async { final diagnostics = DiagnosticPropertiesBuilder();