| author | |
| committer | |
| log | c1792bc9a6f3c2fa62ee7cb66991b4d6508781a2 |
| tree | 912a068d7dd0e8c2f12acafeaede2b0f993f41e8 |
| parent | 1b4317ec35da7cb4fb416d49f7e2a8673d536d05 |
2 files changed, 54 insertions(+), 39 deletions(-)
apps/web/src/components/RightPanelTabs.tsx+16-9| ... | @@ -7,6 +7,7 @@ import { isElectron } from "~/env"; | ... | @@ -7,6 +7,7 @@ import { isElectron } from "~/env"; |
| 7 | import type { RightPanelSurface } from "~/rightPanelStore"; | 7 | import type { RightPanelSurface } from "~/rightPanelStore"; |
| 8 | import { cn } from "~/lib/utils"; | 8 | import { cn } from "~/lib/utils"; |
| 9 | import { Menu, MenuItem, MenuPopup, MenuTrigger } from "~/components/ui/menu"; | 9 | import { Menu, MenuItem, MenuPopup, MenuTrigger } from "~/components/ui/menu"; |
| 10 | import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip"; | ||
| 10 | import { faviconUrlForOrigin } from "~/lib/favicon"; | 11 | import { faviconUrlForOrigin } from "~/lib/favicon"; |
| 11 | 12 | ||
| 12 | import { PreviewPanelShell, type PreviewPanelMode } from "./preview/PreviewPanelShell"; | 13 | import { PreviewPanelShell, type PreviewPanelMode } from "./preview/PreviewPanelShell"; |
| ... | @@ -185,15 +186,21 @@ export function RightPanelTabs(props: RightPanelTabsProps) { | ... | @@ -185,15 +186,21 @@ export function RightPanelTabs(props: RightPanelTabsProps) { |
| 185 | : "text-muted-foreground hover:bg-accent/60 hover:text-foreground", | 186 | : "text-muted-foreground hover:bg-accent/60 hover:text-foreground", |
| 186 | )} | 187 | )} |
| 187 | > | 188 | > |
| 188 | <button | 189 | <Tooltip> |
| 189 | type="button" | 190 | <TooltipTrigger |
| 190 | className="flex min-w-0 flex-1 items-center gap-1.5" | 191 | render={ |
| 191 | onClick={() => props.onActivate(surface)} | 192 | <button |
| 192 | title={title} | 193 | type="button" |
| 193 | > | 194 | className="flex min-w-0 flex-1 items-center gap-1.5" |
| 194 | <SurfaceIcon surface={surface} sessions={props.previewSessions} /> | 195 | onClick={() => props.onActivate(surface)} |
| 195 | <span className="truncate">{title}</span> | 196 | > |
| 196 | </button> | 197 | <SurfaceIcon surface={surface} sessions={props.previewSessions} /> |
| 198 | <span className="truncate">{title}</span> | ||
| 199 | </button> | ||
| 200 | } | ||
| 201 | /> | ||
| 202 | <TooltipPopup>{title}</TooltipPopup> | ||
| 203 | </Tooltip> | ||
| 197 | <button | 204 | <button |
| 198 | type="button" | 205 | type="button" |
| 199 | className="rounded p-0.5 opacity-0 hover:bg-muted group-hover:opacity-100 focus:opacity-100" | 206 | className="rounded p-0.5 opacity-0 hover:bg-muted group-hover:opacity-100 focus:opacity-100" |
apps/web/src/components/preview/PreviewChromeRow.tsx+38-30| ... | @@ -169,37 +169,45 @@ export function PreviewChromeRow({ | ... | @@ -169,37 +169,45 @@ export function PreviewChromeRow({ |
| 169 | </div> | 169 | </div> |
| 170 | 170 | ||
| 171 | <InputGroup className="group/address h-7 flex-1 rounded-md border-transparent bg-transparent shadow-none before:shadow-none hover:bg-muted/40 focus-within:bg-background"> | 171 | <InputGroup className="group/address h-7 flex-1 rounded-md border-transparent bg-transparent shadow-none before:shadow-none hover:bg-muted/40 focus-within:bg-background"> |
| 172 | <InputGroupInput | 172 | <Tooltip> |
| 173 | ref={inputRef} | 173 | <TooltipTrigger |
| 174 | value={inputFocused ? draft : (displayUrl ?? draft)} | 174 | render={ |
| 175 | className={cn( | 175 | <InputGroupInput |
| 176 | onOpenInBrowser && !inputFocused && "group-hover/address:pe-7 transition-[padding]", | 176 | ref={inputRef} |
| 177 | )} | 177 | value={inputFocused ? draft : (displayUrl ?? draft)} |
| 178 | onChange={(event) => setDraft(event.target.value)} | 178 | className={cn( |
| 179 | onFocus={() => { | 179 | onOpenInBrowser && |
| 180 | setDraft(url); | 180 | !inputFocused && |
| 181 | setInputFocused(true); | 181 | "group-hover/address:pe-7 transition-[padding]", |
| 182 | queueMicrotask(() => inputRef.current?.select()); | 182 | )} |
| 183 | }} | 183 | onChange={(event) => setDraft(event.target.value)} |
| 184 | onBlur={() => { | 184 | onFocus={() => { |
| 185 | setDraft(url); | 185 | setDraft(url); |
| 186 | setInputFocused(false); | 186 | setInputFocused(true); |
| 187 | }} | 187 | queueMicrotask(() => inputRef.current?.select()); |
| 188 | onKeyDown={(event) => { | 188 | }} |
| 189 | if (event.key === "Enter") submit(event); | 189 | onBlur={() => { |
| 190 | if (event.key === "Escape") { | 190 | setDraft(url); |
| 191 | event.preventDefault(); | 191 | setInputFocused(false); |
| 192 | setDraft(url); | 192 | }} |
| 193 | inputRef.current?.blur(); | 193 | onKeyDown={(event) => { |
| 194 | if (event.key === "Enter") submit(event); | ||
| 195 | if (event.key === "Escape") { | ||
| 196 | event.preventDefault(); | ||
| 197 | setDraft(url); | ||
| 198 | inputRef.current?.blur(); | ||
| 199 | } | ||
| 200 | }} | ||
| 201 | placeholder="Search or enter URL" | ||
| 202 | spellCheck={false} | ||
| 203 | disabled={inputDisabled} | ||
| 204 | data-preview-url-input | ||
| 205 | size="sm" | ||
| 206 | /> | ||
| 194 | } | 207 | } |
| 195 | }} | 208 | /> |
| 196 | placeholder="Search or enter URL" | 209 | {!inputFocused && displayUrl ? <TooltipPopup>{url}</TooltipPopup> : null} |
| 197 | spellCheck={false} | 210 | </Tooltip> |
| 198 | disabled={inputDisabled} | ||
| 199 | data-preview-url-input | ||
| 200 | title={!inputFocused && displayUrl ? url : undefined} | ||
| 201 | size="sm" | ||
| 202 | /> | ||
| 203 | {onOpenInBrowser && !inputFocused ? ( | 211 | {onOpenInBrowser && !inputFocused ? ( |
| 204 | <InputGroupAddon | 212 | <InputGroupAddon |
| 205 | align="inline-end" | 213 | align="inline-end" |