Compare commits
3 commits
dev
...
tab-shrink
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48a95565bc | ||
|
|
90a7fb7058 | ||
|
|
dff8020a58 |
2 changed files with 38 additions and 34 deletions
|
|
@ -20,6 +20,7 @@
|
||||||
remaining scroll distance > 1px. Hidden defaults make an inactive timeline
|
remaining scroll distance > 1px. Hidden defaults make an inactive timeline
|
||||||
(no overflow) a no-op. Unsupported browsers also degrade to no fades. */
|
(no overflow) a no-op. Unsupported browsers also degrade to no fades. */
|
||||||
[data-slot="titlebar-tabs"] {
|
[data-slot="titlebar-tabs"] {
|
||||||
|
container-type: inline-size;
|
||||||
timeline-scope: --titlebar-tabs-scroll;
|
timeline-scope: --titlebar-tabs-scroll;
|
||||||
|
|
||||||
[data-slot^="titlebar-tabs-fade-"] {
|
[data-slot^="titlebar-tabs-fade-"] {
|
||||||
|
|
@ -27,6 +28,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@container (max-width: 64px) {
|
||||||
|
[data-slot="titlebar-tab-link"] {
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0;
|
||||||
|
padding-inline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slot="titlebar-tab-title"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@supports (animation-timeline: --titlebar-tabs-scroll) and (timeline-scope: --titlebar-tabs-scroll) {
|
@supports (animation-timeline: --titlebar-tabs-scroll) and (timeline-scope: --titlebar-tabs-scroll) {
|
||||||
[data-slot="titlebar-tabs-scroll"] {
|
[data-slot="titlebar-tabs-scroll"] {
|
||||||
scroll-timeline: --titlebar-tabs-scroll x;
|
scroll-timeline: --titlebar-tabs-scroll x;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import {
|
||||||
createMemo,
|
createMemo,
|
||||||
createResource,
|
createResource,
|
||||||
createRoot,
|
createRoot,
|
||||||
createSignal,
|
|
||||||
For,
|
For,
|
||||||
Match,
|
Match,
|
||||||
onMount,
|
onMount,
|
||||||
|
|
@ -33,7 +32,6 @@ import { applyPath, backPath, forwardPath } from "./titlebar-history"
|
||||||
import { projectForSession } from "@/pages/layout/helpers"
|
import { projectForSession } from "@/pages/layout/helpers"
|
||||||
import { SessionTabAvatar } from "@/pages/layout/session-tab-avatar"
|
import { SessionTabAvatar } from "@/pages/layout/session-tab-avatar"
|
||||||
import { makeEventListener } from "@solid-primitives/event-listener"
|
import { makeEventListener } from "@solid-primitives/event-listener"
|
||||||
import { createResizeObserver } from "@solid-primitives/resize-observer"
|
|
||||||
import { createMediaQuery } from "@solid-primitives/media"
|
import { createMediaQuery } from "@solid-primitives/media"
|
||||||
import { readSessionTabsRemovedDetail, SESSION_TABS_REMOVED_EVENT } from "@/components/titlebar-session-events"
|
import { readSessionTabsRemovedDetail, SESSION_TABS_REMOVED_EVENT } from "@/components/titlebar-session-events"
|
||||||
import { useGlobal } from "@/context/global"
|
import { useGlobal } from "@/context/global"
|
||||||
|
|
@ -421,13 +419,6 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
||||||
].filter((v) => v !== undefined)
|
].filter((v) => v !== undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [tabsAreOverflowing, setTabsAreOverflowing] = createSignal(false)
|
|
||||||
let tabScrollRef!: HTMLDivElement
|
|
||||||
|
|
||||||
function refreshTabsAreOverflowing() {
|
|
||||||
setTabsAreOverflowing(tabScrollRef.scrollWidth > tabScrollRef.clientWidth)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class="h-full flex-1 overflow-hidden flex flex-row items-center gap-1.5 px-2 md:pr-3"
|
class="h-full flex-1 overflow-hidden flex flex-row items-center gap-1.5 px-2 md:pr-3"
|
||||||
|
|
@ -465,19 +456,11 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
||||||
/>
|
/>
|
||||||
</TooltipV2>
|
</TooltipV2>
|
||||||
|
|
||||||
<div data-slot="titlebar-tabs" class="relative min-w-0">
|
<div data-slot="titlebar-tabs" class="relative min-w-0 flex-1">
|
||||||
<div
|
<div
|
||||||
data-slot="titlebar-tabs-scroll"
|
class="flex min-w-0 flex-row items-center overflow-hidden [app-region:no-drag]"
|
||||||
class="flex min-w-0 flex-row items-center gap-1.5 overflow-x-auto no-scrollbar [app-region:no-drag]"
|
|
||||||
ref={(el) => {
|
|
||||||
tabScrollRef = el
|
|
||||||
createResizeObserver(el, refreshTabsAreOverflowing)
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div
|
<div class="flex w-full min-w-0 flex-row items-center gap-[min(6px,1cqw)]">
|
||||||
class="flex min-w-0 flex-row items-center gap-1.5"
|
|
||||||
ref={(el) => createResizeObserver(el, refreshTabsAreOverflowing)}
|
|
||||||
>
|
|
||||||
<For each={tabsStore}>
|
<For each={tabsStore}>
|
||||||
{(tab, i) => {
|
{(tab, i) => {
|
||||||
let ref!: HTMLDivElement
|
let ref!: HTMLDivElement
|
||||||
|
|
@ -574,7 +557,6 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
||||||
onClose={() => tabsStoreActions.removeTab(i())}
|
onClose={() => tabsStoreActions.removeTab(i())}
|
||||||
active={currentTab() === tab}
|
active={currentTab() === tab}
|
||||||
activeServer={tab.server === server.key}
|
activeServer={tab.server === server.key}
|
||||||
forceTruncate={tabsAreOverflowing()}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
|
|
@ -631,7 +613,6 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
||||||
aria-label={language.t("command.session.new")}
|
aria-label={language.t("command.session.new")}
|
||||||
/>
|
/>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="flex-1" />
|
|
||||||
<TitlebarV2Right state={v2RightState()} />
|
<TitlebarV2Right state={v2RightState()} />
|
||||||
<Show when={windows() && !electronWindows()}>
|
<Show when={windows() && !electronWindows()}>
|
||||||
<div data-tauri-decorum-tb class="flex flex-row" />
|
<div data-tauri-decorum-tb class="flex flex-row" />
|
||||||
|
|
@ -882,7 +863,6 @@ function TabNavItem(props: {
|
||||||
onNavigate: () => void
|
onNavigate: () => void
|
||||||
active?: boolean
|
active?: boolean
|
||||||
activeServer: boolean
|
activeServer: boolean
|
||||||
forceTruncate?: boolean
|
|
||||||
session: Session
|
session: Session
|
||||||
}) {
|
}) {
|
||||||
const closeTab = (event: MouseEvent) => {
|
const closeTab = (event: MouseEvent) => {
|
||||||
|
|
@ -900,7 +880,8 @@ function TabNavItem(props: {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={props.ref}
|
ref={props.ref}
|
||||||
class="group relative flex h-7 w-56 shrink-0 flex-row items-center gap-1.5 overflow-hidden whitespace-nowrap rounded-[6px] bg-[var(--tab-bg)] px-1.5 [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-background-bg-layer-02)]"
|
data-slot="titlebar-tab"
|
||||||
|
class="group relative flex h-7 min-w-0 max-w-56 flex-1 basis-0 flex-row items-center overflow-hidden whitespace-nowrap rounded-[6px] bg-[var(--tab-bg)] [container-type:inline-size] [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-background-bg-layer-02)]"
|
||||||
data-active={props.active}
|
data-active={props.active}
|
||||||
onMouseDown={(event) => {
|
onMouseDown={(event) => {
|
||||||
if (event.button !== 1) return
|
if (event.button !== 1) return
|
||||||
|
|
@ -918,7 +899,8 @@ function TabNavItem(props: {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
props.onNavigate()
|
props.onNavigate()
|
||||||
}}
|
}}
|
||||||
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 text-[13px] font-medium text-v2-text-text-faint group-data-[active='true']:text-v2-text-text-base"
|
data-slot="titlebar-tab-link"
|
||||||
|
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 px-1.5 text-[13px] font-medium text-v2-text-text-faint group-data-[active='true']:text-v2-text-text-base"
|
||||||
>
|
>
|
||||||
<span data-slot="project-avatar-slot">
|
<span data-slot="project-avatar-slot">
|
||||||
<SessionTabAvatar
|
<SessionTabAvatar
|
||||||
|
|
@ -928,15 +910,16 @@ function TabNavItem(props: {
|
||||||
activeServer={props.activeServer}
|
activeServer={props.activeServer}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span class="min-w-0 flex-1">{session().title}</span>
|
<span data-slot="titlebar-tab-title" class="min-w-0 flex-1">
|
||||||
|
{session().title}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="absolute not-group-hover:not-group-data-[active=true]:not-data-[truncate=true]:left-52 group-hover:right-0 group-data-[active=true]:right-0 data-[truncate=true]:right-0 inset-y-0 flex flex-row items-center pr-1 py-1 w-8 pl-2"
|
class="absolute not-group-hover:not-group-data-[active=true]:left-52 group-hover:right-0 group-data-[active=true]:right-0 inset-y-0 flex flex-row items-center pr-1 py-1 w-8 pl-2"
|
||||||
data-truncate={props.forceTruncate}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 rounded-r-[6px] bg-(image:--inactive-bg) group-hover:bg-(image:--active-bg) group-data-[active=true]:bg-(image:--active-bg)"
|
class="absolute inset-0 rounded-r-[6px] bg-(image:--inactive-bg) group-hover:bg-(image:--active-bg) group-data-[active=true]:bg-(image:--active-bg)"
|
||||||
|
|
@ -974,7 +957,8 @@ function DraftTabItem(props: {
|
||||||
<div
|
<div
|
||||||
ref={props.ref}
|
ref={props.ref}
|
||||||
data-active={props.active}
|
data-active={props.active}
|
||||||
class="group relative flex h-7 w-56 shrink-0 flex-row items-center gap-1.5 overflow-hidden rounded-[6px] bg-[var(--tab-bg)] pl-1.5 pr-8 whitespace-nowrap [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-overlay-simple-overlay-pressed)] focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-[var(--v2-border-border-focus)]"
|
data-slot="titlebar-tab"
|
||||||
|
class="group relative flex h-7 min-w-0 max-w-56 flex-1 basis-0 flex-row items-center overflow-hidden rounded-[6px] bg-[var(--tab-bg)] [container-type:inline-size] whitespace-nowrap [--tab-bg:var(--v2-background-bg-deep)] hover:[--tab-bg:var(--v2-background-bg-layer-02)] data-[active='true']:[--tab-bg:var(--v2-overlay-simple-overlay-pressed)] focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-[var(--v2-border-border-focus)]"
|
||||||
onMouseDown={(event) => {
|
onMouseDown={(event) => {
|
||||||
if (event.button !== 1) return
|
if (event.button !== 1) return
|
||||||
closeTab(event)
|
closeTab(event)
|
||||||
|
|
@ -986,12 +970,15 @@ function DraftTabItem(props: {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
props.onNavigate()
|
props.onNavigate()
|
||||||
}}
|
}}
|
||||||
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 overflow-hidden text-[13px] font-medium leading-5 text-v2-text-text-faint group-data-[active='true']:text-[var(--v2-text-text-base)]"
|
data-slot="titlebar-tab-link"
|
||||||
|
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 overflow-hidden pl-1.5 pr-8 text-[13px] font-medium leading-5 text-v2-text-text-faint group-data-[active='true']:text-[var(--v2-text-text-base)]"
|
||||||
>
|
>
|
||||||
<span class="flex size-4 shrink-0 rotate-90 items-center justify-center">
|
<span class="flex size-4 shrink-0 rotate-90 items-center justify-center">
|
||||||
<IconV2 name="edit" />
|
<IconV2 name="edit" />
|
||||||
</span>
|
</span>
|
||||||
<span class="truncate leading-5">{props.title}</span>
|
<span data-slot="titlebar-tab-title" class="truncate leading-5">
|
||||||
|
{props.title}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="absolute right-0 inset-y-0 flex w-7 items-center justify-center">
|
<div class="absolute right-0 inset-y-0 flex w-7 items-center justify-center">
|
||||||
<IconButtonV2
|
<IconButtonV2
|
||||||
|
|
@ -1019,7 +1006,8 @@ function NewSessionTabItem(props: { ref?: HTMLDivElement; href: string; title: s
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={props.ref}
|
ref={props.ref}
|
||||||
class="group relative flex h-7 w-56 shrink-0 flex-row items-center gap-1.5 overflow-hidden rounded-[6px] bg-[var(--v2-overlay-simple-overlay-pressed)] pl-1.5 pr-8 whitespace-nowrap focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-[var(--v2-border-border-focus)]"
|
data-slot="titlebar-tab"
|
||||||
|
class="group relative flex h-7 min-w-0 max-w-56 flex-1 basis-0 flex-row items-center overflow-hidden rounded-[6px] bg-[var(--v2-overlay-simple-overlay-pressed)] [container-type:inline-size] whitespace-nowrap focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-[var(--v2-border-border-focus)]"
|
||||||
onMouseDown={(event) => {
|
onMouseDown={(event) => {
|
||||||
if (event.button !== 1) return
|
if (event.button !== 1) return
|
||||||
closeTab(event)
|
closeTab(event)
|
||||||
|
|
@ -1028,12 +1016,15 @@ function NewSessionTabItem(props: { ref?: HTMLDivElement; href: string; title: s
|
||||||
<a
|
<a
|
||||||
href={props.href}
|
href={props.href}
|
||||||
aria-current="page"
|
aria-current="page"
|
||||||
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 overflow-hidden text-[13px] font-medium leading-5 text-[var(--v2-text-text-base)]"
|
data-slot="titlebar-tab-link"
|
||||||
|
class="flex h-full min-w-0 flex-1 flex-row items-center gap-1.5 overflow-hidden pl-1.5 pr-8 text-[13px] font-medium leading-5 text-[var(--v2-text-text-base)]"
|
||||||
>
|
>
|
||||||
<span class="flex size-4 shrink-0 rotate-90 items-center justify-center">
|
<span class="flex size-4 shrink-0 rotate-90 items-center justify-center">
|
||||||
<IconV2 name="edit" />
|
<IconV2 name="edit" />
|
||||||
</span>
|
</span>
|
||||||
<span class="truncate leading-5">{props.title}</span>
|
<span data-slot="titlebar-tab-title" class="truncate leading-5">
|
||||||
|
{props.title}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="absolute right-0 inset-y-0 flex w-7 items-center justify-center">
|
<div class="absolute right-0 inset-y-0 flex w-7 items-center justify-center">
|
||||||
<IconButtonV2
|
<IconButtonV2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue