diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5cd9cd53a..7a5ebc971 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,6 +26,11 @@ on: required: true type: "boolean" default: false + disable-pgo: + description: "Build without PGO (skips the profile generation stages)" + required: false + type: "boolean" + default: false workflow_call: inputs: create_release: @@ -48,6 +53,11 @@ on: required: true type: "boolean" default: false + disable-pgo: + description: "Build without PGO (skips the profile generation stages)" + required: false + type: "boolean" + default: false jobs: buildid: @@ -73,6 +83,7 @@ jobs: echo "create_release: ${{ inputs.create_release }}" echo "update_version: ${{ inputs.update_version }}" echo "use sccache: ${{ inputs.use-sccache }}" + echo "disable-pgo: ${{ inputs.disable-pgo }}" echo "update_branch: ${{ inputs.update_branch }}" echo "GITHUB_REPOSITORY: ${{ github.repository }}" echo "GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}" @@ -102,14 +113,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Download aws-cli - if: ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: ${{ inputs.update_branch == 'release' }} run: | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install --update - name: Start self-hosted runner - if: ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: ${{ inputs.update_branch == 'release' }} run: | echo "Starting self-hosted runner" echo "${{ secrets.SELF_HOSTED_RUNNER_START_SCRIPT }}" | base64 -d > start.sh @@ -117,7 +128,7 @@ jobs: bash ./start.sh - name: Remove self-hosted runner script - if: always() && ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: always() && ${{ inputs.update_branch == 'release' }} run: | echo "Removing self-hosted runner script" rm start.sh || true @@ -280,6 +291,7 @@ jobs: windows-step-1: name: Windows build step 1 (PGO build) uses: ./.github/workflows/windows-release-build.yml + if: ${{ !inputs.disable-pgo }} needs: [build-data, buildid] permissions: contents: write @@ -295,6 +307,7 @@ jobs: windows-step-2: name: Windows build step 2 (Generate profile data) uses: ./.github/workflows/windows-profile-build.yml + if: ${{ !inputs.disable-pgo }} permissions: contents: write secrets: inherit @@ -310,10 +323,13 @@ jobs: permissions: contents: write secrets: inherit + # windows-step-2 is skipped when PGO is disabled, so don't inherit its skip + if: ${{ !failure() && !cancelled() }} needs: [build-data, windows-step-2, start-self-host, buildid] with: build-version: ${{ needs.build-data.outputs.version }} generate-pgo: false + disable-pgo: ${{ inputs.disable-pgo }} release-branch: ${{ inputs.update_branch }} MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}} use-sccache: ${{ inputs.use-sccache }} @@ -330,10 +346,12 @@ jobs: release-branch: ${{ inputs.update_branch }} MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}} use-sccache: ${{ inputs.use-sccache }} + disable-pgo: ${{ inputs.disable-pgo }} mac-step-1: name: macOS build step 1 (PGO build) uses: ./.github/workflows/macos-release-build.yml + if: ${{ !inputs.disable-pgo }} needs: [build-data, buildid] permissions: contents: write @@ -348,6 +366,7 @@ jobs: mac-step-2: name: macOS build step 2 (Generate profile data) uses: ./.github/workflows/macos-profile-build.yml + if: ${{ !inputs.disable-pgo }} permissions: contents: write secrets: inherit @@ -362,10 +381,13 @@ jobs: permissions: contents: write secrets: inherit + # mac-step-2 is skipped when PGO is disabled, so don't inherit its skip + if: ${{ !failure() && !cancelled() }} needs: [build-data, mac-step-2, start-self-host, buildid] with: build-version: ${{ needs.build-data.outputs.version }} generate-pgo: false + disable-pgo: ${{ inputs.disable-pgo }} release-branch: ${{ inputs.update_branch }} MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}} use-sccache: ${{ inputs.use-sccache }} @@ -470,14 +492,14 @@ jobs: if: always() steps: - name: Download aws-cli - if: ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: ${{ inputs.update_branch == 'release' }} run: | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install --update - name: Stop self-hosted runner - if: ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: ${{ inputs.update_branch == 'release' }} run: | echo "Stopping self-hosted runner" echo "${{ secrets.SELF_HOSTED_RUNNER_STOP_SCRIPT }}" | base64 -d > stop.sh @@ -485,13 +507,12 @@ jobs: bash ./stop.sh > /dev/null - name: Remove self-hosted runner script - if: always() && ${{ inputs.create_release && inputs.update_branch == 'release' }} + if: always() && ${{ inputs.update_branch == 'release' }} run: | echo "Removing self-hosted runner script" rm stop.sh || true release: - if: ${{ inputs.create_release || inputs.update_branch == 'twilight' }} permissions: write-all name: Release needs: @@ -585,6 +606,7 @@ jobs: - name: Commit uses: stefanzweifel/git-auto-commit-action@v5 + if: ${{ inputs.create_release || inputs.update_branch == 'twilight' }} with: commit_message: 🚀 Update update manifests commit_user_name: Zen Browser Robot @@ -628,9 +650,22 @@ jobs: env: GITHUB_REPOSITORY: ${{ github.repository }} + - name: Upload signed MAR files to workflow artifacts + if: ${{ inputs.update_branch == 'release' && !inputs.create_release }} + uses: actions/upload-artifact@v4 + with: + retention-days: 5 + name: signed-mar-files + path: | + ./linux.mar/* + ./linux-aarch64.mar/* + ./.github/workflows/object/windows-x64-signed-x86_64/windows.mar + ./.github/workflows/object/windows-x64-signed-arm64/windows-arm64.mar + ./macos.mar/* + - name: Release uses: softprops/action-gh-release@v2.2.2 - if: ${{ inputs.update_branch == 'release' }} + if: ${{ inputs.update_branch == 'release' && inputs.create_release }} with: token: ${{ secrets.DEPLOY_KEY }} tag_name: ${{ needs.build-data.outputs.version }} diff --git a/.github/workflows/linux-release-build.yml b/.github/workflows/linux-release-build.yml index baaea9dbf..4841eea82 100644 --- a/.github/workflows/linux-release-build.yml +++ b/.github/workflows/linux-release-build.yml @@ -20,6 +20,11 @@ on: required: true type: boolean default: false + disable-pgo: + description: "Build without PGO at all" + required: false + type: boolean + default: false jobs: build-linux: @@ -122,7 +127,7 @@ jobs: cd .. - name: Build (PGO stage 1 - generate) - if: ${{ matrix.arch == 'x86_64' }} + if: ${{ matrix.arch == 'x86_64' && !inputs.disable-pgo }} env: SURFER_COMPAT: ${{ matrix.arch }} ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }} @@ -139,7 +144,7 @@ jobs: bash .github/workflows/src/release-build.sh - name: Generate PGO profile data - if: ${{ matrix.arch == 'x86_64' }} + if: ${{ matrix.arch == 'x86_64' && !inputs.disable-pgo }} run: | set -x export DISPLAY=:2 @@ -157,6 +162,7 @@ jobs: env: SURFER_COMPAT: ${{ matrix.arch }} ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }} + ZEN_GA_DISABLE_PGO: ${{ inputs.disable-pgo && '1' || '' }} ZEN_SAFEBROWSING_API_KEY: ${{ secrets.ZEN_SAFEBROWSING_API_KEY }} ZEN_MOZILLA_API_KEY: ${{ secrets.ZEN_MOZILLA_API_KEY }} ZEN_GOOGLE_LOCATION_SERVICE_API_KEY: ${{ secrets.ZEN_GOOGLE_LOCATION_SERVICE_API_KEY }} diff --git a/.github/workflows/macos-release-build.yml b/.github/workflows/macos-release-build.yml index 0423c566e..72d7f2ee9 100644 --- a/.github/workflows/macos-release-build.yml +++ b/.github/workflows/macos-release-build.yml @@ -10,6 +10,11 @@ on: required: true type: boolean default: false + disable-pgo: + description: "Build without PGO at all" + required: false + type: boolean + default: false build-version: description: "The version to build" required: true @@ -140,13 +145,13 @@ jobs: - name: Download artifact (if use profdata) uses: actions/download-artifact@v4 - if: ${{ !inputs.generate-pgo }} + if: ${{ !inputs.generate-pgo && !inputs.disable-pgo }} with: path: ~/artifact name: macos-profdata-${{ matrix.arch }} - name: Show artifact info - if: ${{ !inputs.generate-pgo }} + if: ${{ !inputs.generate-pgo && !inputs.disable-pgo }} run: | ls ~/artifact ls ~/artifact/en-US.log @@ -166,6 +171,9 @@ jobs: if test ${{ inputs.generate-pgo }} = true; then export ZEN_GA_GENERATE_PROFILE=1 fi + if test ${{ inputs.disable-pgo }} = true; then + export ZEN_GA_DISABLE_PGO=1 + fi if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then export MOZ_BUILD_DATE=${{ inputs.MOZ_BUILD_DATE }} fi diff --git a/.github/workflows/windows-release-build.yml b/.github/workflows/windows-release-build.yml index e27d50589..970636be3 100644 --- a/.github/workflows/windows-release-build.yml +++ b/.github/workflows/windows-release-build.yml @@ -10,6 +10,11 @@ on: required: true type: boolean default: false + disable-pgo: + description: "Build without PGO at all" + required: false + type: boolean + default: false build-version: description: "The version to build" required: true @@ -215,13 +220,13 @@ jobs: - name: Download artifact (if use profdata) uses: actions/download-artifact@v4 - if: ${{ !inputs.generate-pgo && matrix.arch == 'x86_64' }} + if: ${{ !inputs.generate-pgo && !inputs.disable-pgo && matrix.arch == 'x86_64' }} with: path: ~/artifact name: windows-profdata-${{ matrix.arch == 'aarch64' && 'arm64' || matrix.arch }} - name: Show artifact info - if: ${{ !inputs.generate-pgo && matrix.arch == 'x86_64' }} + if: ${{ !inputs.generate-pgo && !inputs.disable-pgo && matrix.arch == 'x86_64' }} run: | ls ~/artifact ls ~/artifact/en-US.log @@ -246,6 +251,9 @@ jobs: if test ${{ inputs.generate-pgo }} = true; then export ZEN_GA_GENERATE_PROFILE=1 fi + if test ${{ inputs.disable-pgo }} = true; then + export ZEN_GA_DISABLE_PGO=1 + fi if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then export MOZ_BUILD_DATE=${{ inputs.MOZ_BUILD_DATE }} fi diff --git a/README.md b/README.md index 434e58315..45db3aa51 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ Zen is a firefox-based browser with the aim of pushing your productivity to a ne ### Firefox Versions -- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `154.0.1`! -- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 154.0.1`! +- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `155.0`! +- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 155.0`! ### Contributing diff --git a/build/firefox-cache/l10n-last-commit-hash b/build/firefox-cache/l10n-last-commit-hash index 2dbfec531..24e25043a 100644 --- a/build/firefox-cache/l10n-last-commit-hash +++ b/build/firefox-cache/l10n-last-commit-hash @@ -1 +1 @@ -bf4b57fd7fe94054457be7018e8e7beaf754c520 \ No newline at end of file +20e5abbb642ab21d943bc1261864d9c531ba421a \ No newline at end of file diff --git a/locales/en-US/browser/browser/preferences/zen-preferences.ftl b/locales/en-US/browser/browser/preferences/zen-preferences.ftl index 473bfb740..bb31d6c47 100644 --- a/locales/en-US/browser/browser/preferences/zen-preferences.ftl +++ b/locales/en-US/browser/browser/preferences/zen-preferences.ftl @@ -64,6 +64,10 @@ zen-tabs-select-recently-used-on-close = zen-tabs-close-on-back-with-no-history = .label = Close tab and switch to its owner tab (or most recently used tab) when going back with no history +zen-settings-workspaces-sync = + .label = Sync your sidebar across devices + .description = Keep your workspaces, pinned tabs and folders in sync on all your devices through your Mozilla account. + zen-settings-workspaces-sync-unpinned-tabs = .label = Sync only pinned tabs in workspaces diff --git a/locales/en-US/browser/browser/zen-welcome.ftl b/locales/en-US/browser/browser/zen-welcome.ftl index 1967595a9..c351f271a 100644 --- a/locales/en-US/browser/browser/zen-welcome.ftl +++ b/locales/en-US/browser/browser/zen-welcome.ftl @@ -5,29 +5,28 @@ zen-welcome-title-line1 = Welcome to zen-welcome-title-line2 = a calmer internet -zen-welcome-import-title = A Fresh Start, Same Bookmarks -zen-welcome-import-description-1 = Your bookmarks, history, and passwords are like a trail of breadcrumbs through the internet—don’t leave them behind! -zen-welcome-import-description-2 = Easily bring them over from another browser and pick up right where you left off. -zen-welcome-import-button = Import now +zen-welcome-back = Back +zen-welcome-skip = Skip for now -zen-welcome-set-default-browser = Set { -brand-short-name } as your default browser -zen-welcome-dont-set-default-browser = DON’T set { -brand-short-name } as your default browser +zen-welcome-import-title = Bring your stuff along. +zen-welcome-import-description = Import your bookmarks, history and passwords from another browser and pick up right where you left off. +zen-welcome-import-yes = YES, import from another browser. +zen-welcome-import-no = NO, start fresh. -zen-welcome-initial-essentials-title = Your Key Tabs, Always Within Reach -zen-welcome-initial-essentials-description-1 = Keep your most important tabs easily accessible and always at hand, no matter how many you open. -zen-welcome-initial-essentials-description-2 = Essential tabs are always visible, no matter what workspace you are in. +zen-welcome-default-browser-title = Make { -brand-short-name } your default? +zen-welcome-default-browser-description = Links from other apps will open in { -brand-short-name }. You can always change this later. +zen-welcome-set-default-browser = YES, make { -brand-short-name } default. +zen-welcome-dont-set-default-browser = NO, still exploring my options. -zen-welcome-workspace-colors-title = Your Workspaces, Your Colors -zen-welcome-workspace-colors-description = Personalize your browser by giving each workspace its own unique color identity. - -zen-welcome-start-browsing-title = All set?
- Let’s get rolling! -zen-welcome-start-browsing-description-1 = You’re all set up and ready to go. Click the button below to start browsing with { -brand-short-name }. -zen-welcome-start-browsing = Dive in! - -zen-welcome-default-search-title = Your Default Search Engine +zen-welcome-default-search-title = Pick your search engine. zen-welcome-default-search-description = Choose your default search engine. You can always change it later! -zen-welcome-skip-button = Skip +zen-welcome-essentials-title = Choose the apps you use most. +zen-welcome-essentials-description = Select your favorite apps to keep them handy in your sidebar. -zen-welcome-finished = Your Zen has been set up correctly! +zen-welcome-workspace-colors-title = Your space, your colors. +zen-welcome-workspace-colors-description = Personalize your browser by giving each space its own unique color identity. + +zen-welcome-start-browsing-title = All set? Let’s get rolling! +zen-welcome-start-browsing-description-1 = You’re all set up and ready to go. Click the button below to start browsing with { -brand-short-name }. +zen-welcome-start-browsing = Dive in! diff --git a/package-lock.json b/package-lock.json index 484c33d77..7a0bc5651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@babel/preset-typescript": "^7.27.0", "@zen-browser/prettier": "^3.9.3", - "@zen-browser/surfer": "^1.14.8", + "@zen-browser/surfer": "^1.14.9", "formal-git": "^1.2.9", "globals": "^16.3.0", "husky": "^9.1.7", @@ -860,9 +860,9 @@ } }, "node_modules/@zen-browser/surfer": { - "version": "1.14.8", - "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.14.8.tgz", - "integrity": "sha512-5HHcfibwHIK5n3huhJL2TLBX2+8odj6ebCMA6U2EcUj9ROSrcz7/bjY2n5MIa9oIRL9gtV3ott0jwJj6SlapxA==", + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.14.9.tgz", + "integrity": "sha512-XbMzG4GHSRoGzKR/DkpyywcbTYemieDRD1A6qgJ8CaVDixenj/uzMhp6HXAUksRTeh1u9j3lzNcVrI99axcZLw==", "dev": true, "license": "MPL-2.0", "dependencies": { diff --git a/package.json b/package.json index c0ed6239c..9265a194b 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "devDependencies": { "@babel/preset-typescript": "^7.27.0", "@zen-browser/prettier": "^3.9.3", - "@zen-browser/surfer": "^1.14.8", + "@zen-browser/surfer": "^1.14.9", "formal-git": "^1.2.9", "globals": "^16.3.0", "husky": "^9.1.7", diff --git a/prefs/firefox/browser.yaml b/prefs/firefox/browser.yaml index cd66abc63..92032c989 100644 --- a/prefs/firefox/browser.yaml +++ b/prefs/firefox/browser.yaml @@ -95,6 +95,9 @@ - name: browser.search.widget.new value: true +- name: layout.css.corner-shape.enabled + value: true + # Disabled from https://searchfox.org/firefox-main/rev/d6bfff43852356ca98af848b4705d37f8d41856f/modules/libpref/init/StaticPrefList.yaml#2008 # Only enabled for windows, doesn't really fit inside Zen. - name: browser.startup.preXulSkeletonUI diff --git a/prefs/zen/sync.yaml b/prefs/zen/sync.yaml index 9ed0efc35..8424b23f8 100644 --- a/prefs/zen/sync.yaml +++ b/prefs/zen/sync.yaml @@ -3,13 +3,8 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. - name: services.sync.engine.spaces - value: true + value: "@cond" condition: "@IS_TWILIGHT@" -- name: services.sync.engine.spaces - value: false - locked: true - condition: "!@IS_TWILIGHT@" - - name: zen.spaces-sync.debug value: false diff --git a/src/-stylelintrc-js.patch b/src/-stylelintrc-js.patch index baadd6208..75a6e5999 100644 --- a/src/-stylelintrc-js.patch +++ b/src/-stylelintrc-js.patch @@ -1,5 +1,5 @@ diff --git a/.stylelintrc.js b/.stylelintrc.js -index b484bf6600a7e1b8ad2aed8c8b7fe5e84cc3d023..f89712e2c13dfa0bcb48e55cd3872c67f5c98dad 100644 +index b5f8245fa04ffb8fc82240261d63f893f4629f19..1b6ead24adbe69fcb5aeb95cfd3e7fa9662d89d8 100644 --- a/.stylelintrc.js +++ b/.stylelintrc.js @@ -67,7 +67,7 @@ module.exports = { @@ -11,10 +11,10 @@ index b484bf6600a7e1b8ad2aed8c8b7fe5e84cc3d023..f89712e2c13dfa0bcb48e55cd3872c67 { ignore: ["blockless-at-rules"], }, -@@ -280,7 +280,7 @@ module.exports = { - "media-query-no-invalid": null, +@@ -281,7 +281,7 @@ module.exports = { "stylelint-plugin-mozilla/media-query-no-invalid": true, "stylelint-plugin-mozilla/no-base-design-tokens": true, + "stylelint-plugin-mozilla/no-has-selector": true, - "stylelint-plugin-mozilla/use-design-tokens": true, + "stylelint-plugin-mozilla/use-design-tokens": false, }, diff --git a/src/browser/base/content/navigator-toolbox-inc-xhtml.patch b/src/browser/base/content/navigator-toolbox-inc-xhtml.patch index 38ad5946e..a9c01739c 100644 --- a/src/browser/base/content/navigator-toolbox-inc-xhtml.patch +++ b/src/browser/base/content/navigator-toolbox-inc-xhtml.patch @@ -19,7 +19,7 @@ index dd2f391096968564086911c532f696dc7ffb8ae1..c3e809a543397ab360fb83b3f61ef52d + -+ ++ + + + diff --git a/src/browser/base/content/zen-panels/site-data.inc b/src/browser/base/content/zen-panels/site-data.inc index aa95fb9f8..2e798a4da 100644 --- a/src/browser/base/content/zen-panels/site-data.inc +++ b/src/browser/base/content/zen-panels/site-data.inc @@ -15,19 +15,23 @@ mainview-with-header="true"> diff --git a/src/browser/base/content/zen-panels/theme-picker.inc b/src/browser/base/content/zen-panels/theme-picker.inc index ff059d959..7f7f0b495 100644 --- a/src/browser/base/content/zen-panels/theme-picker.inc +++ b/src/browser/base/content/zen-panels/theme-picker.inc @@ -14,14 +14,14 @@ - - - - + + + diff --git a/src/zen/boosts/zen-boosts.css b/src/zen/boosts/zen-boosts.css index 4537642f2..e255aa39e 100644 --- a/src/zen/boosts/zen-boosts.css +++ b/src/zen/boosts/zen-boosts.css @@ -194,7 +194,8 @@ body { max-height: 40px; align-items: center; background-color: var(--zen-boosts-secondary-background); - border: solid 1px var(--zen-boosts-primary-border-color); + border: solid 1px transparent; + border-bottom-color: var(--zen-boosts-primary-border-color); @media (-moz-windows-mica) { background-color: var(--zen-boosts-mica-background); diff --git a/src/zen/common/modules/ZenUIManager.mjs b/src/zen/common/modules/ZenUIManager.mjs index dbb1bd2ca..770ffbb22 100644 --- a/src/zen/common/modules/ZenUIManager.mjs +++ b/src/zen/common/modules/ZenUIManager.mjs @@ -543,6 +543,10 @@ window.gZenUIManager = { return false; } + if (document.documentElement.hasAttribute("zen-welcome-stage")) { + return false; + } + const shouldOpenURLBar = overridePreferance || (gZenVerticalTabsManager._canReplaceNewTab && @@ -864,7 +868,6 @@ window.gZenUIManager = { }, panelUIPosition(panel, anchor) { - void panel; // The alignment position of the panel is determined during the "popuppositioned" event // when the panel opens. The alignment positions help us determine in which orientation // the panel is anchored to the screen space. @@ -1348,18 +1351,21 @@ window.gZenVerticalTabsManager = { document.documentElement.removeAttribute("zen-right-side"); } - delete this._hadSidebarCollapse; - if (isSidebarExpanded) { - this._hadSidebarCollapse = !document.documentElement.hasAttribute( - "zen-sidebar-expanded" - ); - this.navigatorToolbox.setAttribute("zen-sidebar-expanded", "true"); - document.documentElement.setAttribute("zen-sidebar-expanded", "true"); - gBrowser.tabContainer.setAttribute("expanded", "true"); - } else { - this.navigatorToolbox.removeAttribute("zen-sidebar-expanded"); - document.documentElement.removeAttribute("zen-sidebar-expanded"); - gBrowser.tabContainer.removeAttribute("expanded"); + const wasSidebarExpanded = document.documentElement.hasAttribute( + "zen-sidebar-expanded" + ); + if (isSidebarExpanded !== wasSidebarExpanded) { + delete this._hadSidebarCollapse; + if (isSidebarExpanded) { + this._hadSidebarCollapse = true; + this.navigatorToolbox.setAttribute("zen-sidebar-expanded", "true"); + document.documentElement.setAttribute("zen-sidebar-expanded", "true"); + gBrowser.tabContainer.setAttribute("expanded", "true"); + } else { + this.navigatorToolbox.removeAttribute("zen-sidebar-expanded"); + document.documentElement.removeAttribute("zen-sidebar-expanded"); + gBrowser.tabContainer.removeAttribute("expanded"); + } } const appContentNavbarContaienr = document.getElementById( diff --git a/src/zen/common/styles/zen-buttons.css b/src/zen/common/styles/zen-buttons.css index e0f614cf6..0f6bbae5c 100644 --- a/src/zen/common/styles/zen-buttons.css +++ b/src/zen/common/styles/zen-buttons.css @@ -27,7 +27,7 @@ dialog::part(dialog-button) { position: relative; border: none; - border-radius: 10px; + border-radius: calc(10px * var(--zen-squircle-value)); } @media (-moz-platform: macos) { diff --git a/src/zen/common/styles/zen-omnibox.css b/src/zen/common/styles/zen-omnibox.css index 542e67de7..77ec73bf3 100644 --- a/src/zen/common/styles/zen-omnibox.css +++ b/src/zen/common/styles/zen-omnibox.css @@ -18,11 +18,11 @@ .urlbar { --urlbarview-separator-color: light-dark(hsl(0, 0%, 80%), hsl(0, 0%, 20%)); - --urlbarview-background-color-hover: var(--toolbarbutton-hover-background); + --urlbarview-background-color-hover: var(--toolbarbutton-background-color-hover); border-radius: calc(var(--toolbarbutton-border-radius) - 2px); - height: var(--urlbar-height); --urlbarView-results-padding: 10px !important; --urlbar-container-height: 48px !important; + --urlbar-input-container-border: none; --urlbar-margin-inline: 5px; --urlbar-container-padding: 4px; @@ -60,6 +60,9 @@ .urlbar-background { background: var(--zen-toolbar-element-bg) !important; border-radius: var(--border-radius-medium); + :root:not([zen-single-toolbar="true"]) & { + border-radius: calc(var(--border-radius-medium) * var(--zen-squircle-value)); + } outline: none !important; #urlbar:not([breakout-extend]) & { @@ -136,8 +139,13 @@ & #identity-box { margin-inline-end: 0 !important; + + :root[zen-has-empty-tab="true"] &[pageproxystate="invalid"]:not(.chromeUI) { + margin-inline-end: -4px !important; + } + &.chromeUI:not([pageproxystate="invalid"]) #identity-icon-box { - border-radius: 10px !important; + border-radius: calc(10px * var(--zen-squircle-value)) !important; } } @@ -166,13 +174,9 @@ } :root:not([zen-single-toolbar="true"]):not([zen-has-empty-tab="true"]) #urlbar:not([breakout-extend]) .urlbar-input-container { - padding: 2px 3px; + padding: 2px 5px; gap: 2px; - & .urlbar-page-action { - height: 100%; - } - & #zen-copy-url-button { order: -1; } @@ -326,6 +330,7 @@ order: 2; } + /* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */ #notification-popup-box:not([open]):not(:has(> [showing="true"])) { margin-inline-start: calc(-10px - 2 * var(--urlbar-icon-padding)); opacity: 0; @@ -346,7 +351,7 @@ padding: 4px !important; &:hover { - background: var(--toolbarbutton-hover-background); + background: var(--toolbarbutton-background-color-hover); border-radius: var(--toolbarbutton-border-radius); overflow: visible; } @@ -405,7 +410,7 @@ } #notification-popup-box { - border-radius: 10px !important; + border-radius: calc(10px * var(--zen-squircle-value)) !important; } /* Border radius on hover */ @@ -487,9 +492,10 @@ translate: -50% 0%; left: 50% !important; + /* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */ #urlbar-container:has(&) { border-radius: var(--border-radius-medium); - background: var(--toolbarbutton-hover-background); + background: var(--toolbarbutton-background-color-hover); height: var(--urlbar-height) !important; margin-inline: 0.15rem !important; :root:not([zen-single-toolbar="true"]) & { @@ -633,6 +639,7 @@ #urlbar-label-box, #urlbar-search-mode-indicator { + --urlbar-basic-component-size: auto; background-color: color-mix(in srgb, var(--zen-primary-color) 50%, light-dark(rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0.2)) 50%) !important; color: white; padding: 4px 8px; @@ -698,7 +705,7 @@ :root:not([zen-single-toolbar="true"]) #urlbar[breakout-extend]:not([zen-floating-urlbar="true"]) { & .urlbar-background { - border-radius: 10px !important; + border-radius: calc(10px * var(--zen-squircle-value)) !important; } #urlbar-results { @@ -717,6 +724,10 @@ display: none; } +.urlbarView { + overflow: visible; +} + #urlbar-search-mode-indicator-title { font-weight: 600; padding: 0; diff --git a/src/zen/common/styles/zen-panel-ui.css b/src/zen/common/styles/zen-panel-ui.css index 0f2807649..e3c92bd85 100644 --- a/src/zen/common/styles/zen-panel-ui.css +++ b/src/zen/common/styles/zen-panel-ui.css @@ -26,6 +26,7 @@ panel[type="arrow"]:not(#feature-callout) { * way to properly animate the popup without having the mica * backdrop staying still while the popup animates */ animation: none !important; + border-radius: 0; } } diff --git a/src/zen/common/styles/zen-panels/dialog.css b/src/zen/common/styles/zen-panels/dialog.css index e25f3e8d7..ce73d8738 100644 --- a/src/zen/common/styles/zen-panels/dialog.css +++ b/src/zen/common/styles/zen-panels/dialog.css @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ .dialogBox { - border-radius: 12px !important; + border-radius: calc(12px * var(--zen-squircle-value)) !important; border: 0.5px solid light-dark(rgba(0, 0, 0, 0.4), var(--zen-dialog-background)) !important; outline: 1px solid light-dark(transparent, rgba(168, 168, 169, 0.50)) !important; box-shadow: 0 10px 8px rgba(0, 0 , 0, 0.15) !important; diff --git a/src/zen/common/styles/zen-popup.css b/src/zen/common/styles/zen-popup.css index e9aff9a65..133406d7a 100644 --- a/src/zen/common/styles/zen-popup.css +++ b/src/zen/common/styles/zen-popup.css @@ -335,7 +335,7 @@ menuseparator { gap: 8px; z-index: 1000; padding: var(--zen-toast-padding); - border-radius: 10px; + border-radius: 14px; background: linear-gradient(to bottom, var(--zen-primary-color) -40%, color-mix(in srgb, var(--zen-primary-color), #0f0f0f 20%)); box-shadow: light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4)) 0 0 22px 2px; border: none; @@ -374,7 +374,7 @@ menuseparator { min-width: unset !important; min-height: 28px; margin: 0 !important; - border-radius: 6px !important; + border-radius: 10px !important; border-top: 2px solid light-dark(transparent, rgba(255, 255, 255, 0.1)); color: light-dark(rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.8)) !important; box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.05); diff --git a/src/zen/common/styles/zen-single-components.css b/src/zen/common/styles/zen-single-components.css index c6902627c..f1f9ef0c0 100644 --- a/src/zen/common/styles/zen-single-components.css +++ b/src/zen/common/styles/zen-single-components.css @@ -185,7 +185,7 @@ .toolbarbutton-1:not(#tabs-newtab-button), .urlbar-page-action, .identity-box-button { - --tab-border-radius: 6px; + --tab-border-radius: 8px; --toolbarbutton-border-radius: var(--tab-border-radius); --toolbarbutton-padding-inner: 6px; --toolbarbutton-padding-outer: 1px; @@ -291,7 +291,7 @@ --panel-width: 234px; --menu-panel-width-wide: calc(var(--panel-width) - var(--panel-padding) * 2); --uei-icon-size: 16px; - --arrowpanel-menuitem-border-radius: 10px; + --arrowpanel-menuitem-border-radius: calc(10px * var(--zen-squircle-value)); } #unified-extensions-empty-state, @@ -500,13 +500,16 @@ transition: transform 0.12s ease-in-out, opacity 0.12s ease-in-out; + will-change: transform; } + /* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */ .permission-popup-permission-item:hover &::before, .permission-popup-boost-item:hover:not(:has(.zen-permission-popup-boost-editor-button:hover)) &::before { transform: scale(1.05); } + /* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */ .permission-popup-permission-item:active:hover &::before, .permission-popup-boost-item:active:hover:not(:has(.zen-permission-popup-boost-editor-button:hover)) &::before { transform: scale(0.95); @@ -601,6 +604,8 @@ position: absolute; width: 100%; height: 100%; + will-change: transform; + @media (-moz-platform: macos) { background: linear-gradient(to bottom, light-dark(rgb(255, 255, 255), rgb(34, 34, 34)), light-dark(rgb(246, 246, 246), rgb(21, 21, 21))); diff --git a/src/zen/common/styles/zen-theme.css b/src/zen/common/styles/zen-theme.css index 7c26ad91c..745cf922d 100644 --- a/src/zen/common/styles/zen-theme.css +++ b/src/zen/common/styles/zen-theme.css @@ -3,10 +3,6 @@ * 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/. */ -/* Here, we contain all the theme related variables, for example theme - * colors, border radius, etc. - * We have `--zen-border-radius` and `--zen-primary-color` as variables. - */ :host(:is(.anonymous-content-host, notification-message)), :root { @@ -168,7 +164,11 @@ --zen-toolbar-height-with-bookmarks: calc(var(--zen-toolbar-height) + 30px); } - --toolbarbutton-hover-background: var(--zen-toolbar-element-bg-hover) !important; + --toolbarbutton-background-color-hover: color-mix( + in srgb, + var(--zen-branding-bg-reverse) 7%, + transparent + ) !important; --zen-toolbar-button-size: 16px; @media (-moz-platform: macos) { --zen-toolbar-button-size: 17px; @@ -181,19 +181,19 @@ * background on the native theme. */ --toolbar-background-color: light-dark(rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.15)); - --toolbarbutton-active-background: color-mix( + --toolbarbutton-background-color-active: color-mix( in srgb, - var(--zen-branding-bg-reverse) 7%, - transparent 93% + var(--zen-branding-bg-reverse) 10%, + transparent ) !important; --toolbar-color: var(--toolbox-textcolor) !important; --toolbox-textcolor-inactive: var(--toolbox-textcolor) !important; /* Other colors */ - --urlbar-box-active-bgcolor: var(--toolbarbutton-hover-background) !important; + --urlbar-box-active-bgcolor: var(--toolbarbutton-background-color-hover) !important; --zen-input-border-color: light-dark(rgb(204, 204, 204), rgb(66, 65, 77)); - --urlbar-box-hover-bgcolor: var(--toolbarbutton-hover-background) !important; + --urlbar-box-hover-bgcolor: var(--toolbarbutton-background-color-hover) !important; --input-text-background-color: light-dark(rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0.2)) !important; --toolbar-field-focus-background-color: light-dark( rgba(255, 255, 255, 0.25), @@ -217,6 +217,12 @@ --toolbarbutton-border-radius: 6px; --urlbar-margin-inline: 1px !important; + --zen-squircle-value: 1.3; + + @media (-moz-platform: windows) { + --zen-squircle-value: 2.1; + } + --tab-icon-overlay-stroke: light-dark(white, black) !important; --tab-close-button-padding: 4px !important; @@ -257,7 +263,7 @@ --zen-active-tab-scale: 0.985; /* Define tab hover background color */ - --tab-background-color-hover: var(--toolbarbutton-hover-background); + --tab-background-color-hover: var(--toolbarbutton-background-color-hover); /* Sidebar Notifications */ --zen-sidebar-notification-bg: color-mix( @@ -276,7 +282,7 @@ * 1. If the native radius - the separation is less than 4px, use 4px. * 2. Otherwise, use the the calculated value (inner radius = outer radius - separation). */ - max(5px, calc(var(--zen-border-radius) - var(--zen-element-separation) / 2)) + max(5px, calc((var(--zen-border-radius) - var(--zen-element-separation) / 2) * var(--zen-squircle-value))) ); /** Other theme-related styles */ @@ -348,3 +354,11 @@ } %include zen-buttons.css + +@media (-moz-pref('layout.css.corner-shape.enabled')) { + *:not(.no-squircles), + .zen-squircle-before::before, + .zen-squircle-after::after { + corner-shape: superellipse(var(--zen-squircle-value)); + } +} diff --git a/src/zen/common/zenThemeModifier.js b/src/zen/common/zenThemeModifier.js index 314e5fc6e..84fa26405 100644 --- a/src/zen/common/zenThemeModifier.js +++ b/src/zen/common/zenThemeModifier.js @@ -109,7 +109,7 @@ if (AppConstants.platform == "macosx") { const targetRadius = window.matchMedia("(-moz-mac-tahoe-theme)") .matches - ? 14 + ? 12 : 10; document.documentElement.style.setProperty( "--zen-border-radius", diff --git a/src/zen/compact-mode/sidebar.inc.css b/src/zen/compact-mode/sidebar.inc.css index dce38ff44..e25557d22 100644 --- a/src/zen/compact-mode/sidebar.inc.css +++ b/src/zen/compact-mode/sidebar.inc.css @@ -58,7 +58,7 @@ :root[zen-no-padding='true'] & { --zen-compact-float: 10px; --zen-compact-top-toolbar-hidden-fix: var(--zen-compact-float); - --zen-compact-mode-no-padding-radius-fix: 2px; + --zen-compact-mode-no-padding-radius-fix: 6px; } /* Initial padding for when we are animating */ diff --git a/src/zen/compact-mode/zen-compact-mode.css b/src/zen/compact-mode/zen-compact-mode.css index 7058bcf44..4724558e7 100644 --- a/src/zen/compact-mode/zen-compact-mode.css +++ b/src/zen/compact-mode/zen-compact-mode.css @@ -29,7 +29,7 @@ &, &::before, &::after { - border-radius: calc(var(--zen-native-inner-radius) - var(--zen-compact-mode-no-padding-radius-fix, 0px)); + border-radius: calc((var(--zen-native-inner-radius) - var(--zen-compact-mode-no-padding-radius-fix, 0px)) * var(--zen-squircle-value)); } } diff --git a/src/zen/folders/ZenFolder.mjs b/src/zen/folders/ZenFolder.mjs index 088131fa6..793909716 100644 --- a/src/zen/folders/ZenFolder.mjs +++ b/src/zen/folders/ZenFolder.mjs @@ -12,7 +12,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup { #initialized = false; static markup = ` - + `; - const fragment = window.MozXULElement.parseXULToFragment(XUL); - document.getElementById("browser").appendChild(fragment); + document.getElementById("browser").appendChild(parseXUL(XUL)); + const video = document.getElementById("zen-welcome-video"); + video.play().catch(() => {}); window.MozXULElement.insertFTLIfNeeded("browser/zen-welcome.ftl"); } @@ -82,175 +104,212 @@ return data; } + function createOption({ id, group, checked, l10n, text, extra }) { + const label = document.createElement("label"); + label.className = "zen-welcome-option"; + label.setAttribute("for", id); + const input = document.createElement("input"); + input.type = "radio"; + input.id = id; + input.name = group; + input.checked = !!checked; + label.appendChild(input); + const radio = document.createElement("span"); + radio.className = "zen-welcome-option-radio no-squircles"; + label.appendChild(radio); + if (extra) { + label.appendChild(extra); + } + const labelText = document.createElement("span"); + labelText.className = "zen-welcome-option-label"; + if (l10n) { + document.l10n.setAttributes(labelText, l10n); + } else { + labelText.textContent = text; + } + label.appendChild(labelText); + return label; + } + + function removeVideoBackground() { + const video = document.getElementById("zen-welcome-video"); + if (!video) { + return; + } + animate(video, { opacity: 0 }, { duration: 0.6, ease: "easeOut" }).then( + () => { + video.pause(); + video.remove(); + } + ); + } + + const kSpring = { type: "spring", bounce: 0.35, visualDuration: 0.35 }; + const kExit = { duration: 0.12, ease: "easeIn" }; + const kFade = { duration: 0.25, ease: "easeOut" }; + class nsZenWelcomePages { + #index = -1; + #pages; + #content = null; + #renderToken = 0; + #buttonsToken = 0; + constructor(pages) { - this._currentPage = -1; - this._pages = pages; + this.#pages = pages; this.init(); this.next(); } + get textContainer() { + return document.getElementById("zen-welcome-page-sidebar-content"); + } + + get contentContainer() { + return document.getElementById("zen-welcome-page-content"); + } + + get buttonsContainer() { + return document.getElementById("zen-welcome-page-sidebar-buttons"); + } + + get backButton() { + return document.getElementById("zen-welcome-back"); + } + + get currentPage() { + return this.#pages[this.#index]; + } + + get content() { + return this.#content; + } + init() { - document.getElementById("zen-welcome-pages").style.display = "flex"; document.getElementById("zen-welcome-start").remove(); - window.maximize(); - animate( - "#zen-welcome-pages", - { opacity: [0, 1] }, - { delay: 0.2, duration: 0.1 } - ); + const pages = document.getElementById("zen-welcome-pages"); + pages.style.display = "flex"; + animate(pages, { opacity: [0, 1] }, { ...kFade, duration: 0.45 }); + this.backButton.addEventListener("click", () => this.back()); } - async fadeInTitles(page) { - const [title1, description1, description2] = - await document.l10n.formatValues(page.text); - const titleElement = document.getElementById( - "zen-welcome-page-sidebar-content" - ); - /* eslint-disable no-unsanitized/property */ - titleElement.innerHTML = - `${title1}${description1}` + - (description2 ? `${description2}` : ""); - await animate( - "#zen-welcome-page-sidebar-content > *", - { x: ["150%", 0] }, - { - delay: getMotion().stagger(0.05), - type: "spring", - bounce: 0.2, - } - ); + next() { + this.currentPage?.commit?.(this.#content); + this.#show(this.#index + 1, 1); } - async fadeInButtons(page) { - const buttons = document.getElementById( - "zen-welcome-page-sidebar-buttons" - ); - let i = 0; - const insertedButtons = []; - for (const button of page.buttons) { - const buttonElement = document.createXULElement("button"); - document.l10n.setAttributes(buttonElement, button.l10n); - if (i++ === 0) { - buttonElement.classList.add("primary"); - } - buttonElement.classList.add("footer-button"); - buttonElement.addEventListener("click", async () => { - const shouldSkip = await button.onclick(); - if (shouldSkip) { - this.next(); - } - }); - buttonElement.style.pointerEvents = "none"; // Disable pointer events until animation is done - insertedButtons.push(buttonElement); - buttons.appendChild(buttonElement); - } - await animate( - "#zen-welcome-page-sidebar-buttons button", - { x: ["150%", 0] }, - { - delay: getMotion().stagger(0.1, { startDelay: 0.4 }), - type: "spring", - bounce: 0.2, - } - ); - for (const button of insertedButtons) { - button.style.pointerEvents = ""; // Enable pointer events after animation + back() { + if (this.#index <= 0) { + return; } + this.#show(this.#index - 1, -1); } - async fadeInContent() { - await animate( - "#zen-welcome-page-content > *", - { opacity: [0, 1] }, - { - delay: getMotion().stagger(0.1), - type: "spring", - bounce: 0.2, - } - ); - } - - async fadeOutButtons() { - await animate( - "#zen-welcome-page-sidebar-buttons button", - { x: [0, "-150%"] }, - { - type: "spring", - bounce: 0, - delay: getMotion().stagger(0.1, { startDelay: 0.4 }), - } - ); - document.getElementById("zen-welcome-page-sidebar-buttons").innerHTML = - ""; - document.getElementById("zen-welcome-page-sidebar-content").innerHTML = - ""; - } - - async fadeOutTitles() { - await animate( - "#zen-welcome-page-sidebar-content > *", - { x: [0, "-150%"] }, - { - delay: getMotion().stagger(0.05, { startDelay: 0.3 }), - type: "spring", - bounce: 0, - } - ); - } - - async fadeOutContent() { - await animate( - "#zen-welcome-page-content > *", - { opacity: [1, 0] }, - { - delay: getMotion().stagger(0.05, { startDelay: 0.3 }), - type: "spring", - bounce: 0, - duration: 0.1, - } - ); - } - - async next() { - if (this._currentPage !== -1) { - const previousPage = this._pages[this._currentPage]; - const promises = [this.fadeOutTitles(), this.fadeOutButtons()]; - if (!previousPage.dontFadeOut) { - promises.push(this.fadeOutContent()); - } - await Promise.all(promises); - await previousPage.fadeOut(); - document.getElementById("zen-welcome-page-content").innerHTML = ""; - } - this._currentPage++; - const currentPage = this._pages[this._currentPage]; - if (!currentPage) { + #show(index, direction) { + const previous = this.currentPage; + this.#index = index; + const page = this.currentPage; + if (!page) { this.finish(); return; } - await Promise.all([ - this.fadeInTitles(currentPage), - this.fadeInButtons(currentPage), - ]); - await currentPage.fadeIn(); - await this.fadeInContent(); + previous?.leave?.(); + this.#exit(this.textContainer, { x: [0, -80 * direction] }); + this.#exit(this.contentContainer, {}); + this.backButton.toggleAttribute("disabled", index === 0); + this.updateButtons(); + this.#renderText(page, direction); + this.#renderContent(page); + } + + #exit(container, keyframes) { + for (const element of container.children) { + if (element.hasAttribute("exiting")) { + continue; + } + element.setAttribute("exiting", ""); + animate(element, { opacity: [1, 0], ...keyframes }, kExit).then(() => + element.remove() + ); + } + } + + async #renderText(page, direction) { + const token = ++this.#renderToken; + const text = document.createElement("div"); + text.className = "zen-welcome-text"; + const title = document.createElement("h1"); + document.l10n.setAttributes(title, page.title); + text.appendChild(title); + for (const id of page.descriptions ?? []) { + const p = document.createElement("p"); + document.l10n.setAttributes(p, id); + text.appendChild(p); + } + await document.l10n.translateFragment(text); + if (token !== this.#renderToken) { + return; + } + this.textContainer.appendChild(text); + animate( + [...text.children], + { opacity: [0, 1], x: [120 * direction, 0] }, + { + ...kSpring, + bounce: 0.4, + visualDuration: 0.3, + delay: getMotion().stagger(0.03), + } + ); + } + + #renderContent(page) { + const content = document.createElement("div"); + content.className = "zen-welcome-page"; + if (page.id) { + content.setAttribute("page", page.id); + } + page.render(content); + this.contentContainer.appendChild(content); + this.#content = content; + animate(content, { opacity: [0, 1] }, kFade); + } + + async updateButtons() { + const token = ++this.#buttonsToken; + const fragment = document.createDocumentFragment(); + for (const button of this.currentPage.buttons) { + const element = document.createElement("button"); + element.className = button.primary + ? "zen-welcome-button primary" + : "zen-welcome-button"; + document.l10n.setAttributes(element, button.l10n); + element.addEventListener("click", () => { + if (button.onclick?.(this) !== false) { + this.next(); + } + }); + fragment.appendChild(element); + } + await document.l10n.translateFragment(fragment); + if (token === this.#buttonsToken) { + this.buttonsContainer.replaceChildren(fragment); + } } async finish() { - _iconToData = undefined; // Unload icon data + ++this.#buttonsToken; + this.buttonsContainer.replaceChildren(); + this.backButton.toggleAttribute("disabled", true); gZenWorkspaces.reorganizeTabsAfterWelcome(); - await animate( - "#zen-welcome-page-content", - { x: [0, "100%"] }, - { bounce: 0 } - ); - document.getElementById("zen-welcome-page-content").remove(); - await this.animHeart(); - await this.#pinRemainingTabs(); - await animate("#zen-welcome-pages", { opacity: [1, 0] }); + const promises = [this.#applyChoices()]; + await animate("#zen-welcome", { opacity: [1, 0] }); + this.contentContainer.remove(); + await Promise.all(promises); + _iconToData = undefined; // Unload icon data document.getElementById("zen-welcome").remove(); document.documentElement.removeAttribute("zen-welcome-stage"); + unlockWindowSize(); for (const element of document.getElementById("browser").children) { if (kZenElementsToIgnore.includes(element.id)) { continue; @@ -265,14 +324,10 @@ await animate(`#browser > *:not(${elementsToIgnore})`, { opacity: [0, 1], }); - gZenUIManager.showToast("zen-welcome-finished"); } - async #pinRemainingTabs() { - for (const tab of _tabsToPinEssentials) { - tab.removeAttribute("pending"); // Make it appear loaded - gZenPinnedTabManager.addToEssentials(tab); - } + async #applyChoices() { + await this.#pinEssentials(); let tabsToGroup = []; if (!gBrowser.selectedTab.hasAttribute("zen-empty-tab")) { tabsToGroup.push(gBrowser.selectedTab); @@ -283,22 +338,39 @@ }); } - async animHeart() { - const heart = document.createElement("div"); - heart.id = "zen-welcome-heart"; - const sidebar = document.getElementById("zen-welcome-page-sidebar"); - sidebar.style.width = "100%"; - sidebar.appendChild(heart); - sidebar.setAttribute("animate-heart", "true"); - await animate( - "#zen-welcome-heart", - { opacity: [0, 1, 1, 1, 0], scale: [0.5, 1, 1.2, 1, 1.2] }, - { - duration: 1.5, - delay: 0.2, - bounce: 0, - } + async #pinEssentials() { + const apps = kEssentialApps.filter(app => + gChoices.essentials.has(app.url) ); + if (!apps.length) { + return; + } + await PlacesUtils.history.insertMany( + apps.map(app => ({ + url: app.url, + visits: [{ transition: PlacesUtils.history.TRANSITIONS.TYPED }], + })) + ); + const { TabStateCache } = ChromeUtils.importESModule( + "resource:///modules/sessionstore/TabStateCache.sys.mjs" + ); + for (const app of apps) { + const tab = window.gBrowser.addTrustedTab(app.url, { + inBackground: true, + createLazyBrowser: true, + }); + const icon = await getIconData( + `chrome://browser/content/zen-images/favicons/${app.icon}.svg` + ); + // Update the persistent tab state cache with |tabData| information. + TabStateCache.update(tab.linkedBrowser.permanentKey, { + history: { entries: [{ url: app.url }], index: 0 }, + image: icon, + }); + gBrowser.setIcon(tab, icon); + tab.removeAttribute("pending"); // Make it appear loaded + gZenPinnedTabManager.addToEssentials(tab); + } } } @@ -362,363 +434,230 @@ } } + const kNextButton = { l10n: "zen-generic-next", primary: true }; + + async function setDefaultBrowser() { + const shellSvc = + AppConstants.HAVE_SHELL_SERVICE && window.getShellService(); + if (!shellSvc) { + return; + } + try { + await shellSvc.setDefaultBrowser(false); + } catch (ex) { + console.error(ex); + } + } + function getWelcomePages() { return [ { - text: [ - { - id: "zen-welcome-import-title", - }, - { - id: "zen-welcome-import-description-1", - }, - { - id: "zen-welcome-import-description-2", - }, - ], - buttons: [ - { - l10n: "zen-welcome-import-button", - onclick: async () => { - MigrationUtils.showMigrationWizard(window, { - isStartupMigration: true, - }); - document - .querySelector("#zen-welcome-page-sidebar-buttons button") - .remove(); - const newButton = document.querySelector( - "#zen-welcome-page-sidebar-buttons button" - ); - newButton.classList.add("primary"); - document.l10n.setAttributes(newButton, "zen-generic-next"); - return false; - }, - }, - { - l10n: "zen-welcome-skip-button", - onclick: async () => { - return true; - }, - }, - ], - fadeIn() { - const xul = ` - - - - - - - - - `; - const fragment = window.MozXULElement.parseXULToFragment(xul); - document - .getElementById("zen-welcome-page-content") - .appendChild(fragment); - }, - async fadeOut() { - const shouldSetDefault = document.getElementById( - "zen-welcome-set-default-browser" - ).checked; - if (AppConstants.HAVE_SHELL_SERVICE && shouldSetDefault) { - let shellSvc = window.getShellService(); - if (!shellSvc) { - return; - } - - try { - await shellSvc.setDefaultBrowser(false); - } catch (ex) { - console.error(ex); - } - } - }, - }, - { - text: [ - { - id: "zen-welcome-default-search-title", - }, - { - id: "zen-welcome-default-search-description", - }, - ], - buttons: [ - { - l10n: "zen-generic-next", - onclick: async () => { - return true; - }, - }, - ], - async fadeIn() { - const content = document.getElementById("zen-welcome-page-content"); - const engineStore = new ZenSearchEngineStore(); - engineStore.init(); - - content.setAttribute("select-engine", "true"); - - const defaultEngine = await lazy.SearchService.getDefault(); - const promises = []; - engineStore.getEngines().forEach(engine => { - const label = document.createElement("label"); - const engineId = engine.name.replace(/\s+/g, "-").toLowerCase(); - label.setAttribute("for", engineId); - const input = document.createElement("input"); - input.setAttribute("type", "radio"); - input.setAttribute("id", engineId); - input.setAttribute("name", "zen-welcome-set-default-browser"); - input.setAttribute("hidden", "true"); - if (engine.name === defaultEngine.name) { - input.setAttribute("checked", true); - } - label.appendChild(input); - const engineLabel = document.createXULElement("label"); - engineLabel.textContent = engine.name; - const icon = document.createElement("img"); - promises.push( - (async () => { - icon.setAttribute( - "src", - await engine.originalEngine.getIconURL() - ); - })() - ); - icon.setAttribute("width", "32"); - icon.setAttribute("height", "32"); - icon.setAttribute("class", "engine-icon"); - label.appendChild(icon); - label.appendChild(engineLabel); - content.appendChild(label); - label.addEventListener("click", async () => { - const selectedEngine = engineStore.getEngineByName(engine.name); - if (selectedEngine) { - await engineStore.setDefaultEngine(selectedEngine); - } - }); + id: "import", + title: "zen-welcome-import-title", + descriptions: ["zen-welcome-import-description"], + buttons: [kNextButton], + render(content) { + const yes = createOption({ + id: "zen-welcome-import-yes", + group: "zen-welcome-import", + l10n: "zen-welcome-import-yes", }); - await Promise.all(promises); - }, - async fadeOut() { - document - .getElementById("zen-welcome-page-content") - .removeAttribute("select-engine"); - }, - }, - { - text: [ - { - id: "zen-welcome-initial-essentials-title", - }, - { - id: "zen-welcome-initial-essentials-description-1", - }, - { - id: "zen-welcome-initial-essentials-description-2", - }, - ], - buttons: [ - { - l10n: "zen-generic-next", - onclick: async () => { - return true; - }, - }, - ], - fadeIn() { - const xul = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `; - const fragment = window.MozXULElement.parseXULToFragment(xul); - document - .getElementById("zen-welcome-page-content") - .appendChild(fragment); - document - .getElementById( - "zen-welcome-initial-essentials-browser-sidebar-essentials" - ) - .addEventListener("click", async event => { - const tab = event.target.closest(".tabbrowser-tab"); - if (!tab) { - return; - } - tab.toggleAttribute("visuallyselected"); - }); - }, - async fadeOut() { - const selectedTabs = document - .getElementById( - "zen-welcome-initial-essentials-browser-sidebar-essentials" - ) - .querySelectorAll(".tabbrowser-tab[visuallyselected]"); - - if (selectedTabs.length) { - await PlacesUtils.history.insertMany( - [...selectedTabs].map(tab => ({ - url: tab.getAttribute("data-url"), - visits: [ - { - transition: PlacesUtils.history.TRANSITIONS.TYPED, - }, - ], - })) - ); - } - - const { TabStateCache } = ChromeUtils.importESModule( - "resource:///modules/sessionstore/TabStateCache.sys.mjs" + content.appendChild(yes); + content.appendChild( + createOption({ + id: "zen-welcome-import-no", + group: "zen-welcome-import", + l10n: "zen-welcome-import-no", + checked: true, + }) ); - for (const tab of selectedTabs) { - const url = tab.getAttribute("data-url"); - const createdTab = window.gBrowser.addTrustedTab(url, { - inBackground: true, - createLazyBrowser: true, + }, + commit(content) { + if (content.querySelector("#zen-welcome-import-yes").checked) { + MigrationUtils.showMigrationWizard(window, { + isStartupMigration: true, }); - let essentialIconUrl = tab.style.getPropertyValue( - "--zen-essential-tab-icon" - ); - // Remove url() from the icon URL - essentialIconUrl = essentialIconUrl - .replace(/url\(['"]?/, "") - .replace(/['"]?\)/, ""); - essentialIconUrl = await getIconData(essentialIconUrl); - // Update the persistent tab state cache with |tabData| information. - TabStateCache.update(createdTab.linkedBrowser.permanentKey, { - history: { entries: [{ url }], index: 0 }, - image: essentialIconUrl, - }); - gBrowser.setIcon(createdTab, essentialIconUrl); - _tabsToPinEssentials.push(createdTab); } }, }, { - text: [ - { - id: "zen-welcome-workspace-colors-title", - }, - { - id: "zen-welcome-workspace-colors-description", - }, - ], - buttons: [ - { - l10n: "zen-generic-next", - onclick: async () => { - return true; - }, - }, - ], - fadeIn() { + id: "colors", + title: "zen-welcome-workspace-colors-title", + descriptions: ["zen-welcome-workspace-colors-description"], + buttons: [kNextButton], + render(content) { + removeVideoBackground(); const anchor = document.createElement("div"); anchor.id = "zen-welcome-workspace-colors-anchor"; - document - .getElementById("zen-welcome-page-content") - .appendChild(anchor); - gZenThemePicker.panel.setAttribute("noautohide", "true"); - gZenThemePicker.panel.setAttribute("consumeoutsideclicks", "false"); - gZenThemePicker.panel.setAttribute("nonnative", ""); - gZenThemePicker.panel.addEventListener( + content.appendChild(anchor); + const panel = gZenThemePicker.panel; + panel.setAttribute("noautohide", "true"); + panel.setAttribute("consumeoutsideclicks", "false"); + panel.setAttribute("nonnative", ""); + panel.addEventListener( "popupshowing", () => { - const panelRect = gZenThemePicker.panel.getBoundingClientRect(); + const panelRect = panel.getBoundingClientRect(); // 20 is the shadow width * 2 - anchor.style.height = panelRect.height - 20 + "px"; + anchor.style.height = + panelRect.height - + (AppConstants.platform == "macosx" ? -90 : 20) + + "px"; anchor.style.width = panelRect.width - 20 + "px"; }, { once: true } ); - PanelMultiView.openPopup(gZenThemePicker.panel, anchor, { - position: "overlap", - }); + PanelMultiView.openPopup(panel, anchor, { position: "overlap" }); }, - dontFadeOut: true, - async fadeOut() { - gZenThemePicker.panel.removeAttribute("noautohide"); - gZenThemePicker.panel.removeAttribute("consumeoutsideclicks"); - gZenThemePicker.panel.removeAttribute("nonnative"); - await animate(gZenThemePicker.panel, { opacity: [1, 0] }); - gZenThemePicker.panel.hidePopup(); - gZenThemePicker.panel.removeAttribute("style"); + leave() { + const panel = gZenThemePicker.panel; + panel.removeAttribute("noautohide"); + panel.removeAttribute("consumeoutsideclicks"); + panel.removeAttribute("nonnative"); + animate(panel, { opacity: [1, 0] }, kExit).then(() => { + panel.hidePopup(); + panel.removeAttribute("style"); + }); }, }, { - text: [ - { - id: "zen-welcome-start-browsing-title", - }, - { - id: "zen-welcome-start-browsing-description-1", - }, - ], + id: "search", + title: "zen-welcome-default-search-title", + descriptions: ["zen-welcome-default-search-description"], + buttons: [kNextButton], + async render(content) { + const engineStore = new ZenSearchEngineStore(); + await engineStore.init(); + const defaultEngine = await lazy.SearchService.getDefault(); + for (const engine of engineStore.getEngines()) { + const iconWrapper = document.createElement("div"); + iconWrapper.className = "engine-icon-wrapper"; + const iconBackdrop = document.createElement("img"); + iconBackdrop.className = "engine-icon-backdrop"; + const icon = document.createElement("img"); + icon.className = "engine-icon"; + icon.width = icon.height = 40; + iconWrapper.append(iconBackdrop, icon); + engine.originalEngine.getIconURL(96).then(url => { + icon.src = url; + iconBackdrop.src = url; + }); + const option = createOption({ + id: "zen-welcome-engine-" + engine.name.replace(/\s+/g, "-"), + group: "zen-welcome-search-engine", + text: engine.name, + checked: engine.name === defaultEngine.name, + extra: iconWrapper, + }); + option + .querySelector("input") + .addEventListener("change", () => + engineStore.setDefaultEngine(engine) + ); + content.appendChild(option); + } + }, + }, + { + id: "essentials", + title: "zen-welcome-essentials-title", + descriptions: ["zen-welcome-essentials-description"], buttons: [ + kNextButton, { - l10n: "zen-welcome-start-browsing", - onclick: async () => { - return true; + l10n: "zen-welcome-skip", + onclick(pages) { + for (const button of pages.content.querySelectorAll( + ".zen-welcome-essential[selected]" + )) { + button.removeAttribute("selected"); + } }, }, ], - fadeIn() {}, - fadeOut() {}, + render(content) { + content.appendChild( + parseXUL(` + + + + + + + + + + + + + `) + ); + const grid = content.querySelector("#zen-welcome-essentials"); + for (const app of kEssentialApps) { + const button = document.createElement("button"); + button.className = "zen-welcome-essential"; + button.dataset.url = app.url; + button.style.setProperty( + "--zen-welcome-app-icon", + `url("chrome://browser/content/zen-images/favicons/${app.icon}.svg")` + ); + button.style.setProperty("--zen-welcome-app-color", app.color); + button.toggleAttribute( + "selected", + gChoices.essentials.has(app.url) + ); + button.addEventListener("click", () => { + button.toggleAttribute("selected"); + }); + grid.appendChild(button); + } + }, + commit(content) { + gChoices.essentials = new Set( + [ + ...content.querySelectorAll(".zen-welcome-essential[selected]"), + ].map(button => button.dataset.url) + ); + }, + }, + { + id: "default-browser", + title: "zen-welcome-default-browser-title", + descriptions: ["zen-welcome-default-browser-description"], + buttons: [kNextButton], + render(content) { + content.appendChild( + createOption({ + id: "zen-welcome-set-default-browser", + group: "zen-welcome-default-browser", + l10n: "zen-welcome-set-default-browser", + checked: gChoices.setDefaultBrowser, + }) + ); + content.appendChild( + createOption({ + id: "zen-welcome-dont-set-default-browser", + group: "zen-welcome-default-browser", + l10n: "zen-welcome-dont-set-default-browser", + checked: !gChoices.setDefaultBrowser, + }) + ); + }, + commit(content) { + gChoices.setDefaultBrowser = content.querySelector( + "#zen-welcome-set-default-browser" + ).checked; + if (gChoices.setDefaultBrowser) { + setDefaultBrowser(); + } + }, + }, + { + id: "finish", + title: "zen-welcome-start-browsing-title", + descriptions: ["zen-welcome-start-browsing-description-1"], + buttons: [{ l10n: "zen-welcome-start-browsing", primary: true }], + render() {}, }, ]; } @@ -729,33 +668,48 @@ { id: "zen-welcome-title-line2" }, ]); const titleElement = document.getElementById("zen-welcome-title"); - /* eslint-disable no-unsanitized/property */ - titleElement.innerHTML = `${title1}${title2}`; + for (const line of [title1, title2]) { + const lineElement = document.createElement("span"); + for (const char of line) { + if (char === " ") { + lineElement.append(" "); + continue; + } + const charElement = document.createElement("span"); + charElement.className = "zen-welcome-char"; + charElement.textContent = char; + lineElement.appendChild(charElement); + } + titleElement.appendChild(lineElement); + } + const chars = titleElement.querySelectorAll(".zen-welcome-char"); await animate( - "#zen-welcome-title span", - { opacity: [0, 1], y: [20, 0], filter: ["blur(2px)", "blur(0px)"] }, + chars, + { opacity: [0, 1], y: [50, 0] }, { - delay: getMotion().stagger(0.6, { startDelay: 0.2 }), + delay: getMotion().stagger(0.035, { startDelay: 0.8 }), type: "spring", - stiffness: 300, - damping: 20, - mass: 1.8, + bounce: 0.3, + visualDuration: 0.45, } ); const button = document.getElementById("zen-welcome-start-button"); - button.addEventListener("click", async () => { - await animate( - "#zen-welcome-title span, #zen-welcome-start-button", - { opacity: [1, 0], y: [0, -10], filter: ["blur(0px)", "blur(2px)"] }, - { - type: "spring", - ease: [0.755, 0.05, 0.855, 0.06], - bounce: 0.4, - delay: getMotion().stagger(0.4), - } - ); - new nsZenWelcomePages(getWelcomePages()); - }); + button.addEventListener( + "click", + async () => { + await animate( + "#zen-welcome-title .zen-welcome-char, #zen-welcome-start-button", + { opacity: [1, 0], y: [0, -14] }, + { + duration: 0.3, + ease: "easeIn", + delay: getMotion().stagger(0.012), + } + ); + new nsZenWelcomePages(getWelcomePages()); + }, + { once: true } + ); await animate( button, { opacity: [0, 1], y: [20, 0], filter: ["blur(2px)", "blur(0px)"] }, @@ -769,20 +723,45 @@ ); } + const kSizeLockProperties = [ + "min-width", + "max-width", + "min-height", + "max-height", + ]; + + function lockWindowSize(width, height) { + const style = document.documentElement.style; + style.setProperty("min-width", `${width}px`, "important"); + style.setProperty("max-width", `${width}px`, "important"); + style.setProperty("min-height", `${height}px`, "important"); + style.setProperty("max-height", `${height}px`, "important"); + } + + function unlockWindowSize() { + const style = document.documentElement.style; + for (const property of kSizeLockProperties) { + style.removeProperty(property); + } + } + function centerWindowOnScreen() { window.addEventListener( "MozAfterPaint", function () { - window.resizeTo(875, 560); + const width = Math.min(1200, screen.availWidth); + const height = Math.min(720, screen.availHeight); + window.resizeTo(width, height); window.focus(); const appWin = window.docShell.treeOwner .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIAppWindow); appWin.rollupAllPopups(); window.moveTo( - screen.availLeft + (screen.availWidth - outerWidth) / 2, - screen.availTop + (screen.availHeight - outerHeight) / 2 + screen.availLeft + (screen.availWidth - width) / 2, + screen.availTop + (screen.availHeight - height) / 2 ); + lockWindowSize(width, height); }, { once: true } ); diff --git a/src/zen/welcome/jar.inc.mn b/src/zen/welcome/jar.inc.mn index 7295cfbaf..dc8cc2305 100644 --- a/src/zen/welcome/jar.inc.mn +++ b/src/zen/welcome/jar.inc.mn @@ -4,3 +4,4 @@ content/browser/zen-components/ZenWelcome.mjs (../../zen/welcome/ZenWelcome.mjs) content/browser/zen-styles/zen-welcome.css (../../zen/welcome/zen-welcome.css) + content/browser/zen-videos/welcome-background.mp4 (../../zen/welcome/welcome-background.mp4) diff --git a/src/zen/welcome/welcome-background.mp4 b/src/zen/welcome/welcome-background.mp4 new file mode 100644 index 000000000..6619322d8 Binary files /dev/null and b/src/zen/welcome/welcome-background.mp4 differ diff --git a/src/zen/welcome/zen-welcome.css b/src/zen/welcome/zen-welcome.css index 54d2c7f10..6b697eb24 100644 --- a/src/zen/welcome/zen-welcome.css +++ b/src/zen/welcome/zen-welcome.css @@ -15,6 +15,21 @@ -moz-window-dragging: drag; } +#zen-welcome { + position: relative; + isolation: isolate; +} + +#zen-welcome-video { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + pointer-events: none; + will-change: opacity; +} + :root[zen-welcome-stage] { min-width: 875px; min-height: 560px; @@ -24,32 +39,111 @@ } } +#zen-welcome { + --zen-welcome-accent: light-dark( + oklch(from var(--zen-primary-color) clamp(0.35, l, 0.6) c h), + oklch(from var(--zen-primary-color) clamp(0.7, l, 0.85) c h) + ); + --zen-welcome-accent-button: light-dark( + oklch(from var(--zen-primary-color) clamp(0.35, l, 0.6) c h), + oklch(from var(--zen-primary-color) clamp(0.55, l, 0.7) c h) + ); + --zen-welcome-sidebar-bg: light-dark(#ffffff, #1c1c1e); + --zen-welcome-content-bg: light-dark(#f6f6f8f5, #2b2b30ed); + --zen-welcome-surface-bg: light-dark(#ffffff, #1c1c1e); + --zen-welcome-tile-bg: light-dark(#ececee, #333338); + --zen-welcome-border: light-dark( + rgba(0, 0, 0, 0.14), + rgba(255, 255, 255, 0.16) + ); + --zen-welcome-text-secondary: light-dark( + rgba(0, 0, 0, 0.6), + rgba(255, 255, 255, 0.6) + ); +} + +.zen-welcome-button { + appearance: none; + border: none; + border-radius: 12px; + padding: 1.2rem 1rem; + background: transparent; + color: var(--zen-welcome-accent); + font: inherit; + font-size: 1.2rem; + font-weight: 600; + cursor: pointer; + will-change: transform; + transition: scale 0.15s ease-out; + + &:hover { + scale: 1.03; + filter: brightness(1.1); + } + + &:active { + scale: 1; + } + + &.primary { + background: var(--zen-welcome-accent-button); + color: white; + + &:hover { + filter: brightness(1.1); + } + } +} + #zen-welcome-start { flex-direction: column; -moz-window-dragging: drag; - --zen-primary-color: light-dark(black, white); + color: white; #zen-welcome-start-button { opacity: 0; list-style-image: url(chrome://browser/skin/zen-icons/forward.svg); - position: absolute; - bottom: 10%; padding: 1em !important; min-width: 100px; + background: rgb(62, 115, 62) !important; + fill: white !important; + + will-change: transform; + transition: scale 0.15s ease-out; + + &:hover { + scale: 1.03; + filter: brightness(1.1); + } + + &:active { + scale: 1; + transform: none; + } } #zen-welcome-title { text-align: center; - font-size: 5rem; - line-height: 1.1; + font-size: 5.2rem; + font-weight: 700; + line-height: 1.05; + letter-spacing: -0.03em; max-width: 50%; - font-weight: 500; white-space: nowrap; + /* Layered (transformed) glyphs are drawn with grayscale AA on macOS; + * use it for the whole title so animating characters don't look bolder. */ + -moz-osx-font-smoothing: grayscale; + transform: translateY(-5%); & > span { display: block; + } + + .zen-welcome-char { + display: inline-block; opacity: 0; + will-change: transform; } } } @@ -57,28 +151,18 @@ #zen-welcome-pages { -moz-window-dragging: no-drag; opacity: 0; - justify-content: start; - align-items: start; display: none; - background: var(--zen-branding-bg); - border-radius: 1em; + justify-content: start; + align-items: stretch; + background: var(--zen-welcome-content-bg); + color: light-dark(#111111, #ffffff); + border-radius: 1.4rem; position: relative; - width: 60%; - height: 60%; - box-shadow: var(--zen-big-shadow); + width: 86%; + height: 82%; + box-shadow: 0 3px 8px rgba(0,0,0,.05); overflow: hidden; - /* Small screens */ - @media (max-width: 1400px) { - width: 80%; - height: 80%; - } - - @media (max-width: 1200px) { - width: 90%; - height: 90%; - } - @media (max-width: 1000px) { width: 100%; height: 100%; @@ -86,216 +170,339 @@ } #zen-welcome-page-sidebar { + position: relative; + z-index: 1; + display: flex; flex-direction: column; - justify-content: space-between; - padding: 3.8rem; - width: 40%; + width: 38%; height: 100%; - overflow-x: hidden; - overflow-y: auto; + padding: 4rem 3.8rem 3.6rem; + box-sizing: border-box; + overflow: hidden; + background: var(--zen-welcome-sidebar-bg); + box-shadow: 4px 0 24px rgba(0, 0, 0, 0.05); + } - & #zen-welcome-heart { - width: 100%; - height: 100%; - opacity: 0; - color: currentColor; + #zen-welcome-back { + align-self: flex-start; + display: flex; + align-items: center; + gap: 0.5rem; + margin: 0 0 2.2rem; + padding: 0; + appearance: none; + border: none; + background: none; + font: inherit; + font-size: 1.1rem; + font-weight: 600; + color: var(--zen-welcome-accent); + + &::before { + content: ""; + width: 16px; + height: 16px; + background: url(chrome://browser/skin/zen-icons/back.svg) center / contain + no-repeat; + -moz-context-properties: fill; fill: currentColor; - -moz-context-properties: fill, fill-opacity; - background-image: url(chrome://browser/skin/zen-icons/essential-add.svg); - background-size: 15%; - background-repeat: no-repeat; - background-position: center; } - &[animate-heart] { - overflow: hidden; + &[disabled] { + visibility: hidden; + } + } + + #zen-welcome-page-sidebar-content { + flex: 1; + position: relative; + } + + .zen-welcome-text { + position: absolute; + inset: 0; + + & > * { + opacity: 0; + will-change: transform, opacity; + } + + & h1 { + margin: 0 0 2.4rem; + font-size: 3rem; + font-weight: 700; + line-height: 1.1; + letter-spacing: -0.02em; + } + + & p { + margin: 0 0 1.2rem; + font-size: 1.25rem; + line-height: 1.6; + color: var(--zen-welcome-text-secondary); } } #zen-welcome-page-sidebar-buttons { + display: flex; flex-direction: column; - gap: 10px; - } - - #zen-welcome-page-sidebar-content { - & h1 { - font-size: xx-large; - font-weight: 600; - margin-bottom: 1rem; - } - - & p { - margin: 0 0 1.1rem 0; - color: light-dark(rgba(0, 0, 0, 0.6), rgba(255, 255, 255, 0.6)); - } - - & > * { - transform: translate(300%); - } - } - - & button { - justify-content: center; - align-items: center; - transform: translate(300%); + gap: 1rem; } #zen-welcome-page-content { - background: light-dark(rgba(0, 0, 0, 0.1), rgba(255, 255, 255, 0.1)); - width: 60%; - max-width: 80rem; - height: 100%; + flex: 1; position: relative; + height: 100%; overflow: hidden; - justify-content: center; - align-items: center; + + &::before { + content: ""; + position: absolute; + inset: 0; + z-index: 0; + background-image: url(chrome://browser/content/zen-images/grain-bg.png); + opacity: 0.3; + mix-blend-mode: overlay; + pointer-events: none; + } + } + + .zen-welcome-page { + position: absolute; + inset: 0; + opacity: 0; display: flex; flex-direction: column; - gap: 1.6rem; + justify-content: center; + align-items: center; + gap: 2.5rem; + padding: 3rem 4rem; + box-sizing: border-box; - &[select-engine="true"] { - display: grid; - grid-template-columns: 1fr 1fr; - box-sizing: border-box; - padding: 5rem; + &[exiting] { + pointer-events: none; } - & > label { - opacity: 0; - transition: - scale 0.1s, - box-shadow 0.1s; - padding: 1.5rem 1.1rem; - border-radius: 0.6rem; - width: 50%; - gap: 0.8rem; - display: flex; - border: 2px solid var(--zen-colors-border); - background: light-dark(rgba(255, 255, 255, 0.7), rgba(0, 0, 0, 0.4)); - align-items: center; + &[page="essentials"] { + justify-content: flex-end; + align-items: flex-end; + padding: 3rem 0 0 6rem; + } - &:hover { - box-shadow: var(--zen-big-shadow); + &[page="search"] { + justify-content: safe center; + overflow-y: auto; + padding-top: 6rem; + padding-bottom: 6rem; + scrollbar-width: none; + + mask-image: linear-gradient( + transparent, + black 6rem, + black calc(100% - 6rem), + transparent + ); + + .zen-welcome-option { + max-width: 24rem; + min-height: 7.5rem; + padding: 0 0 0 1.8rem; + overflow: hidden; + font-weight: 600; } - &:has(:checked) { - box-shadow: var(--zen-big-shadow); - border: 2px solid var(--zen-primary-color); - scale: 1.03; + .engine-icon-wrapper { + position: relative; + display: flex; + align-items: center; + justify-content: center; + align-self: stretch; + flex-shrink: 0; + width: 34%; + margin-left: auto; + overflow: hidden; + background: var(--zen-welcome-tile-bg); } - } - &[select-engine="true"] > label { - flex-direction: column; - font-weight: 600; - aspect-ratio: 1 / 0.7; - align-items: center; - width: 60%; - justify-self: center; - align-self: center; - justify-content: space-around; - } - - /* 3 or more engines */ - &[select-engine="true"]:has(label:nth-of-type(3)) > label { - height: 50%; - } - - #zen-welcome-workspace-colors-anchor { - width: 1px; - height: 1px; - } - - #zen-welcome-initial-essentials-browser { - min-width: 70%; - min-height: 80%; - display: flex; - margin-left: auto; - margin-top: auto; - border-top-left-radius: 1.2em; - box-shadow: var(--zen-big-shadow); - background: light-dark(rgba(255, 255, 255, 0.5), rgba(0, 0, 0, 0.2)); - padding-right: 20%; - overflow: hidden; - opacity: 0; - border: 1px solid var(--zen-colors-border); - border-bottom-width: 0; - border-right-width: 0; - - #zen-welcome-initial-essentials-browser-sidebar { + .engine-icon-backdrop { + position: absolute; + inset: 0; width: 100%; - padding: 1.4rem; - gap: 1.2rem; - background: light-dark(rgba(255, 255, 255, 0.7), rgba(0, 0, 0, 0.4)); + height: 100%; + object-fit: cover; + scale: 3; + filter: blur(30px) saturate(1.8); + opacity: 0.2; + } - #zen-welcome-initial-essentials-browser-sidebar-win-buttons { - gap: 0.5rem; - align-items: center; + .engine-icon { + position: relative; + width: 26px; + height: 26px; + border-radius: 10px; + } - & > div { - width: 15px; - height: 15px; - border-radius: 50%; - background: var(--zen-toolbar-element-bg); - } - } + .zen-welcome-option-label { + order: -1; + padding-right: 1rem; + } - #zen-welcome-initial-essentials-browser-sidebar-essentials { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1rem; - visibility: visible; + .zen-welcome-option-radio { + order: -2; + } + } + } - & * { - visibility: visible; - } + .zen-welcome-option { + display: flex; + align-items: center; + gap: 1rem; + width: 100%; + max-width: 30rem; + padding: 1.8rem 1.9rem; + font-size: 1.3rem; + box-sizing: border-box; + border-radius: 20px; + border: 1px solid var(--zen-welcome-border); + background: var(--zen-welcome-surface-bg); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); + cursor: pointer; + will-change: transform; + transition: scale 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); - & .extra-tab { - width: 100%; - height: 4rem; - border-radius: var(--border-radius-large); - margin-top: 0.5rem; - background: var(--zen-toolbar-element-bg); - grid-column: span 3; - } + &:hover { + scale: 1.03; + } - & .tabbrowser-tab { - --tab-min-height: 6rem !important; - min-width: 5rem !important; - transition: transform 0.1s; - position: relative; + & input { + display: none; + } - &::after { - position: absolute; - content: ""; - width: 1.8rem; - height: 1.8rem; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background: var(--zen-essential-tab-icon); - background-position: center; - background-size: contain; - background-repeat: no-repeat; - border-radius: 4px; - } + & strong { + font-weight: 700; + } - --border-radius-medium: 1rem; + & .engine-icon { + width: 28px; + height: 28px; + border-radius: 6px; + } - &[visuallyselected] { - transform: scale(1.06); - } + .zen-welcome-option-radio { + position: relative; + flex-shrink: 0; + width: 22px; + height: 22px; + box-sizing: border-box; + border-radius: 50%; + border: 1px solid + light-dark(rgba(0, 0, 0, 0.45), rgba(255, 255, 255, 0.5)); - & .tab-background { - margin: 0 !important; - } + &::after { + content: ""; + position: absolute; + inset: 3px; + border-radius: 50%; + background: currentColor; + opacity: 0; + } + } - & .tab-background::after { - filter: blur(30px) brightness(1.2); - } - } + /* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */ + &:has(:checked) { + scale: 1.03; + border-color: var(--zen-welcome-accent); + color: var(--zen-welcome-accent); + + .zen-welcome-option-radio { + border-color: currentColor; + + &::after { + opacity: 1; } } } } + + #zen-welcome-workspace-colors-anchor { + width: 1px; + height: 1px; + } + + .zen-welcome-mock-browser { + width: 92%; + height: 100%; + border-top-left-radius: 2.4rem; + background: light-dark(#e3e3e5, #232326); + box-shadow: 0 8px 40px rgba(0, 0, 0, 0.12); + overflow: hidden; + + .zen-welcome-mock-browser-sidebar { + display: flex; + flex-direction: column; + gap: 1.6rem; + width: 80%; + height: 100%; + padding: 2.6rem 2.4rem; + box-sizing: border-box; + background: var(--zen-welcome-surface-bg); + } + + .zen-welcome-mock-browser-dots { + display: flex; + gap: 1rem; + margin-bottom: 0.6rem; + + & > div { + width: 22px; + height: 22px; + border-radius: 50%; + background: var(--zen-welcome-tile-bg); + } + } + + #zen-welcome-essentials { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; + } + + .zen-welcome-essential { + appearance: none; + aspect-ratio: 1; + padding: 0; + border-radius: 2rem; + border: 3px solid transparent; + background: var(--zen-welcome-tile-bg) var(--zen-welcome-app-icon) + center / 35% no-repeat; + cursor: pointer; + will-change: transform; + transition: scale 0.25s cubic-bezier(0.34, 1.56, 0.64, 1); + + &:hover, + &[selected] { + scale: 1.04; + } + + &[selected] { + background-color: color-mix( + in srgb, + var(--zen-welcome-app-color) 22%, + var(--zen-welcome-surface-bg) + ); + border-color: color-mix( + in srgb, + var(--zen-welcome-app-color) 60%, + transparent + ); + } + } + + .zen-welcome-mock-tab { + flex-shrink: 0; + height: 4.5rem; + border-radius: 1.6rem; + background: var(--zen-welcome-tile-bg); + } + } } diff --git a/surfer.json b/surfer.json index a1a87a88a..f144a9df1 100644 --- a/surfer.json +++ b/surfer.json @@ -5,8 +5,8 @@ "binaryName": "zen", "version": { "product": "firefox", - "version": "154.0.1", - "candidate": "154.0.1", + "version": "155.0", + "candidate": "155.0", "candidateBuild": 1 }, "buildOptions": { @@ -20,7 +20,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.21.16b", + "displayVersion": "1.22b", "github": { "repo": "zen-browser/desktop" }, @@ -40,7 +40,7 @@ "brandShortName": "Twilight", "brandFullName": "Zen Twilight", "release": { - "displayVersion": "1.22t", + "displayVersion": "1.23t", "github": { "repo": "zen-browser/desktop" }