commit f142c9138f1d943190c5a8f5b4385ae86a6d0985
parent d8715cf302fb2933b6264b68de900dca740479b6
Author: Chloe Zhou <chloezhouny@gmail.com>
Date: Sat, 20 Dec 2025 01:55:36 +0000
Bug 2005380 - Create firstrun model picker screen r=pdahiya,fluent-reviewers,omc-reviewers,ai-frontend-reviewers,bolsson
**Summay**
This patch implements the model picker screen for the AI Window first-run flow. Users select their preferred AI model from three options, and the selection is stored in browser.aiwindow.firstrun.modelChoice preference (values: "1", "2", or "3"). The flow uses the AboutWelcome bundle.
**Test Steps**
1. In about:config, set browser.tabs.allow_transparent_browser and browser.aiwindow.enabled to true
2. Navigate to chrome://browser/content/aiwindow/firstrun.html
3. Verify intro screen appears with gradient title animation
4. Wait ~20 seconds for auto-advance to model picker screen //(Note: Auto-advance timing will be configured in a follow-up patch)//
5. Select a model card and click "Let's go" button
6. Verify screen is navigated to chrome://browser/content/aiwindow/aiwindow.html page
7. Verify browser.aiwindow.firstrun.modelChoice pref is set to selected value ("1", "2", or "3")
Differential Revision: https://phabricator.services.mozilla.com/D276705
Diffstat:
10 files changed, 319 insertions(+), 28 deletions(-)
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
@@ -2255,6 +2255,7 @@ pref("browser.aiwindow.enabled", false);
pref("browser.aiwindow.endpoint", "https://mlpa-prod-prod-mozilla.global.ssl.fastly.net/v1");
pref("browser.aiwindow.insights", false);
pref("browser.aiwindow.insightsLogLevel", "Warn");
+pref("browser.aiwindow.firstrun.modelChoice", "");
pref("browser.aiwindow.model", "");
// Block insecure active content on https pages
diff --git a/browser/components/aiwindow/ui/assets/model-choice-1.svg b/browser/components/aiwindow/ui/assets/model-choice-1.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at https://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="m73 40-15-1-1-1 15-21 1-2-19 5-14 24 1 1h14q3 1 2 2L31 86q1 1 2-1l41-41q2-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="m54 20 19-5-1-1H57z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="m54 20 19-5-1-1H57z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="M57 14H44l10 6z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="m55 46-14-1-1-1 14-24-10-6-1 1-17 34 2 4h16v1L30 85l1 1 26-39z" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="20" x2="75" y1="21" y2="72" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="b" x1="42" x2="97" y1="-3" y2="48" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="46" x2="103" y1="2" y2="52" gradientUnits="userSpaceOnUse"><stop stop-color="#f942ff"/><stop offset="0" stop-color="#cf3aff"/><stop offset="1" stop-color="#6625ff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="d" x1="37" x2="92" y1="2" y2="53" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="48" x2="89" y1="11" y2="68" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="42" x2="99" y1="6" y2="57" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cf3aff"/><stop offset="1" stop-color="#6625ff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="24" x2="65" y1="28" y2="85" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient></defs></svg>
+\ No newline at end of file
diff --git a/browser/components/aiwindow/ui/assets/model-choice-2.svg b/browser/components/aiwindow/ui/assets/model-choice-2.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at https://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="M52 43s23-1 38 22l-7-2s10 5 14 25c-2-4-11-16-22-17q2 0 5 8h-1a79 79 0 0 0-30-16c-10-2 3-20 3-20" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="m5 36 17 14-5 22 18-11 19 11-5-22 17-14-22-2-9-20-8 21z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="M22 50 5 36l22-2 8-20-1-2-1 1-9 18-19 3a2 2 0 0 0-2 4l14 14-3 19 1 2 1-1z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="M22 50 5 36l22-2 8-20-1-2-1 1-9 18-19 3a2 2 0 0 0-2 4l14 14-3 19 1 2 1-1z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="m66 34-19-4-10-17-1-1-1 2 9 20 22 2-17 15 5 21-19-11-19 11v2h2l17-9 18 9q4 1 3-3l-3-19 14-14q3-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="m66 34-19-4-10-17-1-1-1 2 9 20 22 2-17 15 5 21-19-11-19 11v2h2l17-9 18 9q4 1 3-3l-3-19 14-14q3-3-1-4" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#h)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#i)" d="M36 12h-2l1 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#j)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#k)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#l)" d="m15 73 1 1 1-2z" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="94" x2="36" y1="71" y2="50" gradientUnits="userSpaceOnUse"><stop stop-color="#ffeb49"/><stop offset="1" stop-color="#f60"/><stop offset="1" stop-color="#d22232"/><stop offset="1" stop-color="#be0449"/></linearGradient><linearGradient id="b" x1="10" x2="90" y1="22" y2="103" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="10" x2="90" y1="22" y2="103" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="28" x2="108" y1="5" y2="85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="23" x2="47" y1="26" y2="63" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="28" x2="108" y1="5" y2="85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="i" x1="38" x2="62" y1="16" y2="53" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="j" x1="-12" x2="68" y1="44" y2="125" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="l" x1="-4" x2="21" y1="44" y2="80" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#d33aff"/><stop offset="0" stop-color="#9f30ff"/><stop offset="0" stop-color="#7528ff"/><stop offset="1" stop-color="#5421ff"/><stop offset="1" stop-color="#3c1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><radialGradient id="d" cx="0" cy="0" r="1" gradientTransform="matrix(63.9273 0 0 63.9272 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient><radialGradient id="h" cx="0" cy="0" r="1" gradientTransform="matrix(63.9273 0 0 63.9272 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient><radialGradient id="k" cx="0" cy="0" r="1" gradientTransform="matrix(63.9272 0 0 63.9273 11 49)" gradientUnits="userSpaceOnUse"><stop stop-color="#e552fd"/><stop offset="0" stop-color="#e850fd"/><stop offset="0" stop-color="#f248fe"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f641ff"/><stop offset="0" stop-color="#ec40ff"/><stop offset="1" stop-color="#dc3cff"/><stop offset="1" stop-color="#c538ff"/><stop offset="1" stop-color="#a832ff"/><stop offset="1" stop-color="#832bff"/><stop offset="1" stop-color="#5922ff"/><stop offset="1" stop-color="#2919ff"/></radialGradient></defs></svg>
+\ No newline at end of file
diff --git a/browser/components/aiwindow/ui/assets/model-choice-3.svg b/browser/components/aiwindow/ui/assets/model-choice-3.svg
@@ -0,0 +1,4 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at https://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" fill="none" viewBox="0 0 100 100"><path fill="url(#a)" d="m19 44-3 3-1 2c0 9 27 8 29 8q4 0 2 2c-4 6-28 6-23 18 3 5 16 5 17 7 1 5-15 0-19 15h1q6-4 13-3c7 0 17 0 21-6l1-3c0-9-23-8-15-16 7-4 21-6 22-13 0-15-52 1-45-13" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#b)" d="M22 41v4l13 1h4l-1-2 3-5q-3 1-5-2c-3-4 1-7 1-7L81 6 36 30s-4 1-6-1l-2-4-1 2-8 12z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#c)" d="m22 41-3-2-2 3q-1 2 1 3h4z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#d)" d="m22 41-3-2-2 3q-1 2 1 3h4z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#e)" d="m41 39-2 5v2l4-1 37-20 4-5 1-3v-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#f)" d="m41 39-2 5v2l4-1 37-20 4-5 1-3v-2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#g)" d="M30 29q5 2 6 1L81 6h-1l-6-4h-4L31 23l-3 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#h)" d="M30 29q5 2 6 1L81 6h-1l-6-4h-4L31 23l-3 2z" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#i)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#j)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#k)" d="M36 37q2 3 5 2l1-2 43-23v-2l-4-6-44 24s-4 3-1 7" transform="matrix(.8 0 0 .8 10 10)"/><path fill="url(#l)" d="m19 44-3 3-1 2c0 9 27 8 29 8q4 0 2 2c-4 6-28 6-23 18 3 5 16 5 17 7 1 5-15 0-19 15h1q6-4 13-3c7 0 17 0 21-6l1-3c0-9-23-8-15-16 7-4 21-6 22-13 0-15-52 1-45-13" transform="matrix(.8 0 0 .8 10 10)"/><defs><linearGradient id="a" x1="39" x2="39" y1="44" y2="98" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f441ff"/><stop offset="0" stop-color="#ac33ff"/><stop offset="1" stop-color="#7428ff"/><stop offset="1" stop-color="#4b20ff"/><stop offset="1" stop-color="#321bff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="b" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="c" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="d" x1="18" x2="23" y1="39" y2="45" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="e" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="f" x1="57" x2="69" y1="22" y2="45" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="0" stop-color="#7127ff"/><stop offset="0" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="g" x1="56" x2="68" y1="20" y2="53" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="h" x1="53" x2="63" y1="10" y2="62" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="1" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="i" x1="58" x2="70" y1="19" y2="52" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="j" x1="60" x2="72" y1="18" y2="51" gradientUnits="userSpaceOnUse"><stop stop-color="#e46deb"/><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="1" stop-color="#7127ff"/><stop offset="1" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="k" x1="60" x2="72" y1="20" y2="44" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#cb39ff"/><stop offset="0" stop-color="#9a2fff"/><stop offset="0" stop-color="#7127ff"/><stop offset="0" stop-color="#5221ff"/><stop offset="1" stop-color="#3b1dff"/><stop offset="1" stop-color="#2e1aff"/><stop offset="1" stop-color="#2919ff"/></linearGradient><linearGradient id="l" x1="30" x2="96" y1="-49" y2="114" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f942ff"/><stop offset="0" stop-color="#f441ff"/><stop offset="0" stop-color="#ac33ff"/><stop offset="1" stop-color="#7428ff"/><stop offset="1" stop-color="#4b20ff"/><stop offset="1" stop-color="#321bff"/><stop offset="1" stop-color="#2919ff"/></linearGradient></defs></svg>
+\ No newline at end of file
diff --git a/browser/components/aiwindow/ui/content/firstrun.css b/browser/components/aiwindow/ui/content/firstrun.css
@@ -1,7 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-
+:root {
+ --background-color-canvas: transparent;
+}
@keyframes springUp {
from {
opacity: 0;
@@ -14,29 +16,140 @@
}
#multi-stage-message-root {
- #mainContentHeader {
- opacity: 0;
- animation: springUp 0.5s ease-out forwards;
- animation-delay: 0.3s;
- background: linear-gradient(91deg, #7630c0 22.04%, #5c66ee 78.7%);
- -webkit-background-clip: text;
- background-clip: text;
- -webkit-text-fill-color: transparent;
- }
+ --bg-white: light-dark(#fff, #fff);
+ --bg-transparent: transparent;
+ --tile-border-color: #f1e7f8;
+ --shadow-color: rgb(59 34 121);
+
+ --gradient-button: linear-gradient(97deg, #8341ca -31.39%, #656fff 90.52%);
+ --gradient-selected-border: linear-gradient(117deg, #321bfd -17.87%, #cf30e2 52.93%, #f90 89.02%, #f5c451 109.44%);
.main-content,
.section-main,
- .screen,
.dialog-initial,
.onboardingContainer {
box-shadow: none;
}
.onboardingContainer .screen[pos="center"] {
- background-color: transparent;
+ background-color: var(--bg-transparent);
+ }
+
+ #mainContentHeader {
+ /* stylelint-disable-next-line -- using linear gradient for text effect */
+ background: linear-gradient(91deg, #7630c0 22.04%, #5c66ee 78.7%);
+ background-clip: text;
+ /* stylelint-disable-next-line -- transparent needed for gradient text effect */
+ color: var(--bg-transparent);
}
- button.primary {
- display: none;
+ .screen.AI_WINDOW_INTRO {
+ #mainContentHeader {
+ opacity: 0;
+ animation: springUp 0.3s ease-in forwards;
+ animation-delay: 0.3s;
+ }
+ }
+
+ .screen.AI_WINDOW_CHOOSE_MODEL {
+ h2,
+ p {
+ letter-spacing: 0.3px;
+ line-height: normal;
+ }
+
+ .welcome-text h2 {
+ opacity: 0.8;
+ margin-top: var(--space-medium);
+ }
+
+ button.primary {
+ width: calc(var(--size-item-large) * 7);
+ height: var(--size-item-xlarge);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: var(--space-small);
+ padding: var(--space-xsmall) var(--space-large);
+ margin: 0 auto;
+ border: var(--border-width) solid var(--border-color-transparent);
+ border-radius: var(--border-radius-medium);
+ background: var(--gradient-button);
+ color: var(--button-text-color-primary);
+ text-align: center;
+ font-size: var(--button-font-size);
+ font-weight: var(--button-font-weight);
+ letter-spacing: -0.3px;
+ cursor: pointer;
+ }
+
+ &:not(:has(.icon.selected)) button.primary {
+ opacity: 0.5;
+ pointer-events: none;
+ cursor: default;
+ }
+ }
+
+ .tiles-single-select-section.single-select {
+ gap: var(--space-large);
+ margin-top: calc(var(--space-xsmall) * 8);
+ margin-bottom: var(--space-xxlarge);
+
+ .select-item {
+ width: calc(var(--size-item-large) * 7);
+ height: calc(var(--size-item-medium) * 11);
+ padding-block: calc(var(--space-xsmall) * 9) 0;
+ /* stylelint-disable-next-line -- custom border color per Figma design */
+ border: var(--border-width) solid var(--tile-border-color);
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ align-items: center;
+ gap: 0;
+ padding-inline: var(--space-medium);
+ box-sizing: border-box;
+ border-radius: var(--border-radius-large);
+ /* stylelint-disable-next-line -- using white for consistent background */
+ background: color-mix(in srgb, var(--bg-white) 60%, var(--bg-transparent));
+
+ .label-text {
+ margin-top: calc(var(--space-xsmall) * 5);
+ margin-bottom: 0;
+ letter-spacing: 0.5px;
+ opacity: 0.8;
+ line-height: normal;
+ }
+
+ .body-text {
+ opacity: 0.8;
+ line-height: normal;
+ }
+
+ .icon {
+ width: calc(var(--size-item-xlarge) * 2);
+ height: calc(var(--size-item-xlarge) * 2);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-shrink: 0;
+ }
+
+ &:hover:not(:has(.selected)) {
+ /* stylelint-disable-next-line -- using white for hover state */
+ background: var(--bg-white);
+ cursor: pointer;
+ }
+
+ &:has(.selected) {
+ border: calc(var(--border-width) * 2) solid var(--border-color-transparent);
+ background:
+ linear-gradient(#fff, #fff) padding-box,
+ var(--gradient-selected-border) border-box;
+ /* stylelint-disable-next-line -- custom shadow color per Figma design */
+ box-shadow:
+ 0 3px 16px 0 color-mix(in srgb, var(--shadow-color) 12%, var(--bg-transparent)),
+ 0 1px 2px 0 color-mix(in srgb, var(--shadow-color) 20%, var(--bg-transparent));
+ }
+ }
}
}
diff --git a/browser/components/aiwindow/ui/content/firstrun.js b/browser/components/aiwindow/ui/content/firstrun.js
@@ -2,19 +2,28 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-const SMART_ASSIST_URL = "chrome://browser/content/genai/smartAssist.html";
+const lazy = {};
+const { topChromeWindow } = window.browsingContext;
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ AboutWelcomeParent: "resource:///actors/AboutWelcomeParent.sys.mjs",
+ AIWindow:
+ "moz-src:///browser/components/aiwindow/ui/modules/AIWindow.sys.mjs",
+});
+const MODEL_PREF = "browser.aiwindow.firstrun.modelChoice";
+const BRAND_DARK_PURPLE = "#210340";
const AI_WINDOW_CONFIG = {
id: "AI_WINDOW_WELCOME",
template: "spotlight",
transitions: true,
modal: "tab",
- backdrop:
- "radial-gradient(circle at 50% 90%, rgba(253, 244, 243, 1) 0%, rgba(253, 244, 243, 1) 30%, rgba(216, 202, 247, 1) 100%)",
+ backdrop: "transparent",
screens: [
{
- id: "AW_AI_WINDOW_WELCOME",
+ id: "AI_WINDOW_INTRO",
auto_advance: "primary_button",
+ force_hide_steps_indicator: true,
content: {
fullscreen: true,
hide_secondary_section: "responsive",
@@ -25,13 +34,12 @@ const AI_WINDOW_CONFIG = {
overflow: "hidden",
},
title: {
- fontWeight: 400,
+ fontWeight: 350,
fontSize: "39px",
+ letterSpacing: 0,
lineHeight: "56px",
textAlign: "center",
string_id: "aiwindow-firstrun-title",
- color: "transparent",
- letterSpacing: "0px",
},
primary_button: {
label: "",
@@ -41,16 +49,151 @@ const AI_WINDOW_CONFIG = {
},
},
},
+ {
+ id: "AI_WINDOW_CHOOSE_MODEL",
+ force_hide_steps_indicator: true,
+ content: {
+ position: "center",
+ background: "transparent",
+ screen_style: {
+ width: "750px",
+ },
+ title: {
+ string_id: "aiwindow-firstrun-model-title",
+ fontSize: "40px",
+ fontWeight: "350",
+ letterSpacing: 0,
+ lineHeight: "normal",
+ },
+ subtitle: {
+ string_id: "aiwindow-firstrun-model-subtitle",
+ fontSize: "17px",
+ fontWeight: 320,
+ color: BRAND_DARK_PURPLE,
+ },
+ tiles: {
+ type: "single-select",
+ selected: "none",
+ autoTrigger: false,
+ action: {
+ picker: "<event>",
+ },
+ data: [
+ {
+ id: "model_1",
+ label: {
+ string_id: "aiwindow-firstrun-model-fast-label",
+ fontSize: "20px",
+ fontWeight: 613,
+ color: BRAND_DARK_PURPLE,
+ },
+ icon: {
+ background:
+ 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-1.svg")',
+ },
+ body: {
+ string_id: "aiwindow-firstrun-model-fast-body",
+ color: BRAND_DARK_PURPLE,
+ fontSize: "15px",
+ fontWeight: 320,
+ },
+ action: {
+ type: "SET_PREF",
+ data: {
+ pref: {
+ name: MODEL_PREF,
+ value: "1",
+ },
+ },
+ },
+ },
+ {
+ id: "model_2",
+ label: {
+ string_id: "aiwindow-firstrun-model-allpurpose-label",
+ fontSize: "20px",
+ fontWeight: 613,
+ color: BRAND_DARK_PURPLE,
+ },
+ icon: {
+ background:
+ 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-2.svg")',
+ },
+ body: {
+ string_id: "aiwindow-firstrun-model-allpurpose-body",
+ color: BRAND_DARK_PURPLE,
+ fontSize: "15px",
+ fontWeight: 320,
+ },
+ action: {
+ type: "SET_PREF",
+ data: {
+ pref: {
+ name: MODEL_PREF,
+ value: "2",
+ },
+ },
+ },
+ },
+ {
+ id: "model_3",
+ label: {
+ string_id: "aiwindow-firstrun-model-personal-label",
+ fontSize: "20px",
+ fontWeight: 613,
+ color: BRAND_DARK_PURPLE,
+ },
+ icon: {
+ background:
+ 'center / contain no-repeat url("chrome://browser/content/aiwindow/assets/model-choice-3.svg")',
+ },
+ body: {
+ string_id: "aiwindow-firstrun-model-personal-body",
+ color: BRAND_DARK_PURPLE,
+ fontSize: "15px",
+ fontWeight: 320,
+ },
+ action: {
+ type: "SET_PREF",
+ data: {
+ pref: {
+ name: MODEL_PREF,
+ value: "3",
+ },
+ },
+ },
+ },
+ ],
+ },
+ primary_button: {
+ label: {
+ string_id: "aiwindow-firstrun-button",
+ },
+ action: {
+ navigate: true,
+ },
+ },
+ },
+ },
],
};
function renderFirstRun() {
+ const AWParent = new lazy.AboutWelcomeParent();
+ const receive = name => data =>
+ AWParent.onContentMessage(
+ `AWPage:${name}`,
+ data,
+ topChromeWindow.gBrowser.selectedBrowser
+ );
+
window.AWGetFeatureConfig = () => AI_WINDOW_CONFIG;
window.AWEvaluateScreenTargeting = screens => screens;
window.AWGetSelectedTheme = () => ({});
window.AWGetInstalledAddons = () => [];
+ window.AWSendToParent = (name, data) => receive(name)(data);
window.AWFinish = () => {
- window.location.href = SMART_ASSIST_URL;
+ window.location.href = lazy.AIWindow.newTabURL;
};
const script = document.createElement("script");
diff --git a/browser/components/aiwindow/ui/jar.mn b/browser/components/aiwindow/ui/jar.mn
@@ -14,6 +14,9 @@ browser.jar:
content/browser/aiwindow/components/ai-window.css (components/ai-window/ai-window.css)
content/browser/aiwindow/components/input-cta.css (components/input-cta/input-cta.css)
content/browser/aiwindow/components/input-cta.mjs (components/input-cta/input-cta.mjs)
+ content/browser/aiwindow/assets/model-choice-1.svg (assets/model-choice-1.svg)
+ content/browser/aiwindow/assets/model-choice-2.svg (assets/model-choice-2.svg)
+ content/browser/aiwindow/assets/model-choice-3.svg (assets/model-choice-3.svg)
content/browser/aiwindow/firstrun.html (content/firstrun.html)
content/browser/aiwindow/firstrun.css (content/firstrun.css)
content/browser/aiwindow/firstrun.js (content/firstrun.js)
diff --git a/browser/components/aiwindow/ui/test/browser/browser_aiwindow_firstrun.js b/browser/components/aiwindow/ui/test/browser/browser_aiwindow_firstrun.js
@@ -18,16 +18,22 @@ add_task(async function test_firstrun_welcome_screen_renders() {
await SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
await ContentTaskUtils.waitForCondition(
- () => content.document.querySelector(".screen.AW_AI_WINDOW_WELCOME"),
- "Wait for the AI Window welcome screen to be rendered"
+ () => content.document.querySelector(".screen.AI_WINDOW_INTRO"),
+ "Wait for the AI Window intro screen to be rendered"
);
- const welcomeScreen = content.document.querySelector(
- ".screen.AW_AI_WINDOW_WELCOME"
+ const introScreen = content.document.querySelector(
+ ".screen.AI_WINDOW_INTRO"
);
Assert.ok(
- welcomeScreen,
- "The welcome screen with class 'screen AW_AI_WINDOW_WELCOME' should be present"
+ introScreen,
+ "The intro screen with class 'screen AI_WINDOW_INTRO' should be present"
+ );
+
+ await ContentTaskUtils.waitForCondition(
+ () => content.document.querySelector(".screen.AI_WINDOW_CHOOSE_MODEL"),
+ "Wait for the AI Window choose model screen to be rendered",
+ 25000
);
});
diff --git a/browser/locales-preview/aiWindow.ftl b/browser/locales-preview/aiWindow.ftl
@@ -25,3 +25,12 @@ aiwindow-input-cta-label-navigate = Navigate
## Firstrun onboarding
aiwindow-firstrun-title = Welcome to Smart Window
+aiwindow-firstrun-model-title = Pick a model to start
+aiwindow-firstrun-model-subtitle = Switch anytime to find your best fit.
+aiwindow-firstrun-model-fast-label = Fastest
+aiwindow-firstrun-model-fast-body = Best for quick answers to everyday questions
+aiwindow-firstrun-model-allpurpose-label = All-purpose
+aiwindow-firstrun-model-allpurpose-body = Best for a variety of quick and complex features
+aiwindow-firstrun-model-personal-label = Personalization
+aiwindow-firstrun-model-personal-body = Best for learning with you
+aiwindow-firstrun-button = Let’s go
diff --git a/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs b/toolkit/components/messaging-system/lib/SpecialMessageActions.sys.mjs
@@ -248,6 +248,7 @@ export const SpecialMessageActions = {
// Array of prefs that are allowed to be edited by SET_PREF
const allowedPrefs = [
"browser.aboutwelcome.didSeeFinalScreen",
+ "browser.aiwindow.firstrun.modelChoice",
"browser.crashReports.unsubmittedCheck.autoSubmit2",
"browser.dataFeatureRecommendations.enabled",
"browser.ipProtection.enabled",