├── .gitignore ├── README.md ├── antonio-lucio.scss ├── documentation ├── changelog.md ├── command-chain-flags.md ├── images │ └── demo-1.png └── roadmap.md ├── styles ├── _index.scss ├── _layout.scss └── _tab-bar.scss └── utilities ├── _hard-coded-property-values.scss ├── _index.scss ├── _mixins.scss └── _selectors.scss /.gitignore: -------------------------------------------------------------------------------- 1 | *.css 2 | *.css.map -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Antonio Lucio 2 | 3 | ![Antonio Lucio demo screenshot 1](documentation/images/demo-1.png) 4 | 5 | Antonio Lucio is a CSS modification for [Vivaldi Browser](https://vivaldi.com) that likens its appearance to the web browser of that one company with a fruit in their logo. 6 | 7 | ## Requirements 8 | 9 | Antonio Lucio will only be applied when all of the following are true: 10 | 11 | - Tab Bar Position is set to "Top" 12 | - "Show Tab Bar" is checked 13 | - Address Bar Position is set to "Top" 14 | - "Show Address Bar" is checked 15 | - For the current theme, "Accent on Window" is checked 16 | - For the current theme, "Transparent Tab Bar" is **not** checked 17 | 18 | ## Customizing Antonio Lucio 19 | 20 | The look and feel of Antonio Lucio can be customized through [Command Chain Flags](/documentation/command-chain-flags.md) without having to modify any CSS code. 21 | 22 | For example, to disable the tabs being stretched to full width: 23 | 24 | 1. [Create a Command Chain](https://help.vivaldi.com/desktop/shortcuts/command-chains/#Create_a_Command_Chain) with the name `al-disable-tabbar-full-width`. 25 | 2. [Open the Toolbar Editor](https://help.vivaldi.com/desktop/appearance-customization/edit-toolbars/#Customize_toolbars) and select "Command Chains" from the dropdown. Grab your created Command Chain and drag it into one of your toolbars. 26 | 27 | ## Roadmap 28 | 29 | Antonio Lucio will be updated regularly to ensure compatibility with the latest stable version of Vivaldi Browser. New functionality may also be added in the future. 30 | 31 | [Click here](./documentation/roadmap.md) for more information on planned features and known issues. 32 | 33 | --- 34 | 35 | Copyright (c) 2023 HKayn 36 | -------------------------------------------------------------------------------- /antonio-lucio.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Antonio Lucio 3 | Version: 1.1.0 4 | Target Vivaldi Browser versions: 6.2 5 | 6 | Antonio Lucio is a CSS modification for Vivaldi Browser that likens its appearance to the web browser of that one company with a fruit in their logo. 7 | 8 | Copyright (c) 2023 HKayn 9 | */ 10 | 11 | @use "styles"; 12 | @use "utilities"; 13 | 14 | :root:has(#{utilities.$select-browser-with-valid-settings}) { 15 | @include styles.layout-styles; 16 | 17 | @include utilities.mixin-bind-command-chain-flag( 18 | "tabbar-full-width", 19 | true 20 | ) { 21 | @include styles.tab-bar-styles; 22 | } 23 | 24 | @include utilities.mixin-bind-command-chain-flag( 25 | "bookmarkbar-over-tabbar", 26 | true 27 | ) { 28 | @include styles.layout-bookmarkbar-over-tabbar; 29 | } 30 | 31 | @include utilities.mixin-bind-command-chain-flag( 32 | "bookmarkbar-center-display", 33 | true 34 | ) { 35 | @include styles.layout-bookmarkbar-center-display; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /documentation/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v1.1.0 (2023-10-21) 4 | 5 | ### Changes 6 | 7 | - The bookmark bar is now positioned between the address bar and the tab bar by default. Thanks [tojaroslaw](https://github.com/tojaroslaw) for suggesting this! 8 | - The Command Chain Flag `al-disable-bookmarkbar-over-tabbar` is now available to revert this bookmark bar placement. 9 | - Items inside the bookmark bar are now centered. 10 | - *This change is inspired by the centered position of the favorites bar in Safari.* 11 | - The Command Chain Flag `al-disable-bookmarkbar-center-display` is now available to revert this behavior. 12 | - Documentation has been updated and simplified. 13 | - The demo image has been updated. 14 | 15 | ### Fixes 16 | 17 | - The menu button is no longer partially covered; changes to the menu button width are now taken into account. 18 | - When the window is not maximized, the menu button will no longer be vertically misplaced. 19 | - Tab titles are now horizontally centered inside their tab once again. 20 | - The stack counter is now vertically centered inside the tab. 21 | 22 | ### Known Issues 23 | 24 | - When "Menu Position" is set to "Horizontal", the horizontal menu will be covered by the address bar. 25 | - When "Use Native Window" is enabled, the address bar will still leave a gap for nonexistent window buttons. 26 | 27 | --- 28 | 29 | ## v1.0.4 (2023-10-14) 30 | 31 | ### Fixes 32 | 33 | - Fixed several text elements not being correctly aligned. 34 | - Fixed position of "Synced Tabs" and "Show Closed Tabs" buttons. 35 | 36 | --- 37 | 38 | ## v1.0.3 (2023-04-23) 39 | 40 | ### Fixes 41 | 42 | - Tab stack borders are no longer taller than the tab. 43 | - Compact tab stacks no longer introduce an unnecessary gap above the tab bar. 44 | 45 | --- 46 | 47 | ## v1.0.2 (2023-04-23) 48 | 49 | ### Fixes 50 | 51 | - Styles are no longer being applied while in fullscreen. 52 | 53 | --- 54 | 55 | ## v1.0.1 (2023-04-20) 56 | 57 | ### Fixes 58 | 59 | - Styles are no longer being applied to the settings page. 60 | 61 | --- 62 | 63 | ## v1.0.0 (2023-04-20) 64 | 65 | First release of Antonio Lucio. 66 | -------------------------------------------------------------------------------- /documentation/command-chain-flags.md: -------------------------------------------------------------------------------- 1 | # Command Chain Flags 2 | 3 | ## Setup Guide 4 | 5 | You can set up Command Chain Flags for specific features by following the steps below. 6 | 7 | 1. [Create a Command Chain](https://help.vivaldi.com/desktop/shortcuts/command-chains/#Create_a_Command_Chain) in the Quick Commands settings of Vivaldi Browser. 8 | 2. Give this command chain a name that matches the flag you would like to apply, for example `al-disable-tabbar-full-width`. 9 | 3. [Open the Toolbar Editor](https://help.vivaldi.com/desktop/appearance-customization/edit-toolbars/#Customize_toolbars) and select "Command Chains" from the dropdown. Grab your created Command Chain and drag it into one of your toolbars. 10 | 11 | ## Available Flags 12 | 13 | ### Grow width of tabs to occupy free space 14 | 15 | *Enabled by default.* 16 | 17 | To disable: `al-disable-tabbar-full-width` 18 | 19 | Individual tabs grow in width to occupy free space in their tab row. 20 | 21 | ### Move bookmark bar over tab bar 22 | 23 | *Enabled by default.* 24 | 25 | To disable: `al-disable-bookmarkbar-over-tabbar` 26 | 27 | The bookmark bar is moved between the address bar and tab bar, and is also colored appropriately. 28 | 29 | ### Center bookmark bar 30 | 31 | *Enabled by default.* 32 | 33 | To disable: `al-disable-bookmarkbar-center-display` 34 | 35 | Items inside the bookmark bar are centered. 36 | 37 | ### *(Coming soon!)* Show only domain name of URLs in address field 38 | 39 | *Enabled by default.* 40 | 41 | To disable: `al-disable-addressfield-show-only-domain-name` 42 | 43 | The address field only shows the domain name of an URL when it is not in focus. 44 | 45 | ## Precedence Rules 46 | 47 | It is currently possible to have flags set that enable and disable the same feature at the same time. Additionally, each feature has a default state according to what I think is the best default experience for Antonio Lucio. 48 | 49 | For each flag, the following precedence rules apply: 50 | 51 | 1. The `disable` flag always disables a feature. 52 | 2. The `enable` flag enables a feature if the `disable` flag is not set. 53 | 3. The default state of a feature applies if neither flag is set. 54 | -------------------------------------------------------------------------------- /documentation/images/demo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HKayn/antonio-lucio/119739f47ae2288f58341b93024e2c78f5987de5/documentation/images/demo-1.png -------------------------------------------------------------------------------- /documentation/roadmap.md: -------------------------------------------------------------------------------- 1 | # Roadmap 2 | 3 | This document contains all information regarding future changes and known issues on Antonio Lucio. 4 | 5 | ## Planned Features 6 | 7 | The following will be added to Antonio Lucio in the future, in no particular order: 8 | 9 | - Command Chain Flags that control whether to show only the domain name in the address field 10 | - Ongoing updates to maintain compatibility with the latest stable Version of Vivaldi Browser. 11 | 12 | ## Known Issues 13 | 14 | - When "Tab Stacking" is set to "Accordion", the border of a tab stack will not correctly enclose all tabs of a stack when expanded. 15 | - When "Menu Position" is set to "Horizontal", the horizontal menu will be covered by the address bar. 16 | - When "Use Native Window" is enabled, the address bar will still leave a gap for nonexistent window buttons. 17 | -------------------------------------------------------------------------------- /styles/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "layout" as layout-*; 2 | @forward "tab-bar" as tab-bar-*; -------------------------------------------------------------------------------- /styles/_layout.scss: -------------------------------------------------------------------------------- 1 | @use "../utilities"; 2 | 3 | @mixin styles { 4 | #header { 5 | z-index: 1; 6 | background-color: var(--colorAccentBg); 7 | } 8 | 9 | .vivaldi, 10 | .window-buttongroup { 11 | transform: scale(var(--uiZoomLevel)); 12 | } 13 | 14 | .vivaldi { 15 | transform-origin: top left; 16 | height: utilities.$value-of-address-bar-height; 17 | margin: 0; 18 | } 19 | 20 | .window-buttongroup { 21 | transform-origin: top right; 22 | } 23 | 24 | #tabs-tabbar-container { 25 | position: relative; 26 | top: 31px; 27 | background-color: var(--colorAccentBgDark); 28 | } 29 | 30 | #tabs-container:not(.none).top { 31 | padding: 0 !important; // override OS specific padding 32 | } 33 | 34 | #tabs-subcontainer { 35 | background-color: var(--colorAccentBgDarker); 36 | } 37 | 38 | .mainbar { 39 | height: 31px; 40 | background-color: var(--colorAccentBgDark); 41 | } 42 | 43 | .toolbar-mainbar.toolbar-visible { 44 | position: fixed; 45 | top: 0; 46 | left: 0; 47 | right: 0; 48 | background-color: var(--colorAccentBg); 49 | border: none; 50 | color: var(--colorAccentFg); 51 | 52 | .UrlBar-AddressField { 53 | background-color: var(--colorAccentBgDark); 54 | border-color: transparent; 55 | color: var(--colorAccentFg); 56 | 57 | &:not(:has(#urlFieldInput:focus)) { 58 | &::before { 59 | content: " "; 60 | order: 2; 61 | flex: 1; 62 | pointer-events: none; 63 | display: inline-block; 64 | min-width: 192px; 65 | } 66 | 67 | > * { 68 | z-index: 1; 69 | } 70 | 71 | > :has(~ .UrlBar-UrlFieldWrapper) { 72 | order: 1; 73 | } 74 | 75 | .UrlBar-UrlFieldWrapper { 76 | position: absolute; 77 | inset: -2px 0 0 0; 78 | height: min-content; 79 | margin-top: auto; 80 | margin-bottom: auto; 81 | 82 | .UrlField--IsEmpty, 83 | .UrlField--HasEditText { 84 | #urlFieldInput { 85 | text-align: center; 86 | } 87 | } 88 | 89 | ~ * { 90 | order: 3; 91 | } 92 | } 93 | } 94 | 95 | .SiteInfoButton.secure, 96 | .SiteInfoButton.certified { 97 | fill: var(--colorAccentFg); 98 | 99 | path { 100 | fill: var(--colorAccentFg); 101 | } 102 | } 103 | 104 | .UrlFragment-Wrapper { 105 | --HighlightColor: var(--colorAccentFg); 106 | --LowlightColor: var(--colorAccentFgFaded); 107 | 108 | width: 100%; 109 | padding: 6px; 110 | justify-content: center; 111 | 112 | .UrlFragment-Link:not(:first-child), 113 | .UrlFragment-HostFragment-Subdomain, 114 | .UrlFragment--Lowlight { 115 | display: none; 116 | } 117 | } 118 | 119 | .UrlBar-UrlObfuscationWarning path { 120 | fill: var(--colorAccentFg); 121 | } 122 | 123 | .pageload { 124 | color: var(--colorAccentFg); 125 | } 126 | } 127 | 128 | .UrlBar-SearchField { 129 | background-color: var(--colorAccentBgDark); 130 | border-color: transparent; 131 | color: var(--colorAccentFg); 132 | } 133 | 134 | .button-toolbar { 135 | &.ExtensionIcon--Hidden { 136 | background-color: var(--colorAccentBgDark); 137 | 138 | &:hover { 139 | background-color: var(--colorAccentBgDarker); 140 | } 141 | } 142 | 143 | > button { 144 | &:hover { 145 | background-color: var(--colorAccentBgDark); 146 | } 147 | 148 | &.button-pressed { 149 | background-image: linear-gradient( 150 | var(--colorAccentBgDarker), 151 | var(--colorAccentBgDark) 152 | ); 153 | } 154 | } 155 | } 156 | } 157 | 158 | #tabs-tabbar-container.top { 159 | margin-top: 8px; 160 | padding-top: 2px; 161 | } 162 | 163 | #browser { 164 | &:not(.maximized) { 165 | .toolbar-mainbar.toolbar-visible { 166 | height: 39px; 167 | } 168 | } 169 | 170 | &.maximized { 171 | #titlebar > * { 172 | height: 39px; 173 | } 174 | 175 | .toolbar-mainbar.toolbar-visible { 176 | height: 39px; 177 | } 178 | } 179 | 180 | &.win { 181 | &.maximized .window-buttongroup > * { 182 | height: 100%; 183 | } 184 | 185 | .toolbar-mainbar.toolbar-visible { 186 | // address bar margins are derived from #tabs-container padding 187 | margin-left: var(--menuWidth); //calc(var(--menuWidth) / var(--uiZoomLevel)); 188 | margin-right: 140px; //calc(140px / var(--uiZoomLevel)); 189 | } 190 | } 191 | 192 | &.mac { 193 | .toolbar-mainbar.toolbar-visible { 194 | // address bar margins are derived from #tabs-container padding 195 | margin-left: 78px; //calc(78px / var(--uiZoomLevel)); 196 | margin-right: 78px; //calc(78px / var(--uiZoomLevel)); 197 | } 198 | 199 | .window-buttongroup { 200 | transform-origin: top left; 201 | height: 38px; 202 | margin: 0; 203 | padding-left: 13px; //calc(13px / var(--uiZoomLevel)); 204 | width: 78px; //calc(78px / var(--uiZoomLevel)); 205 | background-color: var(--colorAccentBg); 206 | align-items: center; 207 | } 208 | } 209 | 210 | &.linux { 211 | &.normal #tabs-tabbar-container.top { 212 | margin-top: 9px; 213 | } 214 | 215 | .window-buttongroup { 216 | top: 10px; //calc(10px / var(--uiZoomLevel)); 217 | } 218 | 219 | .toolbar-mainbar.toolbar-visible { 220 | // address bar margins are derived from #tabs-container padding 221 | margin-left: var(--menuWidth); //calc(var(--menuWidth) / var(--uiZoomLevel)); 222 | margin-right: 90px; //calc(90px / var(--uiZoomLevel)); 223 | } 224 | } 225 | } 226 | } 227 | 228 | @mixin bookmarkbar-over-tabbar { 229 | #browser.bookmark-bar-top { 230 | #tabs-tabbar-container { 231 | top: calc( 232 | utilities.$value-of-address-bar-height + utilities.$value-of-bookmark-bar-height 233 | ); 234 | } 235 | 236 | .bookmark-bar { 237 | position: fixed; 238 | top: utilities.$value-of-address-bar-height; 239 | left: 0; 240 | right: 0; 241 | z-index: 1; 242 | border: none; 243 | 244 | * { 245 | background-color: var(--colorAccentBg) !important; 246 | color: var(--colorAccentFg); 247 | } 248 | 249 | .separator { 250 | border-color: var(--colorAccentFgAlpha); 251 | } 252 | 253 | button { 254 | img, svg { 255 | fill: var(--colorAccentFgFaded); 256 | } 257 | } 258 | } 259 | 260 | .inner { 261 | margin-top: 28px; // TODO: decipher this magic number 262 | 263 | #panels-container { 264 | margin-top: 1px; // aligns top edge of panel with that of webpage 265 | } 266 | } 267 | } 268 | } 269 | 270 | @mixin bookmarkbar-center-display { 271 | #browser { 272 | .bookmark-bar .observer { 273 | justify-content: center; 274 | 275 | .chevron { 276 | position: absolute; 277 | inset: 0 0 0 auto; 278 | } 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /styles/_tab-bar.scss: -------------------------------------------------------------------------------- 1 | @mixin styles { 2 | .tab-strip { 3 | display: flex; 4 | margin-right: 116px; // width of .sync-and-trash-container + the regular 60px margin 5 | 6 | > span { 7 | display: block; 8 | flex: 1; 9 | position: relative; 10 | 11 | &:has(> .tab-position > .tab.active) { 12 | min-width: 30px; 13 | } 14 | 15 | > .tab-position { 16 | transform: unset; 17 | width: unset; 18 | position: absolute; 19 | left: 0; 20 | right: 0; 21 | 22 | .title { 23 | margin-right: 21px; 24 | text-align: center; 25 | display: inline; 26 | margin-top: 3px; 27 | height: min-content; 28 | line-height: unset; 29 | } 30 | } 31 | } 32 | 33 | > :has(.newtab) { 34 | position: absolute; 35 | left: 100%; 36 | 37 | .newtab { 38 | left: 0 !important; // override inline styling 39 | } 40 | } 41 | 42 | .svg-tab-stack { 43 | width: 100% !important; // override inline styling 44 | height: calc(100% + 1px); 45 | } 46 | 47 | .tab { 48 | .stack-counter { 49 | position: absolute; 50 | right: 0; 51 | margin-top: 4px; // eyeballs margin to center the stack counter vertically inside the tab 52 | } 53 | } 54 | 55 | .tab-position.accordion-toggle-arrow { 56 | position: static; 57 | transform: none; 58 | } 59 | } 60 | 61 | .toolbar-tabbar { 62 | position: absolute; 63 | right: 0; 64 | bottom: unset; 65 | } 66 | 67 | #browser { 68 | &:not(.alt-tabs) { 69 | .tab { 70 | &.force-hover .stack-counter { 71 | right: 24px; 72 | } 73 | 74 | .close { 75 | position: absolute; 76 | right: 0; 77 | } 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /utilities/_hard-coded-property-values.scss: -------------------------------------------------------------------------------- 1 | // This file contains properties of UI elements whose values are not accessible via custom properties. 2 | // It migitates the issue of magic numbers by granting them semantic meaning- 3 | 4 | $address-bar-height: 39px; 5 | $bookmark-bar-height: 21px; -------------------------------------------------------------------------------- /utilities/_index.scss: -------------------------------------------------------------------------------- 1 | @forward "hard-coded-property-values" as value-of-*; 2 | @forward "mixins" as mixin-*; 3 | @forward "selectors" as select-*; -------------------------------------------------------------------------------- /utilities/_mixins.scss: -------------------------------------------------------------------------------- 1 | @use "selectors"; 2 | 3 | @mixin highlight-toolbar-component-in-toolbar-editor($selector) { 4 | #browser.toolbar-edit-mode #{$selector} { 5 | opacity: 0.5; 6 | 7 | > button::before { 8 | content: " "; 9 | pointer-events: none; 10 | position: absolute; 11 | inset: 0; 12 | border: 1px dashed; 13 | border-radius: var(--radius); 14 | } 15 | } 16 | } 17 | 18 | $-command-chain-flag-namespace: "al-"; 19 | $-command-chain-flag-prefix-enable: "#{$-command-chain-flag-namespace}enable-"; 20 | $-command-chain-flag-prefix-disable: "#{$-command-chain-flag-namespace}disable-"; 21 | 22 | @mixin bind-command-chain-flag($flag, $enabled-by-default: false) { 23 | @if $enabled-by-default { 24 | @include does-not-exist(#{$-command-chain-flag-prefix-disable}#{$flag}) { 25 | @content; 26 | } 27 | } @else { 28 | @include exists(#{$-command-chain-flag-prefix-enable}#{$flag}) { 29 | @include does-not-exist(#{$-command-chain-flag-prefix-disable}#{$flag}) { 30 | @content; 31 | } 32 | } 33 | } 34 | 35 | @at-root { 36 | #browser:not(.toolbar-edit-mode) 37 | #{selectors.$command-chain-toolbar-component}:has( 38 | button[title="#{$-command-chain-flag-prefix-enable}#{$flag}"], 39 | button[title="#{$-command-chain-flag-prefix-disable}#{$flag}"] 40 | ) { 41 | display: none; 42 | } 43 | 44 | @include highlight-toolbar-component-in-toolbar-editor( 45 | '#{selectors.$command-chain-toolbar-component}:has(button[title="#{$-command-chain-flag-prefix-enable}#{$flag}"], button[title="#{$-command-chain-flag-prefix-disable}#{$flag}"])' 46 | ); 47 | } 48 | } 49 | 50 | @mixin exists($full-flag) { 51 | > :has(:is(#{selectors.$editable-toolbars}) button[title="#{$full-flag}"]) { 52 | @content; 53 | } 54 | } 55 | 56 | @mixin does-not-exist($full-flag) { 57 | > :not( 58 | :has(:is(#{selectors.$editable-toolbars}) button[title="#{$full-flag}"]) 59 | ) { 60 | @content; 61 | } 62 | } -------------------------------------------------------------------------------- /utilities/_selectors.scss: -------------------------------------------------------------------------------- 1 | // This file contains selectors that can be reused and/or are in need of semantic meaning. 2 | 3 | // Settings check intended to act as a failsafe 4 | $browser-with-valid-settings: "#browser.color-behind-tabs-on.tabs-top.address-top:not(.transparent-tabbar, .is-settingspage, .fullscreen)"; 5 | 6 | // Grid items 7 | $title-bar: "#titlebar"; 8 | $title-bar-menu-position-horizontal: "#header .topmenu"; 9 | $address-bar: "#main .toolbar-mainbar"; 10 | $bookmark-bar: "#main .bookmark-bar"; 11 | $panel: "#panels-container"; 12 | $tab-bar: "#main > .inner > :has(#tabs-tabbar-container)"; // TODO: Change this to "#main .tabbar-wrapper" when Vivaldi 5.8 reaches stable. 13 | $footer-has-status-bar: "footer:has(.toolbar-statusbar)"; // This cannot be nested within another :has() 14 | $webpage: "#webview-container"; 15 | 16 | // Other toolbars not listed above 17 | $status-bar: "footer .toolbar-statusbar"; 18 | 19 | // Toolbar components 20 | $command-chain-toolbar-component: ".button-toolbar.toolbar-command"; 21 | $toolbar-editor-modal: "#modal-bg.toolbar-editor"; 22 | $flexible-space: ".toolbar-spacer-flexible"; 23 | 24 | // Combined variables 25 | $editable-toolbars: "#{$address-bar}, #{$panel}, #{$status-bar}"; 26 | --------------------------------------------------------------------------------