Files
Verso/services/web/frontend/stylesheets/pages/editor/toolbar.scss
T
CopilotCopybotaeaton-overleafcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>Rebeka
fb9fed2b74 Fix dropdown active item outline clipped by adjacent items (#32073)
* Initial plan

* Fix selected item outline overlapping next item in dropdown menus

Replace position:relative + absolute positioning with flexbox layout
on .dropdown-item to prevent stacking context overlap of active outline.

Co-authored-by: aeaton-overleaf <75253002+aeaton-overleaf@users.noreply.github.com>

* Fix invalid HTML - replace `div` with `span` inside dropdown item description container

* Do not suppress keyboard focus outlines in toolbar dropdown menus

* Add explicit keyboard focus ring for dropdown items

* Avoid overlapping link focus rings with inset box-shadow

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aeaton-overleaf <75253002+aeaton-overleaf@users.noreply.github.com>
Co-authored-by: Rebeka <o.dekany@gmail.com>
GitOrigin-RevId: ce4d1b01f04476fd154b6c05a52fc5632bf8b8dc
2026-04-08 08:04:49 +00:00

448 lines
10 KiB
SCSS

@import '../../abstracts/variables';
:root {
--toolbar-border-color: var(--neutral-80);
--toolbar-header-bg-color: var(--neutral-90);
--toolbar-header-btn-border-color: var(--neutral-80);
--toolbar-btn-color: var(--white);
--toolbar-btn-hover-bg-color: var(--neutral-80);
--toolbar-btn-hover-color: var(--white);
--toolbar-btn-active-color: var(--white);
--toolbar-btn-active-bg-color: var(--green-50);
--toolbar-height: #{$toolbar-height};
--toolbar-small-height: #{$toolbar-small-height};
--toolbar-alt-bg-color: var(--neutral-80);
--formatting-btn-color: var(--white);
--formatting-btn-bg: var(--neutral-80);
--formatting-btn-border: var(--neutral-70);
--project-name-color: var(--neutral-40);
--toolbar-filetree-bg-color: var(--neutral-80);
--project-rename-link-color: var(--neutral-40);
--project-rename-link-color-hover: var(--neutral-20);
--editor-header-logo-background: url(../../../../public/img/ol-brand/overleaf-o-white.svg)
center / contain no-repeat;
--editor-toolbar-bg: var(--neutral-80);
--toolbar-dropdown-divider-color: var(--border-dark-divider);
}
.ide-redesign-main {
--toolbar-alt-bg-color: var(--bg-dark-secondary);
--toolbar-btn-color: var(--content-primary-dark);
--toolbar-btn-hover-bg-color: var(--neutral-80);
--toolbar-btn-hover-color: var(--white);
--editor-toolbar-bg: var(--bg-dark-primary);
--toolbar-filetree-bg-color: var(--neutral-80);
.ol-cm-toolbar-portal {
display: flex;
align-items: center;
background-color: var(--editor-toolbar-bg);
.review-panel-header {
align-self: flex-start;
}
}
.ol-cm-toolbar-wrapper {
flex: 1;
width: 100%;
}
.ol-cm-toolbar-wrapper-indented {
width: calc(100% - var(--review-panel-width));
}
}
@include theme('light') {
--toolbar-border-color: var(--neutral-20);
--toolbar-header-bg-color: var(--white);
--toolbar-header-btn-border-color: var(--neutral-20);
--toolbar-btn-color: var(--neutral-70);
--toolbar-btn-hover-bg-color: var(--neutral-10);
--toolbar-btn-hover-color: var(--neutral-70);
--toolbar-btn-active-bg-color: var(--green-50);
--toolbar-alt-bg-color: var(--white);
--formatting-btn-color: var(--neutral-70);
--formatting-btn-bg: transparent;
--formatting-btn-border: var(--neutral-20);
--project-name-color: var(--neutral-70);
--toolbar-filetree-bg-color: var(--white);
--project-rename-link-color: var(--neutral-70);
--project-rename-link-color-hover: var(--neutral-70);
--editor-header-logo-background: url(../../../../public/img/ol-brand/overleaf-o.svg)
center / contain no-repeat;
--editor-toolbar-bg: var(--white);
--toolbar-dropdown-divider-color: var(--border-divider);
.ide-redesign-main {
--toolbar-alt-bg-color: var(--bg-light-secondary);
--toolbar-btn-color: var(--content-primary);
--toolbar-btn-hover-bg-color: var(--neutral-80);
--toolbar-btn-hover-color: var(--white);
--editor-toolbar-bg: var(--white);
--toolbar-filetree-bg-color: var(--white);
}
}
.toolbar {
display: flex;
align-items: center;
height: var(--toolbar-height);
border-bottom: 1px solid var(--toolbar-border-color);
button {
position: relative;
.badge {
position: absolute;
top: 0;
right: 0;
pointer-events: none; // Labels were capturing button/anchor clicks.
.badge-content {
padding: 0;
}
}
}
.toolbar-right,
.toolbar-left {
button:not(.back-to-editor-btn) {
background: transparent;
box-shadow: none;
}
}
.toolbar-right .back-to-editor-btn {
margin-right: var(--spacing-09);
display: flex;
align-items: center;
.toolbar-label {
margin-bottom: 0;
}
}
> a:not(.btn),
> button,
.toolbar-left > a:not(.btn),
.toolbar-left > button,
.toolbar-right > a:not(.btn),
.toolbar-right > button:not(.back-to-editor-btn) {
display: inline-block;
color: var(--toolbar-btn-color);
background-color: transparent;
padding: var(--spacing-01);
line-height: 1;
height: 24px;
border-radius: var(--border-radius-base);
&.toolbar-header-back-projects {
padding: var(--spacing-02) var(--spacing-04) var(--spacing-02);
margin-bottom: var(--spacing-01);
}
&:hover {
text-shadow: none;
color: var(--toolbar-btn-hover-color);
background-color: transparent;
text-decoration: none;
}
&.active,
&:active {
.label {
display: none;
}
color: white;
background-color: var(--bg-info-01);
box-shadow: none;
&:hover {
color: white;
}
}
}
a.btn-full-height,
button.btn-full-height {
border: none;
border-radius: 0;
border-right: 1px solid var(--toolbar-header-btn-border-color);
color: var(--toolbar-btn-color);
padding: var(--spacing-02) var(--spacing-05) var(--spacing-03);
font-size: var(--font-size-05);
max-height: 39px;
&:hover {
text-shadow: none;
background-color: var(--toolbar-btn-hover-bg-color);
color: var(--toolbar-btn-color);
}
&.active,
&:active {
color: var(--white);
background-color: $bg-accent-01;
box-shadow: none;
}
.badge {
top: var(--spacing-01);
right: var(--spacing-02);
}
.spinner-border {
vertical-align: middle;
font-size: var(--font-size-02);
}
&.dropdown-toggle {
line-height: 1;
&::after {
vertical-align: middle;
font-size: var(--font-size-02);
}
}
}
.toolbar-left {
display: flex;
align-items: stretch;
float: left;
text-align: center;
}
.toolbar-right {
display: flex;
align-items: stretch;
flex-grow: 1;
justify-content: flex-end;
a.btn-full-height,
button.btn-full-height {
border-right: 0;
border-left: 1px solid var(--toolbar-header-btn-border-color);
}
}
.toolbar-center {
text-align: center;
text-overflow: ellipsis;
overflow: hidden;
// At small screen sizes, center relative to the left menu and right buttons
width: 100%;
display: flex;
justify-content: center;
}
&.toolbar-header {
align-items: stretch;
background-color: var(--toolbar-header-bg-color);
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 1;
}
.toolbar-item {
display: flex;
justify-content: center;
}
}
.layout-dropdown .dropdown-item {
align-items: center;
}
.toolbar-label {
display: none;
margin: 0 var(--spacing-02);
font-size: var(--font-size-02);
font-weight: 600;
vertical-align: middle;
text-align: left;
@include media-breakpoint-up(lg) {
display: inline-block;
}
&.toolbar-label-multiline {
line-height: 1.1;
}
}
.toolbar-filetree {
@include toolbar-sm-height;
background-color: var(--toolbar-filetree-bg-color);
padding: 0 var(--spacing-03);
flex-shrink: 0;
}
.toolbar-editor {
height: var(--toolbar-small-height);
background-color: var(--editor-toolbar-bg);
padding: 0 5px;
overflow: hidden;
position: relative;
z-index: 10; // Prevent track changes showing over toolbar
}
/**************************************
Toggle Switch
***************************************/
.toggle-switch {
--toggle-switch-height: 26px;
--toggle-switch-padding: var(--spacing-01);
display: inline-flex;
align-items: center;
height: var(--toggle-switch-height);
margin-right: var(--spacing-03);
border-radius: var(--border-radius-full);
background-color: var(--bg-tertiary-themed);
padding: var(--toggle-switch-padding);
}
.toggle-switch-label {
display: inline-block;
float: left;
font-weight: normal;
// It seems we need to set the height explicitly rather than using 100% to get the button to display correctly in Blink
height: calc(var(--toggle-switch-height) - 2 * var(--toggle-switch-padding));
text-align: center;
margin: 0;
cursor: pointer;
user-select: none;
color: var(--content-secondary-themed);
border-radius: var(--border-radius-full);
transition:
color 0.12s ease-out,
background-color 0.12s ease-out,
box-shadow 0.12s ease-out;
overflow: hidden;
span {
display: flex;
align-items: center;
height: 100%;
width: 100%;
padding: 0 var(--spacing-08);
background-size: 200% 100%;
background-position: 0 0;
transition: background-position 0.12s ease-out;
font-size: var(--font-size-02);
font-weight: bold;
}
}
.toggle-switch-input {
@include visually-hidden;
}
.toggle-switch-input:disabled + .toggle-switch-label {
cursor: not-allowed;
}
.toggle-switch-input:checked + .toggle-switch-label {
span {
background-position: -100% 0;
}
color: var(--white);
background-color: var(--bg-accent-01);
border-radius: var(--border-radius-full);
box-shadow: 0 2px 4px rgb(30 37 48 / 16%);
}
.toggle-switch-input:checked:nth-child(2) + .toggle-switch-label {
span {
background-position: 100% 0;
}
}
.editor-toggle-switch {
display: flex;
align-items: center;
white-space: nowrap;
.toggle-switch {
margin-left: var(--spacing-03);
}
.toggle-switch-label span {
background: none;
transition: background 0.12s ease-out;
}
.toggle-switch-label:first-of-type span {
padding-left: var(--spacing-04);
}
.toggle-switch-label:last-of-type span {
padding-right: var(--spacing-04);
border-right: none;
}
}
/**************************************
Formatting buttons
***************************************/
.formatting-btn {
color: var(--formatting-btn-color);
background-color: var(--formatting-btn-bg);
padding: 0;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
border: none;
border-left: 1px solid var(--formatting-btn-border);
border-radius: 0;
&:hover {
color: var(--formatting-btn-color);
}
&.active {
color: var(--white);
background-color: var(--toolbar-btn-active-bg-color);
box-shadow: none;
&:focus {
color: var(--toolbar-btn-active-color);
&:not(:focus-visible) {
outline: none;
}
}
}
&:focus {
color: var(--formatting-btn-color);
}
}
.formatting-btn-icon {
min-width: 32px;
width: 32px;
}
.formatting-btn-icon:last-of-type {
border-right: 1px solid var(--formatting-btn-border);
}
.try-new-editor-button {
.button-content {
gap: var(--spacing-02);
}
}