diff --git a/resources/css/app.css b/resources/css/app.css index a0b80d195..826e5470a 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1174,6 +1174,20 @@ body.terminal-is-fullscreen .terminal-fullscreen-shell [data-terminal-mobile-too box-shadow: none !important; } +/* Reserve the trailing area used by the native select chevron. */ +.application-settings-workspace .select, +.application-settings-form .select { + padding-right: 2.5rem; +} + +@media (max-width: 767px) { + .application-settings-workspace .select, + .application-settings-form .select { + font-size: 0.75rem !important; + line-height: 1.25rem; + } +} + /* Keep password toggle / copy button clear of the value inside denser settings inputs */ .application-settings-workspace .input.input-with-password-toggle, .application-settings-workspace .input[type="password"], diff --git a/resources/views/components/forms/button.blade.php b/resources/views/components/forms/button.blade.php index e57757b32..86423eb9d 100644 --- a/resources/views/components/forms/button.blade.php +++ b/resources/views/components/forms/button.blade.php @@ -26,26 +26,45 @@ @endphp @if ($authDisabled || filled($tooltip)) + x-data="{ + visible: false, + _t: null, + showTooltip(delay = 0) { + clearTimeout(this._t); + this._t = setTimeout(() => { + this.visible = true; + this.positionTooltip(); + }, delay); + }, + hideTooltip() { + clearTimeout(this._t); + this.visible = false; + }, + positionTooltip() { + this.$nextTick(() => requestAnimationFrame(() => { + const tip = this.$refs.tip; + if (!tip) return; + const r = this.$el.getBoundingClientRect(); + const t = tip.getBoundingClientRect(); + let top = r.top - t.height - 6; + let left = r.left; + if (top < 4) top = r.bottom + 6; + if (left + t.width > innerWidth - 8) left = innerWidth - 8 - t.width; + if (left < 4) left = 4; + tip.style.top = top + 'px'; + tip.style.left = left + 'px'; + })); + } + }" + @if ($disabled) tabindex="0" :aria-describedby="visible ? $id('button-tooltip') : null" @endif + @mouseenter="showTooltip(300)" + @mouseleave="hideTooltip()" + @focusin="showTooltip()" + @focusout="hideTooltip()" + @click.outside="hideTooltip()"> @endif @if ($authDisabled || filled($tooltip)) -
+ diff --git a/resources/views/components/helper.blade.php b/resources/views/components/helper.blade.php index 79870196a..1f0581b8c 100644 --- a/resources/views/components/helper.blade.php +++ b/resources/views/components/helper.blade.php @@ -33,6 +33,21 @@ this.pinned = false; this.open = false; }, + closeWhenFocusLeaves() { + this.$nextTick(() => { + const activeElement = document.activeElement; + if (!this.$refs.trigger?.contains(activeElement) && !this.$refs.popup?.contains(activeElement)) { + this.close(); + } + }); + }, + closeWhenPointerIsOutside(event) { + if (!this.open || this.$refs.trigger?.contains(event.target) || this.$refs.popup?.contains(event.target)) { + return; + } + + this.close(); + }, position() { const trigger = this.$refs.trigger; const popup = this.$refs.popup; @@ -56,7 +71,8 @@ this.style = `top: ${top}px; left: ${left}px;`; } -}" @click.outside="close" @keydown.window.escape="close" @resize.window="open && position()" @scroll.window="open && position()" +}" @pointerdown.window="closeWhenPointerIsOutside($event)" @keydown.window.escape="close" + @resize.window="open && position()" @scroll.window="open && position()" {{ $attributes->merge(['class' => 'relative z-10 inline-block align-middle']) }}> {{-- button (not div) so label-for associations do not steal the click on mobile --}}