├── bun.lockb ├── .github ├── assets │ ├── ui.png │ ├── arc-ui-default.svg │ ├── arc-ui-square.svg │ └── arc-ui-square-transparent.svg ├── ISSUE_TEMPLATE │ ├── 📗-documentation-issue.md │ ├── 🚀-feature-request.md │ └── 🐛-bug-report.md └── CONTRIBUTING.md ├── src ├── components │ ├── index.css │ ├── close-dialog.css │ ├── url-indicator.css │ ├── sidebar.css │ └── from-navigator │ │ ├── alt-menu.css │ │ ├── screenshot-panel.css │ │ ├── hover-sidebar │ │ ├── bottom.css │ │ ├── bookmarks.css │ │ ├── top.css │ │ ├── search-input.css │ │ ├── index.css │ │ └── tabs.css │ │ └── search-prompt.css ├── index.css └── variables.css ├── scripts ├── build.ts ├── fix-dev-server.sh ├── uninstall.sh ├── install.sh ├── utils.ts └── dev.ts ├── .stylelintrc.json ├── tsconfig.json ├── biome.json ├── package.json ├── license ├── readme.md └── .gitignore /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dxdotdev/arc-ui/HEAD/bun.lockb -------------------------------------------------------------------------------- /.github/assets/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dxdotdev/arc-ui/HEAD/.github/assets/ui.png -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/📗-documentation-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F4D7 Documentation Issue" 3 | about: Tell us if there is missing or incorrect documentation. 4 | title: '' 5 | labels: docs 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/components/index.css: -------------------------------------------------------------------------------- 1 | @import url("./from-navigator/search-prompt.css"); 2 | @import url("./from-navigator/hover-sidebar/index.css"); 3 | @import url("./from-navigator/alt-menu.css"); 4 | @import url("./from-navigator/screenshot-panel.css"); 5 | @import url("./url-indicator.css"); 6 | @import url("./sidebar.css"); 7 | @import url("./close-dialog.css"); 8 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import { build, error, info } from './utils' 2 | 3 | console.log() 4 | info('check', 'Getting data to start building...') 5 | 6 | try { 7 | build('userChrome.css') 8 | info('build', `output: "userChrome.css"`) 9 | 10 | info('build', 'Complete!') 11 | console.log() 12 | } catch (err) { 13 | error('Got error:', err) 14 | } 15 | -------------------------------------------------------------------------------- /scripts/fix-dev-server.sh: -------------------------------------------------------------------------------- 1 | profiles=$(grep 'Name=' ~/.mozilla/firefox/profiles.ini | sed 's/Name=//g') 2 | 3 | for i in "${!profiles[@]}"; do 4 | user=$(grep --max-count 1 "Path=.*${profiles[$i]}" ~/.mozilla/firefox/profiles.ini | sed 's/Path=//g') 5 | userChromeCSSPath=~/.mozilla/firefox/$user/chrome/userChrome.css 6 | 7 | rm -f "$userChromeCSSPath" 8 | done 9 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/refs/heads/master/src/schemas/json/stylelintrc.json", 3 | "extends": ["stylelint-config-standard", "stylelint-config-rational-order"], 4 | "rules": { 5 | "selector-class-pattern": null, 6 | "selector-id-pattern": null 7 | }, 8 | "ignoreFiles": ["userChrome.css"] 9 | } 10 | -------------------------------------------------------------------------------- /src/components/close-dialog.css: -------------------------------------------------------------------------------- 1 | #window-modal-dialog { 2 | position: absolute; 3 | transform: translate(50%, -50%); 4 | inset: 50% 50% auto auto; 5 | 6 | #commonDialogWindow { 7 | background-color: var(--base-100) !important; 8 | } 9 | 10 | .dialogBox { 11 | border: 3px solid var(--neutral) !important; 12 | border-radius: var(--lg) !important; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /scripts/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | profiles=$(grep 'Name=' ~/.mozilla/firefox/profiles.ini | sed 's/Name=//g') 3 | 4 | for i in "${!profiles[@]}"; do 5 | user=$(grep --max-count 1 "Path=.*${profiles[$i]}" ~/.mozilla/firefox/profiles.ini | sed 's/Path=//g') 6 | userSettings=~/.mozilla/firefox/$user/user.js 7 | userChromeCSSPath=~/.mozilla/firefox/$user/chrome/userChrome.css 8 | 9 | rm -f "$userSettings" "$userChromeCSSPath" 10 | done 11 | 12 | echo "userChrome.css uninstalled!" 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext"], 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleDetection": "force", 7 | "jsx": "react-jsx", 8 | "allowJs": true, 9 | 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "verbatimModuleSyntax": true, 13 | "noEmit": true, 14 | 15 | "skipLibCheck": true, 16 | "strict": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "forceConsistentCasingInFileNames": true 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.5.2/schema.json", 3 | "files": { 4 | "ignoreUnknown": true 5 | }, 6 | "organizeImports": { 7 | "enabled": true 8 | }, 9 | "formatter": { 10 | "indentStyle": "space", 11 | "lineWidth": 120 12 | }, 13 | "linter": { 14 | "rules": { 15 | "style": { 16 | "useNamingConvention": "error" 17 | } 18 | } 19 | }, 20 | "javascript": { 21 | "formatter": { 22 | "semicolons": "asNeeded", 23 | "quoteStyle": "single" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/components/url-indicator.css: -------------------------------------------------------------------------------- 1 | #statuspanel { 2 | max-width: 40% !important; 3 | margin: var(--md) !important; 4 | padding: var(--sm) 0 var(--sm) var(--lg) !important; 5 | background-color: var(--base-100) !important; 6 | border: 2px solid var(--neutral) !important; 7 | border-radius: var(--lg) !important; 8 | } 9 | 10 | #statuspanel-label { 11 | padding: 0 !important; 12 | color: var(--base-content) !important; 13 | font-weight: 600; 14 | font-size: 14px; 15 | background-color: transparent !important; 16 | border: none !important; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/sidebar.css: -------------------------------------------------------------------------------- 1 | #sidebar-header { 2 | border: none !important; 3 | } 4 | 5 | #sidebar-box { 6 | overflow: hidden; 7 | border: 2px solid var(--neutral) !important; 8 | border-radius: var(--lg) !important; 9 | box-shadow: var(--shadow); 10 | 11 | &[sidebarcommand*="sidebar-action"] > #sidebar-header { 12 | display: none !important; 13 | } 14 | } 15 | 16 | :is(#sidebar-switcher-target, #sidebar-close):hover { 17 | background-color: var(--neutral) !important; 18 | } 19 | 20 | #sidebar-splitter { 21 | width: calc(var(--content-padding) / 2) !important; 22 | background-color: transparent !important; 23 | border: none !important; 24 | } 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/🚀-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature request" 3 | about: Suggest an idea for this project. 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arc-ui", 3 | "version": "2.2.0", 4 | "description": "Make your Firefox like the Arc Browser", 5 | "author": "dx.dev ", 6 | "license": "MIT", 7 | "scripts": { 8 | "build": "bun run scripts/build.ts", 9 | "dev": "bun run scripts/dev.ts", 10 | "dev:fix": "./scripts/fix-dev-server.sh" 11 | }, 12 | "devDependencies": { 13 | "@astrojs/cli-kit": "^0.4.1", 14 | "@types/bun": "^1.1.12", 15 | "cli-highlight": "^2.1.11", 16 | "clipboardy": "^4.0.0", 17 | "glob": "^11.0.0", 18 | "lightningcss": "^1.25.1", 19 | "stylelint": "^16.10.0", 20 | "stylelint-config-rational-order": "^0.1.2", 21 | "stylelint-config-standard": "^36.0.1" 22 | }, 23 | "peerDependencies": { 24 | "typescript": "^5.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url("./variables.css"); 2 | @import url("./components/index.css"); 3 | 4 | :root { 5 | --content-padding: var(--md); 6 | --content-border: 1px solid var(--base-200); 7 | --content-border-radius: var(--lg); 8 | --sidebar-width: 300px; 9 | --sidebar-padding: var(--sm); 10 | 11 | font-size: 16px !important; 12 | 13 | &[inFullscreen] { 14 | --content-padding: 0px; 15 | --content-border: none; 16 | --content-border-radius: 0px; 17 | } 18 | 19 | --arc-ui-version: "v2.2.0"; 20 | } 21 | 22 | #browser { 23 | padding: var(--content-padding); 24 | background-color: var(--base-100) !important; 25 | backdrop-filter: blur(1rem); 26 | } 27 | 28 | #tabbrowser-tabpanels { 29 | overflow: hidden; 30 | border: var(--content-border); 31 | border-radius: var(--content-border-radius); 32 | box-shadow: var(--shadow); 33 | } 34 | -------------------------------------------------------------------------------- /src/components/from-navigator/alt-menu.css: -------------------------------------------------------------------------------- 1 | #menubar-items { 2 | position: absolute; 3 | top: var(--md); 4 | left: 200vw; 5 | z-index: 30; 6 | } 7 | 8 | #toolbar-menubar:not([inactive]) #menubar-items { 9 | left: calc(var(--md) + var(--sidebar-correction) * (var(--sidebar-width) + var(--content-padding) / 2)); 10 | } 11 | 12 | #main-menubar { 13 | display: flex !important; 14 | overflow: hidden; 15 | background-color: var(--base-100) !important; 16 | background-image: none !important; 17 | border: 2px solid var(--neutral) !important; 18 | border-radius: var(--lg) !important; 19 | box-shadow: var(--shadow); 20 | transition: background-color var(--transition); 21 | 22 | menu { 23 | padding: var(--md) var(--lg) !important; 24 | border: none !important; 25 | 26 | &:hover, 27 | &[open] { 28 | background-color: var(--neutral) !important; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/🐛-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Report an issue that should be fixed. 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 dx.dev 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* sizing and spacing (reference liftkit) */ 3 | --xs: 0.129rem; 4 | --sm: 0.272rem; 5 | --md: 0.618rem; 6 | --lg: 1rem; 7 | --xl: 1.618rem; 8 | --xxl: 2.618rem; 9 | 10 | /* colors (reference daisy ui) */ 11 | --primary: var(--toolbarbutton-icon-fill) !important; 12 | --primary-content: ; 13 | --secondary: ; 14 | --secondary-content: ; 15 | --accent: ; 16 | --accent-content: ; 17 | --neutral: hsl(from var(--base-100) h s calc(l + 5)); 18 | --neutral-content: ; 19 | --base-100: var(--toolbar-bgcolor); 20 | --base-200: hsl(from var(--base-100) h s calc(l - 5)); 21 | --base-300: hsl(from var(--base-200) h s calc(l - 5)); 22 | --base-content: var(--toolbar-color); 23 | --info: ; 24 | --info-content: ; 25 | --success: #4ade80; 26 | --success-content: ; 27 | --warning: #fcd34d; 28 | --warning-content: ; 29 | --error: #f87171; 30 | --error-content: ; 31 | 32 | /* other */ 33 | --shadow: 0 2px 12px rgb(0 0 0 / 25%); 34 | --transition: 100ms ease-in-out; 35 | 36 | /* firefox adjusts */ 37 | --color-accent-primary: var(--primary) !important; 38 | --toolbar-field-color: var(--base-content) !important; 39 | --toolbarbutton-icon-fill-attention: var(--primary) !important; 40 | --button-primary-bgcolor: var(--primary) !important; 41 | } 42 | -------------------------------------------------------------------------------- /src/components/from-navigator/screenshot-panel.css: -------------------------------------------------------------------------------- 1 | screenshots-buttons { 2 | position: fixed !important; 3 | top: var(--lg) !important; 4 | left: calc(100vw + var(--sidebar-correction) * (var(--sidebar-width) + var(--content-padding) / 2)) !important; 5 | width: calc(2 * 7 * var(--lg) + 4px); 6 | padding: 0 !important; 7 | overflow: hidden; 8 | background-color: var(--base-200) !important; 9 | border: 2px solid var(--neutral) !important; 10 | border-radius: var(--lg) !important; 11 | box-shadow: var(--shadow); 12 | transform: translateX(calc(-100% - 2px - var(--content-padding) - var(--lg))); 13 | } 14 | 15 | #full-page { 16 | margin-left: 0 !important; 17 | } 18 | 19 | #visible-page, 20 | #full-page { 21 | width: calc(7 * var(--lg)); 22 | height: calc(6 * var(--lg)); 23 | padding-bottom: 0 !important; 24 | color: var(--base-content) !important; 25 | background-color: var(--base-200) !important; 26 | border-radius: 0 !important; 27 | outline: none !important; 28 | transition: background-color var(--transition); 29 | 30 | &:hover { 31 | background-color: var(--base-100) !important; 32 | } 33 | } 34 | 35 | .dialogStack.tab-dialog-box.tab-prompt-dialog .dialogTemplate.dialogOverlay .dialogBox { 36 | position: absolute; 37 | inset: 50% 50% auto auto; 38 | border: 3px solid var(--neutral) !important; 39 | border-radius: var(--lg) !important; 40 | box-shadow: var(--shadow) !important; 41 | transform: translate(50%, -50%); 42 | } 43 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/bottom.css: -------------------------------------------------------------------------------- 1 | #navigator-toolbox { 2 | --btn-size: 32px; 3 | } 4 | 5 | #alltabs-button { 6 | display: none; 7 | } 8 | 9 | #firefox-view-button, 10 | #new-tab-button, 11 | #save-to-pocket-button, 12 | #unified-extensions-button, 13 | #fxa-toolbar-menu-button { 14 | position: fixed; 15 | bottom: var(--sidebar-padding); 16 | display: block !important; 17 | } 18 | 19 | #firefox-view-button { 20 | left: var(--sidebar-padding); 21 | } 22 | 23 | #new-tab-button { 24 | right: var(--sidebar-padding); 25 | } 26 | 27 | #save-to-pocket-button, 28 | #unified-extensions-button, 29 | #fxa-toolbar-menu-button { 30 | bottom: calc(var(--sidebar-padding) + 36px / 2); 31 | width: var(--btn-size) !important; 32 | height: var(--btn-size) !important; 33 | transform: translate(-50%, +50%); 34 | } 35 | 36 | #save-to-pocket-button { 37 | left: calc(50% - var(--sidebar-padding) - var(--btn-size)); 38 | } 39 | 40 | #unified-extensions-button { 41 | left: calc(50% + var(--sidebar-padding) + var(--btn-size)); 42 | } 43 | 44 | #fxa-toolbar-menu-button { 45 | left: 50%; 46 | 47 | .toolbarbutton-badge-stack { 48 | width: var(--btn-size) !important; 49 | height: var(--btn-size) !important; 50 | border-radius: var(--md) !important; 51 | transition: background-color var(--transition); 52 | } 53 | 54 | &:hover .toolbarbutton-badge-stack { 55 | background-color: var(--base-100) !important; 56 | } 57 | 58 | &[open] .toolbarbutton-badge-stack { 59 | background-color: var(--neutral) !important; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Available profiles:" 3 | 4 | profiles=$(grep 'Name=' ~/.mozilla/firefox/profiles.ini | sed 's/Name=//g') 5 | 6 | for i in "${!profiles[@]}"; do 7 | echo "$((i + 1))=${profiles[$i]}" 8 | done 9 | 10 | echo "Specify which profile you want the theme to apply to (enter the number):" 11 | read -r choice 12 | 13 | selected_profile=${profiles[$((choice - 1))]} 14 | 15 | echo "You selected: $selected_profile" 16 | user=$(grep --max-count 1 "Path=.*$selected_profile" ~/.mozilla/firefox/profiles.ini | sed 's/Path=//g') 17 | 18 | echo "Profile path: $user" 19 | 20 | userSettings=~/.mozilla/firefox/$user/user.js 21 | userChromeCSSPath=~/.mozilla/firefox/$user/chrome/userChrome.css 22 | 23 | mkdir -p "$HOME/.mozilla/firefox/$user/chrome" 24 | touch "$userChromeCSSPath" 25 | 26 | curl -L https://github.com/dxdotdev/arc-ui-theme/releases/latest/download/userChrome.css >"$userChromeCSSPath" 27 | 28 | if [ ! -e "$userSettings" ] || (! grep 'toolkit.legacyUserProfileCustomizations.stylesheets' "$userSettings"); then 29 | echo 'user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);' >>"$userSettings" 30 | fi 31 | 32 | if [ ! -e "$userSettings" ] || (! grep 'browser.urlbar.maxRichResults' "$userSettings"); then 33 | echo 'user_pref("browser.urlbar.maxRichResults", true);' >>"$userSettings" 34 | fi 35 | 36 | if [ ! -e "$userSettings" ] || (! grep 'browser.tabs.loadBookmarksInTabs' "$userSettings"); then 37 | echo 'user_pref("browser.tabs.loadBookmarksInTabs", true);' >>"$userSettings" 38 | fi 39 | 40 | echo "userChrome.css installed!" 41 | -------------------------------------------------------------------------------- /scripts/utils.ts: -------------------------------------------------------------------------------- 1 | import { color, label } from '@astrojs/cli-kit' 2 | import { bundle } from 'lightningcss' 3 | 4 | export function time(): string { 5 | return new Date().toLocaleTimeString() 6 | } 7 | 8 | export function info(title: string, text: string) { 9 | console.log(`${time()}${label(`[${title}]`, color.visible, color.blue)}${text}`) 10 | } 11 | 12 | export function error(text: string, error: unknown) { 13 | console.log(`${time()}${label('[error]', color.visible, color.red)}${text}`) 14 | console.log(`\n${error}\n`) 15 | } 16 | 17 | export function build(path: string) { 18 | try { 19 | const { code } = bundle({ 20 | filename: './src/index.css', 21 | minify: true, 22 | }) 23 | 24 | Bun.write(path, code) 25 | } catch (err) { 26 | error('Got error:', err) 27 | } 28 | } 29 | 30 | export const autoReloadCode = ` 31 | let io = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); 32 | let ss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); 33 | let ds = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); 34 | 35 | let chromepath = ds.get("UChrm", Ci.nsIFile); 36 | chromepath.append("userChrome.css"); 37 | let chromefile = io.newFileURI(chromepath); 38 | 39 | function updateUserChromeCss() { 40 | if (ss.sheetRegistered(chromefile, ss.USER_SHEET)) 41 | ss.unregisterSheet(chromefile, ss.USER_SHEET); 42 | 43 | ss.loadAndRegisterSheet(chromefile, ss.USER_SHEET); 44 | } 45 | 46 | let userChromeCssUpdater = setInterval(updateUserChromeCss, 2500);\n` 47 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/bookmarks.css: -------------------------------------------------------------------------------- 1 | #OtherBookmarks, 2 | #PlacesChevron, 3 | #personal-toolbar-empty-description { 4 | display: none; 5 | } 6 | 7 | #PersonalToolbar { 8 | max-height: none !important; 9 | padding: 0 !important; 10 | background-color: transparent !important; 11 | 12 | &[collapsed="true"] { 13 | display: none; 14 | } 15 | } 16 | 17 | #PlacesToolbarItems { 18 | display: grid !important; 19 | gap: var(--sidebar-padding); 20 | padding-top: calc(2 * var(--sidebar-padding) + var(--urlbar-container-height)); 21 | 22 | &:has(.bookmark-item:nth-child(2)) { 23 | grid-template-columns: repeat(2, 1fr); 24 | } 25 | 26 | &:has(.bookmark-item:nth-child(3)) { 27 | grid-template-columns: repeat(3, 1fr); 28 | } 29 | 30 | &:has(.bookmark-item:nth-child(4)) { 31 | grid-template-columns: repeat(4, 1fr); 32 | } 33 | 34 | .bookmark-item { 35 | max-width: none !important; 36 | min-height: var(--urlbar-container-height); 37 | margin: 0 !important; 38 | padding: var(--sm) !important; 39 | background-color: var(--base-100) !important; 40 | border-radius: var(--lg) !important; 41 | visibility: visible !important; 42 | transition: background-color var(--transition); 43 | 44 | &:hover { 45 | background-color: var(--neutral) !important; 46 | } 47 | 48 | .toolbarbutton-icon { 49 | width: calc(2 * var(--md)) !important; 50 | height: calc(2 * var(--md)) !important; 51 | margin-inline-end: 0 !important; 52 | } 53 | 54 | .toolbarbutton-text { 55 | display: none !important; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/top.css: -------------------------------------------------------------------------------- 1 | #titlebar { 2 | height: var(--xxl) !important; 3 | } 4 | 5 | #nav-bar { 6 | --toolbar-bgcolor: transparent; 7 | 8 | position: absolute !important; 9 | inset: var(--sidebar-padding) var(--sidebar-padding) auto auto; 10 | height: var(--xxl) !important; 11 | border: none !important; 12 | } 13 | 14 | .titlebar-buttonbox-container { 15 | position: absolute; 16 | inset: var(--sidebar-padding) auto auto var(--sidebar-padding); 17 | height: var(--xxl) !important; 18 | } 19 | 20 | .titlebar-button { 21 | padding-inline: calc(var(--sm) / 2) !important; 22 | 23 | image { 24 | width: 0.95rem !important; 25 | height: 0.95rem !important; 26 | margin-top: calc(-1.6 * var(--sm)) !important; 27 | background-color: var(--neutral) !important; 28 | background-image: none !important; 29 | transition: background-color var(--transition); 30 | } 31 | 32 | &:where(.titlebar-max, .titlebar-restore):hover image { 33 | background-color: var(--success) !important; 34 | } 35 | 36 | &.titlebar-close:hover image { 37 | background-color: var(--error) !important; 38 | } 39 | 40 | &.titlebar-min:hover image { 41 | background-color: var(--warning) !important; 42 | } 43 | } 44 | 45 | #PanelUI-menu-button, 46 | #downloads-button { 47 | .toolbarbutton-badge-stack { 48 | border-radius: var(--md) !important; 49 | transition: background-color var(--transition); 50 | } 51 | 52 | &:hover .toolbarbutton-badge-stack { 53 | background-color: var(--base-100) !important; 54 | } 55 | 56 | &[open] .toolbarbutton-badge-stack { 57 | background-color: var(--neutral) !important; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to Arc UI contributing guide 2 | 3 | Thank you for investing your time in contributing to Arc UI! Any contribution you make will be amazing :sparkles:. 4 | 5 | In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR. 6 | 7 | ## Setup Local Development Environment 8 | 9 | The Arc UI repo is using [bun](https://bun.sh). Make sure you have the [latest version of bun](https://github.com/oven-sh/bun/releases) installed in your system. To run the development server: 10 | 11 | 1. Clone this repository 12 | 13 | 2. In the root of this project, run `bun install` to install all of the necessary dependencies 14 | 15 | 3. To run the development server, run `bun run dev` 16 | 17 | 4. And follow the instructions in the command 18 | 19 | **Obs:** Sometimes Firefox stops updating on changes, to solve this follow the instructions: 20 | 21 | 1. Close Firefox and stop development server 22 | 23 | 2. Run the command `bun run dev:fix` 24 | 25 | 3. Open Firefox, run development server again and follow instructions normally 26 | 27 | ## Pull Request Guidelines 28 | 29 | - Checkout a topic branch from a base branch (e.g. `main`), and merge back against that branch. 30 | 31 | - If adding a new feature: 32 | 33 | - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first, and have it approved before working on it. 34 | 35 | - If fixing a bug: 36 | 37 | - If you are resolving a special issue, please add the issues number in the PR's description. 38 | 39 | - Provide a detailed description of the bug in the PR. Live demo preferred. 40 | 41 | - It's OK to have multiple small commits as you work on the PR. GitHub can automatically squash them before merging. 42 | 43 | ## Thanks :purple_heart: 44 | 45 | Thanks for all your contributions and efforts towards improving Arc UI. We thank you for being part of our :sparkles: community :sparkles:! 46 | -------------------------------------------------------------------------------- /scripts/dev.ts: -------------------------------------------------------------------------------- 1 | import { existsSync, unlinkSync, watch } from 'node:fs' 2 | import { homedir } from 'node:os' 3 | import { highlight } from 'cli-highlight' 4 | import clipboard from 'clipboardy' 5 | 6 | import { autoReloadCode, build, error, info } from './utils' 7 | 8 | console.log() 9 | info('check', 'Checking data to start watching...') 10 | 11 | try { 12 | const profilesConfig = await Bun.file(`${homedir()}/.mozilla/firefox/profiles.ini`).text() 13 | 14 | const pathLine = profilesConfig.split('\n').find((s) => s.startsWith('Path=')) 15 | const userFolder = pathLine?.split('=')[1] 16 | const userChromeCssPath = `${homedir()}/.mozilla/firefox/${userFolder}/chrome/userChrome.css` 17 | 18 | info('check', `UserChrome.css file path: ${userChromeCssPath}`) 19 | 20 | if (existsSync(userChromeCssPath)) { 21 | info('check', 'Deleting previous userChrome.css file..') 22 | unlinkSync(userChromeCssPath) 23 | } 24 | 25 | info( 26 | 'watch', 27 | 'Watching for file changes! Paste this command into Firefox Browser Toolbox to enable the updater (Ctrl+Alt+Shift+I):', 28 | ) 29 | 30 | console.log(highlight(autoReloadCode, { language: 'javascript' })) 31 | 32 | try { 33 | clipboard.writeSync(autoReloadCode) 34 | info('clipboard', 'Copied code to clipboard!') 35 | } catch (err) { 36 | error("Can't to copy code to clipboard:", err) 37 | } 38 | 39 | info('watch', 'To stop the updater, run:') 40 | console.log( 41 | highlight(' clearInterval(userChromeCssUpdater)', { 42 | language: 'javascript', 43 | }), 44 | ) 45 | console.log() 46 | 47 | info('watch', 'Change detected') 48 | build(userChromeCssPath) 49 | 50 | let changeCounter = 0 51 | 52 | watch(import.meta.dir.replace('/scripts', '/src'), { recursive: true }, () => { 53 | if (changeCounter === 0) { 54 | info('watch', 'Change detected') 55 | build(userChromeCssPath) 56 | 57 | changeCounter++ 58 | return 59 | } 60 | 61 | changeCounter = 0 62 | }) 63 | } catch (err) { 64 | error('Got error:', err) 65 | } 66 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [userChrome.css]: https://www.userchrome.org/ 2 | [Arc Browser]: https://arc.net/ 3 | [install the userChrome.css manually]: https://www.reddit.com/r/FirefoxCSS/wiki/index/tutorials/#wiki_create_the_folder_and_its_files 4 | [latest release]: https://github.com/dxdotdev/arc-ui/releases/latest 5 | [Zen Browser]: https://zen-browser.app/ 6 | 7 | ## WARNING: 8 | 9 | As the [Zen Browser] has gained a lot of attention lately and is proving to be a promising project, I'm leaving this project aside and focusing on open-source contributions to improve Zen Browser. 10 | 11 | If you want an alternative to this project give it a try: [Zen Browser]. 12 | 13 |
14 | 15 |
16 | 17 | 18 |

