Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions packages/app/src/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export default function Layout(props: ParentProps) {
const dialog = useDialog()
const command = useCommand()
const theme = useTheme()
const [pendingArchive, setPendingArchive] = createSignal<string | undefined>()
const availableThemeEntries = createMemo(() => Object.entries(theme.themes()))
const colorSchemeOrder: ColorScheme[] = ["system", "light", "dark"]
const colorSchemeLabel: Record<ColorScheme, string> = {
Expand Down Expand Up @@ -519,6 +520,7 @@ export default function Layout(props: ParentProps) {
const index = sessions.findIndex((s) => s.id === session.id)
const nextSession = sessions[index + 1] ?? sessions[index - 1]

setPendingArchive(undefined)
await globalSDK.client.session.update({
directory: session.directory,
sessionID: session.id,
Expand Down Expand Up @@ -589,7 +591,12 @@ export default function Layout(props: ParentProps) {
disabled: !params.dir || !params.id,
onSelect: () => {
const session = currentSessions().find((s) => s.id === params.id)
if (session) archiveSession(session)
if (!session) return
if (pendingArchive() === session.id) {
archiveSession(session)
} else {
setPendingArchive(session.id)
}
},
},
{
Expand Down Expand Up @@ -852,12 +859,25 @@ export default function Layout(props: ParentProps) {
const status = sessionStore.session_status[props.session.id]
return status?.type === "busy" || status?.type === "retry"
})
const isConfirming = () => pendingArchive() === props.session.id
const handleArchiveClick = (e: MouseEvent) => {
e.preventDefault()
e.stopPropagation()
if (isConfirming()) {
archiveSession(props.session)
} else {
setPendingArchive(props.session.id)
}
}
return (
<>
<div
data-session-id={props.session.id}
class="group/session relative w-full rounded-md cursor-default transition-colors
hover:bg-surface-raised-base-hover focus-within:bg-surface-raised-base-hover has-[.active]:bg-surface-raised-base-hover"
onMouseLeave={() => {
if (isConfirming()) setPendingArchive(undefined)
}}
>
<Tooltip placement={props.mobile ? "bottom" : "right"} value={props.session.title} gutter={10}>
<A
Expand Down Expand Up @@ -918,10 +938,14 @@ export default function Layout(props: ParentProps) {
<div class="hidden group-hover/session:flex group-active/session:flex group-focus-within/session:flex text-text-base gap-1 items-center absolute top-1 right-1">
<TooltipKeybind
placement={props.mobile ? "bottom" : "right"}
title="Archive session"
title={isConfirming() ? "Click to confirm" : "Archive session"}
keybind={command.keybind("session.archive")}
>
<IconButton icon="archive" variant="ghost" onClick={() => archiveSession(props.session)} />
<IconButton
icon="archive"
variant={isConfirming() ? "danger" : "ghost"}
onClick={handleArchiveClick}
/>
</TooltipKeybind>
</div>
</div>
Expand Down
18 changes: 18 additions & 0 deletions packages/ui/src/components/icon-button.css
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,24 @@
}
}

&[data-variant="danger"] {
background-color: color-mix(in srgb, var(--surface-critical-strong) 20%, transparent);

[data-slot="icon-svg"] {
color: var(--surface-critical-strong);
}

&:hover:not(:disabled) {
background-color: color-mix(in srgb, var(--surface-critical-strong) 30%, transparent);
}
&:focus:not(:disabled) {
background-color: color-mix(in srgb, var(--surface-critical-strong) 25%, transparent);
}
&:active:not(:disabled) {
background-color: color-mix(in srgb, var(--surface-critical-strong) 35%, transparent);
}
}

&[data-size="normal"] {
width: 24px;
height: 24px;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/icon-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface IconButtonProps extends ComponentProps<typeof Kobalte> {
icon: IconProps["name"]
size?: "normal" | "large"
iconSize?: IconProps["size"]
variant?: "primary" | "secondary" | "ghost"
variant?: "primary" | "secondary" | "ghost" | "danger"
}

export function IconButton(props: ComponentProps<"button"> & IconButtonProps) {
Expand Down