opencode-island 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-island",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "A macOS Dynamic Island for OpenCode: live status of every session and agent on your machine, plus permission prompts you can answer without leaving your work.",
5
5
  "keywords": [
6
6
  "opencode",
package/src/gui.tsx CHANGED
@@ -32,6 +32,9 @@ export default Plugin.define({
32
32
  },
33
33
  onBlur: () => {
34
34
  if (!open) return
35
+ // An island that is asking for an answer stays up: the window never
36
+ // has focus, so the app taking focus back would close it mid-question.
37
+ if (state.sessions.some((session) => session.permission)) return
35
38
  open = false
36
39
  island.send(message())
37
40
  },
@@ -16,13 +16,19 @@ import {
16
16
  import type { IslandMessage, PermissionDecision, SessionView } from "../../../state"
17
17
  import { Button } from "@/components/ui/button"
18
18
  import { Toggle } from "@/components/ui/toggle"
19
- import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
20
19
  import { cn } from "@/lib/utils"
21
20
 
22
21
  const EMPTY: IslandMessage = { sessions: [], working: 0, waiting: 0, open: false }
23
22
 
24
23
  type Theme = "light" | "dark" | "system"
25
24
 
25
+ /** The appearance button cycles through the three, one click each. */
26
+ const THEMES: Theme[] = ["light", "dark", "system"]
27
+
28
+ function nextTheme(theme: Theme): Theme {
29
+ return THEMES[(THEMES.indexOf(theme) + 1) % THEMES.length]
30
+ }
31
+
26
32
  function elapsed(ms: number) {
27
33
  if (!ms || ms < 0) return ""
28
34
  const seconds = Math.floor(ms / 1000)
@@ -357,26 +363,22 @@ export function Island() {
357
363
  ) : null}
358
364
 
359
365
  <div className="flex items-center gap-1 border-t px-2 py-1.5">
360
- <ToggleGroup
361
- type="single"
362
- size="sm"
366
+ <Button
363
367
  variant="outline"
364
- value={theme}
365
- onValueChange={(value) => {
366
- if (value) setTheme(value as Theme)
367
- }}
368
- aria-label="Theme"
368
+ size="icon-sm"
369
+ onClick={() => setTheme(nextTheme(theme))}
370
+ aria-label={`Appearance: ${theme}. Click for ${nextTheme(theme)}.`}
371
+ title={`Appearance: ${theme}`}
372
+ className={cn(alert && "border-warning-foreground/30 bg-transparent hover:bg-warning-foreground/10")}
369
373
  >
370
- <ToggleGroupItem value="light" aria-label="Light" title="Light">
374
+ {theme === "light" ? (
371
375
  <Sun weight="duotone" />
372
- </ToggleGroupItem>
373
- <ToggleGroupItem value="dark" aria-label="Dark" title="Dark">
376
+ ) : theme === "dark" ? (
374
377
  <Moon weight="duotone" />
375
- </ToggleGroupItem>
376
- <ToggleGroupItem value="system" aria-label="System" title="System">
378
+ ) : (
377
379
  <Monitor weight="duotone" />
378
- </ToggleGroupItem>
379
- </ToggleGroup>
380
+ )}
381
+ </Button>
380
382
 
381
383
  <span className="flex-1" />
382
384
 
@@ -387,6 +389,7 @@ export function Island() {
387
389
  onPressedChange={setClickThrough}
388
390
  aria-label="Click through"
389
391
  title="Click through"
392
+ className={cn(alert && "border-warning-foreground/30 bg-transparent hover:bg-warning-foreground/10")}
390
393
  >
391
394
  <CursorClick weight="duotone" />
392
395
  </Toggle>
@@ -397,6 +400,7 @@ export function Island() {
397
400
  onPressedChange={setShowLatest}
398
401
  aria-label="Show latest work"
399
402
  title="Show latest work"
403
+ className={cn(alert && "border-warning-foreground/30 bg-transparent hover:bg-warning-foreground/10")}
400
404
  >
401
405
  <ListDashes weight="duotone" />
402
406
  </Toggle>
@@ -1,83 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { type VariantProps } from "class-variance-authority"
5
- import { cn } from "@/lib/utils"
6
- import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
7
-
8
- import { toggleVariants } from "@/components/ui/toggle"
9
-
10
- const ToggleGroupContext = React.createContext<
11
- VariantProps<typeof toggleVariants> & {
12
- spacing?: number
13
- }
14
- >({
15
- size: "default",
16
- variant: "default",
17
- spacing: 0,
18
- })
19
-
20
- function ToggleGroup({
21
- className,
22
- variant,
23
- size,
24
- spacing = 0,
25
- children,
26
- ...props
27
- }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
28
- VariantProps<typeof toggleVariants> & {
29
- spacing?: number
30
- }) {
31
- return (
32
- <ToggleGroupPrimitive.Root
33
- data-slot="toggle-group"
34
- data-variant={variant}
35
- data-size={size}
36
- data-spacing={spacing}
37
- style={{ "--gap": spacing } as React.CSSProperties}
38
- className={cn(
39
- "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
40
- className
41
- )}
42
- {...props}
43
- >
44
- <ToggleGroupContext.Provider value={{ variant, size, spacing }}>
45
- {children}
46
- </ToggleGroupContext.Provider>
47
- </ToggleGroupPrimitive.Root>
48
- )
49
- }
50
-
51
- function ToggleGroupItem({
52
- className,
53
- children,
54
- variant,
55
- size,
56
- ...props
57
- }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
58
- VariantProps<typeof toggleVariants>) {
59
- const context = React.useContext(ToggleGroupContext)
60
-
61
- return (
62
- <ToggleGroupPrimitive.Item
63
- data-slot="toggle-group-item"
64
- data-variant={context.variant || variant}
65
- data-size={context.size || size}
66
- data-spacing={context.spacing}
67
- className={cn(
68
- toggleVariants({
69
- variant: context.variant || variant,
70
- size: context.size || size,
71
- }),
72
- "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
73
- "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
74
- className
75
- )}
76
- {...props}
77
- >
78
- {children}
79
- </ToggleGroupPrimitive.Item>
80
- )
81
- }
82
-
83
- export { ToggleGroup, ToggleGroupItem }