Remove the application title from the header bar

This commit is contained in:
Keavon Chambers 2025-11-06 09:20:51 -08:00
parent 0d76ffd66d
commit 96d73a8570
6 changed files with 33 additions and 132 deletions

View File

@ -3,22 +3,18 @@
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, type AppWindowPlatform, UpdateMenuBarLayout } from "@graphite/messages"; import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, type AppWindowPlatform, UpdateMenuBarLayout } from "@graphite/messages";
import type { PortfolioState } from "@graphite/state-providers/portfolio";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { platformIsMac } from "@graphite/utility-functions/platform";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte"; import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte";
import WindowButtonsLinux from "@graphite/components/window/title-bar/WindowButtonsLinux.svelte"; import WindowButtonsLinux from "@graphite/components/window/title-bar/WindowButtonsLinux.svelte";
import WindowButtonsMac from "@graphite/components/window/title-bar/WindowButtonsMac.svelte";
import WindowButtonsWeb from "@graphite/components/window/title-bar/WindowButtonsWeb.svelte"; import WindowButtonsWeb from "@graphite/components/window/title-bar/WindowButtonsWeb.svelte";
import WindowButtonsWindows from "@graphite/components/window/title-bar/WindowButtonsWindows.svelte"; import WindowButtonsWindows from "@graphite/components/window/title-bar/WindowButtonsWindows.svelte";
import WindowTitle from "@graphite/components/window/title-bar/WindowTitle.svelte";
export let platform: AppWindowPlatform; export let platform: AppWindowPlatform;
export let maximized: boolean; export let maximized: boolean;
const editor = getContext<Editor>("editor"); const editor = getContext<Editor>("editor");
const portfolio = getContext<PortfolioState>("portfolio");
// TODO: Apparently, Safari does not support the Keyboard.lock() API but does relax its authority over certain keyboard shortcuts in fullscreen mode, which we should take advantage of // TODO: Apparently, Safari does not support the Keyboard.lock() API but does relax its authority over certain keyboard shortcuts in fullscreen mode, which we should take advantage of
const ACCEL_KEY = platformIsMac() ? "Command" : "Control"; const ACCEL_KEY = platformIsMac() ? "Command" : "Control";
@ -32,10 +28,6 @@
let entries: MenuListEntry[] = []; let entries: MenuListEntry[] = [];
$: docIndex = $portfolio.activeDocumentIndex;
$: displayName = $portfolio.documents[docIndex]?.displayName || "";
$: windowTitle = `${displayName}${displayName && " - "}Graphite`;
onMount(() => { onMount(() => {
const arraysEqual = (a: KeyRaw[], b: KeyRaw[]): boolean => a.length === b.length && a.every((aValue, i) => aValue === b[i]); const arraysEqual = (a: KeyRaw[], b: KeyRaw[]): boolean => a.length === b.length && a.every((aValue, i) => aValue === b[i]);
const shortcutRequiresLock = (shortcut: LayoutKeysGroup): boolean => { const shortcutRequiresLock = (shortcut: LayoutKeysGroup): boolean => {
@ -67,32 +59,26 @@
</script> </script>
<LayoutRow class="title-bar"> <LayoutRow class="title-bar">
<!-- Menu bar (or on Mac: window buttons) --> {#if platform !== "Mac"}
<LayoutRow class="left"> <!-- Menu bar -->
{#if platform === "Mac"} <LayoutRow>
<WindowButtonsMac />
{:else}
{#each entries as entry} {#each entries as entry}
<TextButton label={entry.label} icon={entry.icon} menuListChildren={entry.children} action={entry.action} flush={true} /> <TextButton label={entry.label} icon={entry.icon} menuListChildren={entry.children} action={entry.action} flush={true} />
{/each} {/each}
{/if} </LayoutRow>
<LayoutRow on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} /> <!-- Spacer -->
</LayoutRow> <LayoutRow class="spacer" on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} />
<!-- Document title --> <!-- Window buttons -->
<LayoutRow class="center" on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()}> <LayoutRow>
<WindowTitle text={windowTitle} /> {#if platform === "Web"}
</LayoutRow> <WindowButtonsWeb />
<!-- Window buttons (except on Mac) --> {:else if platform === "Windows"}
<LayoutRow class="right"> <WindowButtonsWindows {maximized} />
<LayoutRow on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} /> {:else if platform === "Linux"}
{#if platform === "Windows"} <WindowButtonsLinux {maximized} />
<WindowButtonsWindows {maximized} /> {/if}
{:else if platform === "Linux"} </LayoutRow>
<WindowButtonsLinux {maximized} /> {/if}
{:else if platform === "Web"}
<WindowButtonsWeb />
{/if}
</LayoutRow>
</LayoutRow> </LayoutRow>
<style lang="scss" global> <style lang="scss" global>
@ -101,23 +87,15 @@
flex: 0 0 auto; flex: 0 0 auto;
> .layout-row { > .layout-row {
flex: 1 1 100%; flex: 0 0 auto;
&.left { &.spacer {
justify-content: flex-start; flex: 1 1 100%;
} }
&.center { .text-button {
justify-content: center; height: 100%;
} }
&.right {
justify-content: flex-end;
}
}
.text-button {
height: 28px;
} }
} }
</style> </style>

View File

@ -1,47 +0,0 @@
<script lang="ts">
import { getContext } from "svelte";
import type { Editor } from "@graphite/editor";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
const editor = getContext<Editor>("editor");
</script>
<LayoutRow class="window-buttons-mac">
<div class="close" on:click={() => editor.handle.appWindowClose()} />
<div class="minimize" on:click={() => editor.handle.appWindowMinimize()} />
<div class="zoom" on:click={() => editor.handle.appWindowMaximize()} />
</LayoutRow>
<style lang="scss" global>
.window-buttons-mac {
flex: 0 0 auto;
align-items: center;
margin: 0 8px;
div {
flex: 0 0 auto;
align-items: center;
width: 11px;
height: 11px;
border-radius: 50%;
& + div {
margin-left: 8px;
}
&.close {
background: #ff5a52;
}
&.minimize {
background: #e6c029;
}
&.zoom {
background: #54c22b;
}
}
}
</style>

View File

@ -5,7 +5,6 @@
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte"; import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
const fullscreen = getContext<FullscreenState>("fullscreen"); const fullscreen = getContext<FullscreenState>("fullscreen");
@ -17,10 +16,12 @@
} }
</script> </script>
<LayoutRow class="window-buttons-web" on:click={handleClick} tooltip={$fullscreen.windowFullscreen ? "Exit Fullscreen (F11)" : "Enter Fullscreen (F11)"}> <LayoutRow
{#if requestFullscreenHotkeys} class="window-buttons-web"
<TextLabel italic={true}>Go fullscreen to access all hotkeys</TextLabel> on:click={handleClick}
{/if} tooltip={($fullscreen.windowFullscreen ? "Exit Fullscreen (F11)" : "Enter Fullscreen (F11)") +
(requestFullscreenHotkeys ? "\n\nThis provides access to hotkeys normally reserved by the browser" : "")}
>
<IconLabel icon={$fullscreen.windowFullscreen ? "FullscreenExit" : "FullscreenEnter"} /> <IconLabel icon={$fullscreen.windowFullscreen ? "FullscreenExit" : "FullscreenEnter"} />
</LayoutRow> </LayoutRow>
@ -34,13 +35,8 @@
fill: var(--color-e-nearwhite); fill: var(--color-e-nearwhite);
} }
.text-label {
margin-right: 8px;
}
&:hover { &:hover {
background: var(--color-6-lowergray); background: var(--color-6-lowergray);
color: var(--color-f-white);
svg { svg {
fill: var(--color-f-white); fill: var(--color-f-white);

View File

@ -1,19 +0,0 @@
<script lang="ts">
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
export let text: string;
</script>
<LayoutRow class="window-title">
<TextLabel>{text}</TextLabel>
</LayoutRow>
<style lang="scss" global>
.window-title {
flex: 0 0 auto;
align-items: center;
white-space: nowrap;
padding: 0 8px;
}
</style>

View File

@ -139,12 +139,9 @@ export class UpdateWirePathInProgress extends JsMessage {
export class OpenDocument { export class OpenDocument {
readonly id!: bigint; readonly id!: bigint;
@Type(() => DocumentDetails) @Type(() => DocumentDetails)
readonly details!: DocumentDetails; readonly details!: DocumentDetails;
get displayName(): string {
return this.details.displayName;
}
} }
export class DocumentDetails { export class DocumentDetails {
@ -153,10 +150,6 @@ export class DocumentDetails {
readonly isAutoSaved!: boolean; readonly isAutoSaved!: boolean;
readonly isSaved!: boolean; readonly isSaved!: boolean;
get displayName(): string {
return `${this.name}${this.isSaved ? "" : "*"}`;
}
} }
export class Box { export class Box {

View File

@ -579,10 +579,10 @@ fn binary_gcd<T: num_traits::int::PrimInt + std::ops::ShrAssign<i32> + std::ops:
fn equals<T: std::cmp::PartialEq<T>>( fn equals<T: std::cmp::PartialEq<T>>(
_: impl Ctx, _: impl Ctx,
/// One of the two numbers to compare for equality. /// One of the two numbers to compare for equality.
#[implementations(f64, f32, u32, DVec2, &str, String)] #[implementations(f64, f32, u32, DVec2, bool, &str, String)]
value: T, value: T,
/// The other of the two numbers to compare for equality. /// The other of the two numbers to compare for equality.
#[implementations(f64, f32, u32, DVec2, &str, String)] #[implementations(f64, f32, u32, DVec2, bool, &str, String)]
other_value: T, other_value: T,
) -> bool { ) -> bool {
other_value == value other_value == value
@ -593,10 +593,10 @@ fn equals<T: std::cmp::PartialEq<T>>(
fn not_equals<T: std::cmp::PartialEq<T>>( fn not_equals<T: std::cmp::PartialEq<T>>(
_: impl Ctx, _: impl Ctx,
/// One of the two numbers to compare for inequality. /// One of the two numbers to compare for inequality.
#[implementations(f64, f32, u32, DVec2, &str)] #[implementations(f64, f32, u32, DVec2, bool, &str)]
value: T, value: T,
/// The other of the two numbers to compare for inequality. /// The other of the two numbers to compare for inequality.
#[implementations(f64, f32, u32, DVec2, &str)] #[implementations(f64, f32, u32, DVec2, bool, &str)]
other_value: T, other_value: T,
) -> bool { ) -> bool {
other_value != value other_value != value