feat(website): drop the tmux bar from the hero demo
The demo is the client, not the terminal it happens to run in. Removing the bar takes the tmux window list, session name, host and clock with it, plus the three --tmux-* tokens that existed only to paint it. The scale floor goes too: the terminal now shrinks to whatever width it is given instead of stopping at half size and scrolling sideways, which makes useFitScale's minScale parameter and the media query feeding it dead weight.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { VERSION } from '@/lib/links'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
import { CLOCK, DATE, HOST, SESSION, SHORTCUTS, WINDOWS } from './data'
|
||||
import { SHORTCUTS } from './data'
|
||||
|
||||
interface TuiPaneProps {
|
||||
title: string
|
||||
@@ -54,32 +54,6 @@ export const MacWindow = ({ children }: { children: React.ReactNode }) => (
|
||||
</div>
|
||||
)
|
||||
|
||||
export const TmuxBar = () => (
|
||||
<div className="flex h-[26px] items-center border-b border-[color-mix(in_srgb,var(--color-dust)_25%,transparent)] bg-[var(--tmux-bg)] text-[12.5px] text-[var(--color-phosphor)]">
|
||||
<span className="flex h-full items-center bg-[var(--color-phosphor)] px-2.5 font-bold text-[var(--tmux-bg)]">
|
||||
{SESSION}
|
||||
</span>
|
||||
{WINDOWS.map((w) => (
|
||||
<span
|
||||
key={w.n}
|
||||
className={cn(
|
||||
'flex h-full items-center gap-1.5 px-3',
|
||||
w.active === true
|
||||
? 'bg-[var(--tmux-hl)] font-bold text-[var(--tmux-hl-fg)]'
|
||||
: 'text-[var(--color-phosphor)]',
|
||||
)}
|
||||
>
|
||||
{w.n} <span className="opacity-55">›</span> {w.name}
|
||||
</span>
|
||||
))}
|
||||
<span className="ml-auto flex gap-4 px-3 text-[var(--color-paper)]">
|
||||
<span className="bg-[var(--tmux-hl)] px-2 font-semibold text-[var(--tmux-hl-fg)]">
|
||||
{DATE} · {CLOCK}
|
||||
</span>
|
||||
<span className="font-bold">{HOST}</span>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
|
||||
export interface StatusCounts {
|
||||
active: number
|
||||
|
||||
@@ -41,26 +41,8 @@ export interface TransferRow {
|
||||
rateMbps?: number
|
||||
}
|
||||
|
||||
interface TmuxWindow {
|
||||
n: number
|
||||
name: string
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
export const HOST = 'michels-macbook-pro-m4'
|
||||
export const CLOCK = '01:45 PM'
|
||||
export const DATE = '2026-07-24'
|
||||
export const SESSION = 'develop'
|
||||
export const SHARE = '/Users/micheldegraaf/Downloads/Soulseek'
|
||||
|
||||
export const WINDOWS: readonly TmuxWindow[] = [
|
||||
{ n: 1, name: 'fish #' },
|
||||
{ n: 2, name: 'fish #' },
|
||||
{ n: 3, name: 'fish #' },
|
||||
{ n: 4, name: 'fish #-' },
|
||||
{ n: 5, name: 'fish *', active: true },
|
||||
]
|
||||
|
||||
export const SEARCHES: readonly SearchRow[] = [
|
||||
{ id: 's1', query: 'public domain field recordings', results: 606, status: 'Done' },
|
||||
{ id: 's2', query: 'creative commons ambient', results: 33, status: 'Done' },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react'
|
||||
|
||||
import { MacWindow, ShortcutBar, StatusLine, TmuxBar, type StatusCounts } from './chrome'
|
||||
import { MacWindow, ShortcutBar, StatusLine, type StatusCounts } from './chrome'
|
||||
import {
|
||||
RESULTS,
|
||||
SEARCHES,
|
||||
@@ -362,22 +362,9 @@ export const HeroTerminal = () => {
|
||||
setPhase('interactive')
|
||||
}
|
||||
|
||||
// Below 820px, stop shrinking at half size and let the wrapper scroll.
|
||||
const [minScale, setMinScale] = useState(() =>
|
||||
matches('(max-width: 820px)') ? 0.5 : 0,
|
||||
)
|
||||
useEffect(() => {
|
||||
const query = window.matchMedia('(max-width: 820px)')
|
||||
const sync = (event: MediaQueryListEvent) => {
|
||||
setMinScale(event.matches ? 0.5 : 0)
|
||||
}
|
||||
query.addEventListener('change', sync)
|
||||
return () => {
|
||||
query.removeEventListener('change', sync)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const { wrapRef, innerRef, scale, height, ready } = useFitScale(DESIGN_WIDTH, minScale)
|
||||
// No floor: the terminal shrinks to whatever width it is given rather than
|
||||
// holding a minimum size and scrolling sideways.
|
||||
const { wrapRef, innerRef, scale, height, ready } = useFitScale(DESIGN_WIDTH)
|
||||
|
||||
const shownSearches = searches.map((search, i) =>
|
||||
i === 0 && phase === 'searching' ? { ...search, status: '⋯', results: '—' } : search,
|
||||
@@ -401,7 +388,6 @@ export const HeroTerminal = () => {
|
||||
}}
|
||||
>
|
||||
<MacWindow>
|
||||
<TmuxBar />
|
||||
{/*
|
||||
role="application" is the ARIA escape hatch for a widget that
|
||||
handles its own keys: it stops screen readers intercepting
|
||||
|
||||
@@ -15,11 +15,8 @@ interface FitScale {
|
||||
* looking like a terminal. So it renders at native width and gets a CSS
|
||||
* transform, and the wrapper is told the resulting height so the page below
|
||||
* does not sit under it.
|
||||
*
|
||||
* `minScale` stops the shrink at a floor on small screens — past that the
|
||||
* wrapper scrolls sideways instead, which beats unreadable 4px text.
|
||||
*/
|
||||
export const useFitScale = (designWidth: number, minScale: number): FitScale => {
|
||||
export const useFitScale = (designWidth: number): FitScale => {
|
||||
const wrapRef = useRef<HTMLDivElement>(null)
|
||||
const innerRef = useRef<HTMLDivElement>(null)
|
||||
const [{ scale, height }, setState] = useState({ scale: 0, height: 0 })
|
||||
@@ -36,7 +33,7 @@ export const useFitScale = (designWidth: number, minScale: number): FitScale =>
|
||||
const width = wrap.clientWidth
|
||||
if (width === 0) return
|
||||
|
||||
const next = Math.max(minScale, Math.min(1, width / designWidth))
|
||||
const next = Math.min(1, width / designWidth)
|
||||
const nextHeight = inner.offsetHeight * next
|
||||
if (nextHeight === 0) return
|
||||
|
||||
@@ -58,7 +55,7 @@ export const useFitScale = (designWidth: number, minScale: number): FitScale =>
|
||||
return () => {
|
||||
observer.disconnect()
|
||||
}
|
||||
}, [designWidth, minScale])
|
||||
}, [designWidth])
|
||||
|
||||
return { wrapRef, innerRef, scale, height, ready: scale > 0 }
|
||||
}
|
||||
|
||||
@@ -150,11 +150,6 @@
|
||||
--tui-track: #2a2622;
|
||||
--tui-bezel: #000000;
|
||||
|
||||
/* tmux's own status bar. Emulator chrome, so it does not follow the theme. */
|
||||
--tmux-bg: #0e0c0a;
|
||||
--tmux-hl: #b9a6e8;
|
||||
--tmux-hl-fg: #1a1526;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
@@ -223,10 +218,6 @@
|
||||
* is what the Rust client does. Those names do not flip with the theme, so on
|
||||
* manila they would leave paper-on-paper. Light mode re-cuts the same names
|
||||
* darker, scoped to the terminal's content.
|
||||
*
|
||||
* Deliberately not applied to the tmux bar above it: that is the emulator's
|
||||
* own chrome, it keeps its near-black background in both themes, and needs
|
||||
* the bright phosphor to stay legible against it.
|
||||
*/
|
||||
[data-theme='light'] .tui-content {
|
||||
--color-paper: #14110f;
|
||||
|
||||
Reference in New Issue
Block a user