Arc UI

19 |

Make your Firefox like the Arc Browser

20 |
21 | 22 |
23 | InstallFeaturesContributing 24 |
25 | 26 |
27 | 28 | Arc UI is a custom [userChrome.css] packed with styles to make your browser look and feel like [Arc Browser]. 29 | 30 | 31 | 32 |
33 | 34 | ## Install 35 | 36 | To install the userChrome.css, close Firefox and follow the steps below: 37 | 38 |
39 | Linux 40 | 41 | Just run the command: 42 | 43 | ```bash 44 | bash -c "$(curl https://raw.githubusercontent.com/dxdotdev/arc-ui/main/scripts/install.sh)" 45 | ``` 46 | 47 | And restart your Firefox. 48 | 49 |
50 | 51 |
52 | Windows 53 | 54 | You can [install the userChrome.css manually] in windows (auto install script in development). 55 | 56 | The Arc UI userChrome.css can be found and downloaded in the [latest release]. 57 | 58 |
59 | 60 | ## Uninstall 61 | 62 | To uninstall the userChrome.css follow the instructions: 63 | 64 |
65 | Linux 66 | 67 | Just run the command: 68 | 69 | ```bash 70 | bash -c "$(curl https://raw.githubusercontent.com/dxdotdev/arc-ui/main/scripts/uninstall.sh)" 71 | ``` 72 | 73 | And restart your Firefox. 74 | 75 |
76 | 77 |
78 | Windows 79 | 80 | Delete the userChrome.css file specified in the windows manual [installation](#install) guide. 81 | 82 |
83 | 84 | ## Contributing 85 | 86 | See [Contributing Guide](./.github/CONTRIBUTING.md). 87 | -------------------------------------------------------------------------------- /src/components/from-navigator/search-prompt.css: -------------------------------------------------------------------------------- 1 | #urlbar-container { 2 | position: fixed !important; 3 | top: 28vh; 4 | left: calc( 5 | 50vw - 6 | 2px - 7 | var(--content-padding) + 8 | var(--sidebar-correction) * 9 | (var(--sidebar-width) + var(--content-padding) / 2) 10 | ); 11 | z-index: 10; 12 | width: clamp(35rem, 35rem + 35vw, 46rem) !important; 13 | transform: translateX(-50%); 14 | } 15 | 16 | #urlbar { 17 | padding: var(--sm) !important; 18 | background-color: var(--base-200) !important; 19 | border: 2px solid var(--neutral) !important; 20 | border-radius: var(--lg) !important; 21 | box-shadow: var(--shadow); 22 | backdrop-filter: blur(1rem); 23 | transition: none !important; 24 | } 25 | 26 | #urlbar-background { 27 | background-color: transparent !important; 28 | border: none !important; 29 | border-radius: calc(var(--lg) - 2px) !important; 30 | outline: none !important; 31 | } 32 | 33 | .urlbar-input-container { 34 | margin-bottom: var(--sm); 35 | } 36 | 37 | #urlbar-search-mode-indicator { 38 | height: var(--xl); 39 | margin-top: -2px; 40 | background-color: var(--neutral) !important; 41 | border-radius: var(--md) !important; 42 | } 43 | 44 | .urlbar-icon { 45 | margin: auto 0; 46 | } 47 | 48 | .urlbar-input-box { 49 | font-weight: 600; 50 | font-size: 18px !important; 51 | } 52 | 53 | #identity-box { 54 | margin-top: -2px; 55 | } 56 | 57 | #identity-icon-label { 58 | display: none !important; 59 | } 60 | 61 | .urlbar-go-button { 62 | margin-top: -2px; 63 | border-radius: var(--sm) !important; 64 | transition: background-color var(--transition); 65 | 66 | &:hover { 67 | background-color: var(--neutral) !important; 68 | } 69 | } 70 | 71 | #urlbar-results { 72 | display: flex !important; 73 | flex-direction: column; 74 | gap: calc(var(--sm) / 3) !important; 75 | } 76 | 77 | .urlbarView-body-inner, 78 | .search-one-offs { 79 | border: none !important; 80 | } 81 | 82 | .urlbarView-body-outer { 83 | border-top: 2px solid var(--neutral); 84 | border-bottom: 2px solid var(--neutral); 85 | } 86 | 87 | .urlbarView-row { 88 | height: var(--urlbar-container-height) !important; 89 | border-radius: var(--lg) !important; 90 | transition: background-color var(--transition); 91 | 92 | &[selected], 93 | &:hover { 94 | background-color: var(--neutral) !important; 95 | } 96 | } 97 | 98 | .searchbar-engine-one-off-item[selected] { 99 | background-color: var(--base-100) !important; 100 | } 101 | 102 | .search-one-offs { 103 | height: var(--urlbar-container-height) !important; 104 | 105 | & > * { 106 | margin: auto 0 !important; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/search-input.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --urlbar-container-height: calc(3.5 * var(--lg)) !important; 3 | } 4 | 5 | #urlbar, 6 | #urlbar-container, 7 | #urlbar-input-container { 8 | --urlbar-height: var(--xl) !important; 9 | --urlbar-toolbar-height: calc(3.5 * var(--lg)) !important; 10 | --urlbar-container-height: calc(3.5 * var(--lg)) !important; 11 | } 12 | 13 | .identity-box-button, 14 | #tracking-protection-icon-container, 15 | #notification-popup-box, 16 | .urlbar-page-action { 17 | width: var(--xl) !important; 18 | height: var(--xl) !important; 19 | margin: auto 0; 20 | border-radius: var(--md) !important; 21 | transition: background-color var(--transition); 22 | padding-inline: 0 !important; 23 | 24 | /* stylelint-disable-next-line no-descending-specificity */ 25 | & > * { 26 | margin: auto !important; 27 | } 28 | 29 | &:hover { 30 | background-color: hsl(from var(--neutral) h s calc(l + 10)) !important; 31 | } 32 | } 33 | 34 | #reader-mode-button-icon { 35 | margin-top: -1px !important; 36 | } 37 | 38 | #star-button { 39 | margin-top: -2px !important; 40 | } 41 | 42 | #urlbar-container:not(:has(#urlbar[breakout-extend])) { 43 | width: calc(100% - 2 * var(--sidebar-padding)) !important; 44 | transform: none; 45 | inset: calc(2 * var(--sidebar-padding) + var(--xxl)) auto auto var(--sidebar-padding); 46 | margin-inline: 0 !important; 47 | 48 | #urlbar-background { 49 | box-shadow: none !important; 50 | } 51 | 52 | #urlbar { 53 | height: var(--urlbar-container-height) !important; 54 | padding: 0 var(--md) !important; 55 | background-color: var(--base-100) !important; 56 | border: none !important; 57 | box-shadow: none !important; 58 | transition: background-color var(--transition) !important; 59 | 60 | &:hover { 61 | background-color: var(--neutral) !important; 62 | } 63 | } 64 | 65 | #urlbar-search-mode-indicator { 66 | margin: auto 0; 67 | } 68 | 69 | #identity-box { 70 | margin-top: auto !important; 71 | margin-bottom: auto !important; 72 | } 73 | 74 | .urlbar-go-button { 75 | display: none !important; 76 | } 77 | 78 | #identity-permission-box { 79 | width: auto !important; 80 | padding: 0 var(--sm) !important; 81 | } 82 | 83 | .urlbar-input-container { 84 | padding: 0 !important; 85 | border: none !important; 86 | } 87 | 88 | .urlbar-input-box { 89 | font-size: 16px !important; 90 | } 91 | 92 | &:has(#identity-box.localResource) { 93 | #urlbar-input { 94 | text-overflow: ellipsis; 95 | } 96 | } 97 | } 98 | 99 | #nav-bar:has(#urlbar[breakout-extend])::after { 100 | position: fixed; 101 | top: calc(2 * var(--sidebar-padding) + var(--xxl)); 102 | left: var(--sidebar-padding); 103 | z-index: 10 !important; 104 | width: calc(100% - 2 * var(--sidebar-padding)); 105 | height: var(--urlbar-container-height); 106 | background-color: var(--base-100); 107 | border-radius: var(--lg); 108 | content: ""; 109 | } 110 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | 177 | # sass build 178 | userChrome.css 179 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/index.css: -------------------------------------------------------------------------------- 1 | @import url("./top.css"); 2 | @import url("./search-input.css"); 3 | @import url("./bookmarks.css"); 4 | @import url("./tabs.css"); 5 | @import url("./bottom.css"); 6 | 7 | @property --sidebar-correction { 8 | syntax: ""; 9 | initial-value: 1; 10 | inherits: true; 11 | } 12 | 13 | /* small buttons on sidebar (navigator) */ 14 | #navigator-toolbox .toolbarbutton-1 { 15 | width: 36px; 16 | height: 36px; 17 | padding: 0 !important; 18 | 19 | .toolbarbutton-icon { 20 | border-radius: var(--md) !important; 21 | transition: background-color var(--transition); 22 | } 23 | 24 | &[open] .toolbarbutton-icon, 25 | &:not([disabled]):hover .toolbarbutton-icon { 26 | background-color: var(--base-100) !important; 27 | } 28 | } 29 | 30 | #navigator-toolbox { 31 | --sidebar-correction: 1; 32 | --sidebar-translate: calc(var(--sidebar-width) + var(--content-padding) / 2); 33 | 34 | position: absolute; 35 | z-index: 10; 36 | width: var(--sidebar-width) !important; 37 | height: calc(100vh - var(--content-padding)) !important; 38 | padding: var(--sidebar-padding) !important; 39 | background-color: var(--base-200) !important; 40 | background-image: none !important; 41 | border: 2px solid var(--neutral) !important; 42 | border-radius: var(--lg) !important; 43 | box-shadow: var(--shadow); 44 | transform: translateY(-50%); 45 | backdrop-filter: blur(1rem); 46 | transition: left 150ms ease-in-out, --sidebar-correction 150ms ease-in-out !important; 47 | inset: 50vh auto auto calc(-1 * var(--sidebar-width)); 48 | 49 | &::before, 50 | &::after { 51 | position: absolute; 52 | top: 0; 53 | width: var(--content-padding); 54 | height: 100%; 55 | content: ""; 56 | } 57 | 58 | &::before { 59 | left: calc(-1 * var(--content-padding)); 60 | } 61 | 62 | &::after { 63 | right: calc(-1 * var(--content-padding)); 64 | } 65 | } 66 | 67 | :root:has( 68 | :is( 69 | :is(#placesContext, #tabContextMenu):hover, 70 | :is(#fxa-toolbar-menu-button, #star-button-box)[open], 71 | :is( 72 | #appMenu-popup, 73 | #downloadsPanel, 74 | #notification-popup, 75 | #unified-extensions-panel, 76 | #full-page-translations-panel, 77 | #notification-popup, 78 | #appMenu-notification-popup 79 | )[panelopen] 80 | ) 81 | ) 82 | #navigator-toolbox, 83 | #navigator-toolbox[movingtab], 84 | #navigator-toolbox:has(#toolbar-menubar[inactive]):not( 85 | :has(:is(#urlbar[breakout-extend], screenshots-buttons):hover) 86 | ):hover { 87 | --sidebar-correction: 0; 88 | 89 | left: calc(var(--content-padding) / 2); 90 | } 91 | 92 | .titlebar-spacer, 93 | #customizableui-special-spring1, 94 | #customizableui-special-spring2, 95 | #scrollbutton-up, 96 | #scrollbutton-down, 97 | spacer { 98 | display: none; 99 | } 100 | 101 | #appMenu-popup, 102 | #unified-extensions-panel, 103 | #customizationui-widget-panel, 104 | #full-page-translations-panel, 105 | #editBookmarkPanel { 106 | margin: calc(var(--sm) / 3) auto !important; 107 | } 108 | 109 | :root:has(#notification-popup[panelopen]) #unified-extensions-button { 110 | position: absolute; 111 | top: 0; 112 | right: 0; 113 | z-index: 100; 114 | background-color: var(--base-200) !important; 115 | transform: translate(2px, 3px) !important; 116 | } 117 | 118 | #notification-popup { 119 | width: calc(var(--sidebar-width) - var(--sidebar-padding)); 120 | padding-top: var(--sm); 121 | transform: translateX(0) !important; 122 | } 123 | 124 | #appMenu-notification-popup { 125 | width: calc(var(--sidebar-width) - var(--sidebar-padding) + 4px); 126 | transform: translate(var(--sidebar-padding), var(--sm)) !important; 127 | } 128 | -------------------------------------------------------------------------------- /src/components/from-navigator/hover-sidebar/tabs.css: -------------------------------------------------------------------------------- 1 | #tabbrowser-arrowscrollbox { 2 | --bookmarks-height: 0px; 3 | 4 | position: absolute; 5 | top: calc(2 * var(--urlbar-container-height) + 3 * var(--sidebar-padding) + var(--bookmarks-height)) !important; 6 | left: 0; 7 | width: calc(var(--sidebar-width) - 3 * var(--sidebar-padding)) !important; 8 | max-height: calc(100vh - var(--content-padding) - 4 * var(--urlbar-container-height) - var(--bookmarks-height)) !important; 9 | } 10 | 11 | #navigator-toolbox:not(:has(#PersonalToolbar[collapsed="true"])) { 12 | &:has(#PlacesToolbarItems > .bookmark-item) #tabbrowser-arrowscrollbox { 13 | --bookmarks-height: calc(var(--urlbar-container-height) + var(--sidebar-padding)); 14 | } 15 | 16 | &:has(#PlacesToolbarItems > .bookmark-item:nth-child(5)) #tabbrowser-arrowscrollbox { 17 | --bookmarks-height: calc(2 * (var(--urlbar-container-height) + var(--sidebar-padding))); 18 | } 19 | 20 | &:has(#PlacesToolbarItems > .bookmark-item:nth-child(9)) #tabbrowser-arrowscrollbox { 21 | --bookmarks-height: calc(3 * (var(--urlbar-container-height) + var(--sidebar-padding))); 22 | } 23 | 24 | &:has(#PlacesToolbarItems > .bookmark-item:nth-child(13)) #tabbrowser-arrowscrollbox { 25 | --bookmarks-height: calc(4 * (var(--urlbar-container-height) + var(--sidebar-padding))); 26 | } 27 | 28 | &:has(#PlacesToolbarItems > .bookmark-item:nth-child(17)) #tabbrowser-arrowscrollbox { 29 | --bookmarks-height: calc(5 * (var(--urlbar-container-height) + var(--sidebar-padding))); 30 | } 31 | 32 | &:has(#PlacesToolbarItems > .bookmark-item:nth-child(25)) #tabbrowser-arrowscrollbox { 33 | --bookmarks-height: calc(6 * (var(--urlbar-container-height) + var(--sidebar-padding))); 34 | } 35 | } 36 | 37 | /* stylelint-disable-next-line selector-type-no-unknown */ 38 | scrollbox[part="scrollbox"][flex="1"][orient="horizontal"][smoothscroll="true"] > * { 39 | flex-direction: column !important; 40 | gap: var(--sidebar-padding) !important; 41 | overflow: hidden scroll; 42 | } 43 | 44 | #tabbrowser-tabs { 45 | border-inline: none !important; 46 | padding-inline: 0 !important; 47 | margin-inline: 0 !important; 48 | } 49 | 50 | #tabs-newtab-button { 51 | position: absolute; 52 | top: calc(-1 * (var(--sidebar-padding) + var(--urlbar-container-height))) !important; 53 | width: 100% !important; 54 | height: var(--urlbar-container-height) !important; 55 | border-radius: var(--lg) !important; 56 | transition: background-color var(--transition); 57 | 58 | &:hover { 59 | background-color: var(--base-100) !important; 60 | } 61 | 62 | .toolbarbutton-icon { 63 | width: 2.5rem !important; 64 | height: 2.5rem !important; 65 | margin-top: -1px; 66 | margin-left: -180px; 67 | opacity: 0.7; 68 | } 69 | 70 | &::after { 71 | color: var(--toolbarbutton-icon-fill); 72 | font-weight: 600; 73 | opacity: 0.7; 74 | content: "New Tab"; 75 | } 76 | } 77 | 78 | .tab-background { 79 | height: var(--urlbar-container-height) !important; 80 | margin: 0 !important; 81 | border-radius: var(--lg) !important; 82 | outline: none !important; 83 | transition: background-color var(--transition); 84 | 85 | &[selected] { 86 | background-color: var(--neutral) !important; 87 | box-shadow: none !important; 88 | } 89 | } 90 | 91 | .tabbrowser-tab { 92 | width: 100% !important; 93 | max-width: none !important; 94 | margin-inline: 0 !important; 95 | padding: 0 !important; 96 | transform: translateX(0) !important; 97 | 98 | &:not([fadein]) { 99 | display: none; 100 | } 101 | 102 | &:hover .tab-background:not([selected]) { 103 | background-color: var(--base-100) !important; 104 | } 105 | } 106 | 107 | #tabbrowser-tabs[haspinnedtabs] .tabbrowser-tab { 108 | width: 100% !important; 109 | max-width: none !important; 110 | margin-inline: 0 !important; 111 | padding: 0 !important; 112 | } 113 | 114 | #tabbrowser-tabs[haspinnedtabs] .tabbrowser-tab:nth-child(1 of [fadein]:not([pinned], [hidden])) .tab-stack { 115 | padding-top: var(--sidebar-padding); 116 | border-top: 2px solid var(--base-100); 117 | } 118 | 119 | .tab-content { 120 | gap: var(--sm); 121 | padding: 0 var(--lg) !important; 122 | 123 | .tab-icon-image { 124 | margin-inline-end: 5.5px; 125 | } 126 | 127 | .tab-close-button { 128 | border-radius: var(--sm) !important; 129 | opacity: 0; 130 | transition: all var(--transition); 131 | 132 | &:hover { 133 | background-color: var(--base-200) !important; 134 | } 135 | } 136 | 137 | &:hover .tab-close-button { 138 | opacity: 1; 139 | } 140 | } 141 | 142 | #tab-preview-panel { 143 | --panel-width: calc(var(--sidebar-width) - 4px - 2 * var(--sidebar-padding)) !important; 144 | 145 | margin-top: calc(-1 * var(--urlbar-container-height) - 4px) !important; 146 | margin-left: calc(var(--panel-width) + 2px + var(--sidebar-padding)) !important; 147 | } 148 | 149 | slot[part="content"] { 150 | border: 2px solid var(--neutral) !important; 151 | border-radius: var(--lg) !important; 152 | } 153 | 154 | .tab-preview-text-container { 155 | padding-right: var(--lg) !important; 156 | padding-left: var(--lg) !important; 157 | } 158 | 159 | .tab-preview-thumbnail-container { 160 | width: var(--panel-width) !important; 161 | border-top: 2px solid var(--neutral) !important; 162 | } 163 | -------------------------------------------------------------------------------- /.github/assets/arc-ui-default.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/assets/arc-ui-square.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/assets/arc-ui-square-transparent.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------