@opencode-ai/ui 1.18.3 → 1.18.4
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/dist/components/resize-handle.d.ts +2 -0
- package/dist/v2/components/button-v2.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/dock-surface.css +14 -0
- package/src/components/resize-handle.tsx +21 -5
- package/src/components/tabs.css +61 -1
- package/src/v2/components/button-v2.css +23 -0
- package/src/v2/components/button-v2.tsx +1 -1
- package/src/v2/components/dialog-v2.tsx +1 -1
- package/src/v2/components/divider-v2.css +2 -2
- package/src/v2/components/inline-input-v2.css +7 -0
- package/src/v2/components/inline-input-v2.tsx +16 -1
- package/src/v2/components/text-input-v2.css +1 -0
|
@@ -7,6 +7,8 @@ export interface ResizeHandleProps extends Omit<JSX.HTMLAttributes<HTMLDivElemen
|
|
|
7
7
|
max: number;
|
|
8
8
|
onResize: (size: number) => void;
|
|
9
9
|
onCollapse?: () => void;
|
|
10
|
+
/** Called while dragging when size crosses `collapseThreshold`. */
|
|
11
|
+
onCollapseChange?: (collapsed: boolean) => void;
|
|
10
12
|
collapseThreshold?: number;
|
|
11
13
|
}
|
|
12
14
|
export declare function ResizeHandle(props: ResizeHandleProps): JSX.Element;
|
|
@@ -4,7 +4,7 @@ import { type IconProps } from "./icon";
|
|
|
4
4
|
import "./button-v2.css";
|
|
5
5
|
export interface ButtonV2Props extends ComponentProps<typeof Kobalte>, Pick<ComponentProps<"button">, "class" | "classList" | "children"> {
|
|
6
6
|
size?: "small" | "normal" | "large";
|
|
7
|
-
variant?: "neutral" | "danger" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading";
|
|
7
|
+
variant?: "neutral" | "danger" | "warning" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading";
|
|
8
8
|
icon?: IconProps["name"];
|
|
9
9
|
}
|
|
10
10
|
export declare function ButtonV2(props: ButtonV2Props): import("solid-js").JSX.Element;
|
package/package.json
CHANGED
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
overflow: clip;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
[data-dock-border-underlay] {
|
|
11
|
+
/* Later shadows paint underneath, so this solid ring masks overlapping surfaces without changing border geometry. */
|
|
12
|
+
box-shadow:
|
|
13
|
+
var(--dock-shell-visual-shadow, var(--shadow-xs-border)),
|
|
14
|
+
0 0 0 var(--dock-shell-border-underlay-width, 1px)
|
|
15
|
+
var(--dock-shell-border-underlay-background, var(--surface-raised-stronger-non-alpha));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
[data-dock-border-underlay="v2"] {
|
|
19
|
+
--dock-shell-visual-shadow: var(--v2-elevation-raised);
|
|
20
|
+
--dock-shell-border-underlay-width: 0.5px;
|
|
21
|
+
--dock-shell-border-underlay-background: var(--v2-background-bg-base);
|
|
22
|
+
}
|
|
23
|
+
|
|
10
24
|
[data-dock-surface="tray"] {
|
|
11
25
|
background-color: var(--background-base);
|
|
12
26
|
border: 1px solid var(--border-weak-base);
|
|
@@ -8,6 +8,8 @@ export interface ResizeHandleProps extends Omit<JSX.HTMLAttributes<HTMLDivElemen
|
|
|
8
8
|
max: number
|
|
9
9
|
onResize: (size: number) => void
|
|
10
10
|
onCollapse?: () => void
|
|
11
|
+
/** Called while dragging when size crosses `collapseThreshold`. */
|
|
12
|
+
onCollapseChange?: (collapsed: boolean) => void
|
|
11
13
|
collapseThreshold?: number
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -20,17 +22,26 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
|
|
20
22
|
"max",
|
|
21
23
|
"onResize",
|
|
22
24
|
"onCollapse",
|
|
25
|
+
"onCollapseChange",
|
|
23
26
|
"collapseThreshold",
|
|
24
27
|
"class",
|
|
25
28
|
"classList",
|
|
26
29
|
])
|
|
27
30
|
|
|
28
31
|
const handleMouseDown = (e: MouseEvent) => {
|
|
32
|
+
if (e.detail > 1) return
|
|
29
33
|
e.preventDefault()
|
|
30
34
|
const edge = local.edge ?? (local.direction === "vertical" ? "start" : "end")
|
|
31
35
|
const start = local.direction === "horizontal" ? e.clientX : e.clientY
|
|
32
36
|
const startSize = local.size
|
|
37
|
+
const min = local.min
|
|
38
|
+
const max = local.max
|
|
39
|
+
const threshold = local.collapseThreshold ?? 0
|
|
40
|
+
const onResize = local.onResize
|
|
41
|
+
const onCollapse = local.onCollapse
|
|
42
|
+
const onCollapseChange = local.onCollapseChange
|
|
33
43
|
let current = startSize
|
|
44
|
+
let collapsed = false
|
|
34
45
|
|
|
35
46
|
document.body.style.userSelect = "none"
|
|
36
47
|
document.body.style.overflow = "hidden"
|
|
@@ -46,8 +57,12 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
|
|
46
57
|
? start - pos
|
|
47
58
|
: pos - start
|
|
48
59
|
current = startSize + delta
|
|
49
|
-
const
|
|
50
|
-
|
|
60
|
+
const nextCollapsed = threshold > 0 && current < threshold
|
|
61
|
+
if (nextCollapsed !== collapsed) {
|
|
62
|
+
collapsed = nextCollapsed
|
|
63
|
+
onCollapseChange?.(collapsed)
|
|
64
|
+
}
|
|
65
|
+
onResize(Math.min(max, Math.max(min, current)))
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
const onMouseUp = () => {
|
|
@@ -56,10 +71,11 @@ export function ResizeHandle(props: ResizeHandleProps) {
|
|
|
56
71
|
document.removeEventListener("mousemove", onMouseMove)
|
|
57
72
|
document.removeEventListener("mouseup", onMouseUp)
|
|
58
73
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
74
|
+
if (collapsed) {
|
|
75
|
+
onCollapse?.()
|
|
76
|
+
return
|
|
62
77
|
}
|
|
78
|
+
onCollapseChange?.(false)
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
document.addEventListener("mousemove", onMouseMove)
|
package/src/components/tabs.css
CHANGED
|
@@ -723,7 +723,11 @@ body[data-new-layout] #review-panel [data-component="tabs"][data-variant="normal
|
|
|
723
723
|
}
|
|
724
724
|
|
|
725
725
|
&:has([data-slot="tabs-trigger-close-button"]) {
|
|
726
|
-
padding-right:
|
|
726
|
+
padding-right: 8px;
|
|
727
|
+
|
|
728
|
+
[data-slot="tabs-trigger-close-button"] {
|
|
729
|
+
margin-left: 2px;
|
|
730
|
+
}
|
|
727
731
|
}
|
|
728
732
|
|
|
729
733
|
&:has([data-selected]) {
|
|
@@ -789,6 +793,62 @@ body[data-new-layout]
|
|
|
789
793
|
[data-slot="tabs-list"]
|
|
790
794
|
> .sticky {
|
|
791
795
|
padding-right: 0;
|
|
796
|
+
|
|
797
|
+
[data-component="icon-button-v2"] {
|
|
798
|
+
position: relative;
|
|
799
|
+
|
|
800
|
+
&::after {
|
|
801
|
+
content: "";
|
|
802
|
+
position: absolute;
|
|
803
|
+
left: 100%;
|
|
804
|
+
top: 50%;
|
|
805
|
+
transform: translateY(-50%);
|
|
806
|
+
width: 20px;
|
|
807
|
+
height: 28px;
|
|
808
|
+
background-color: var(--v2-background-bg-base);
|
|
809
|
+
pointer-events: none;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
body[data-new-layout]
|
|
815
|
+
#review-panel
|
|
816
|
+
[data-component="tabs"]
|
|
817
|
+
.session-review-v2-tabs-bar
|
|
818
|
+
[data-slot="tabs-list"]
|
|
819
|
+
> .session-review-v2-sidebar-toggle-slot.sticky {
|
|
820
|
+
padding-right: 0;
|
|
821
|
+
|
|
822
|
+
&::before {
|
|
823
|
+
content: "";
|
|
824
|
+
position: absolute;
|
|
825
|
+
top: 50%;
|
|
826
|
+
bottom: auto;
|
|
827
|
+
left: auto;
|
|
828
|
+
right: 100%;
|
|
829
|
+
transform: translateY(-50%);
|
|
830
|
+
width: 12px;
|
|
831
|
+
height: 28px;
|
|
832
|
+
background-color: var(--v2-background-bg-base);
|
|
833
|
+
background-image: none;
|
|
834
|
+
pointer-events: none;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
&::after {
|
|
838
|
+
content: "";
|
|
839
|
+
position: absolute;
|
|
840
|
+
top: 50%;
|
|
841
|
+
left: 100%;
|
|
842
|
+
transform: translateY(-50%);
|
|
843
|
+
width: 8px;
|
|
844
|
+
height: 28px;
|
|
845
|
+
pointer-events: none;
|
|
846
|
+
background: linear-gradient(90deg, var(--v2-background-bg-base), transparent);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
[data-component="icon-button-v2"]::after {
|
|
850
|
+
display: none;
|
|
851
|
+
}
|
|
792
852
|
}
|
|
793
853
|
|
|
794
854
|
body[data-new-layout] #review-panel [data-component="tabs"] .session-review-v2-open-in-app-slot {
|
|
@@ -113,6 +113,29 @@
|
|
|
113
113
|
cursor: not-allowed;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
[data-component="button-v2"][data-variant="warning"] {
|
|
117
|
+
background-color: var(--v2-background-bg-button-neutral);
|
|
118
|
+
color: var(--v2-state-fg-warning);
|
|
119
|
+
box-shadow: var(--v2-elevation-button-neutral);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
[data-component="button-v2"][data-variant="warning"]:is(:hover, [data-state="hover"]):not(:disabled) {
|
|
123
|
+
background-image:
|
|
124
|
+
linear-gradient(90deg, var(--v2-overlay-simple-overlay-hover) 0%, var(--v2-overlay-simple-overlay-hover) 100%),
|
|
125
|
+
linear-gradient(90deg, var(--v2-background-bg-button-neutral) 0%, var(--v2-background-bg-button-neutral) 100%);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
[data-component="button-v2"][data-variant="warning"]:is(:active, [data-state="pressed"]):not(:disabled) {
|
|
129
|
+
background-image:
|
|
130
|
+
linear-gradient(90deg, var(--v2-overlay-simple-overlay-pressed) 0%, var(--v2-overlay-simple-overlay-pressed) 100%),
|
|
131
|
+
linear-gradient(90deg, var(--v2-background-bg-button-neutral) 0%, var(--v2-background-bg-button-neutral) 100%);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
[data-component="button-v2"][data-variant="warning"]:is(:disabled, [data-state="disabled"]) {
|
|
135
|
+
opacity: 0.5;
|
|
136
|
+
cursor: not-allowed;
|
|
137
|
+
}
|
|
138
|
+
|
|
116
139
|
/* Outline */
|
|
117
140
|
[data-component="button-v2"][data-variant="outline"] {
|
|
118
141
|
background-color: transparent;
|
|
@@ -7,7 +7,7 @@ export interface ButtonV2Props
|
|
|
7
7
|
extends ComponentProps<typeof Kobalte>,
|
|
8
8
|
Pick<ComponentProps<"button">, "class" | "classList" | "children"> {
|
|
9
9
|
size?: "small" | "normal" | "large"
|
|
10
|
-
variant?: "neutral" | "danger" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading"
|
|
10
|
+
variant?: "neutral" | "danger" | "warning" | "outline" | "contrast" | "ghost" | "ghost-muted" | "loading"
|
|
11
11
|
icon?: IconProps["name"]
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -101,7 +101,7 @@ export function Dialog(props: DialogProps) {
|
|
|
101
101
|
const autofocusEl = target?.querySelector("[autofocus]") as HTMLElement | null
|
|
102
102
|
if (autofocusEl) {
|
|
103
103
|
e.preventDefault()
|
|
104
|
-
autofocusEl.focus()
|
|
104
|
+
autofocusEl.focus({ preventScroll: true })
|
|
105
105
|
}
|
|
106
106
|
}}
|
|
107
107
|
>
|
|
@@ -67,9 +67,14 @@
|
|
|
67
67
|
gap: 4px;
|
|
68
68
|
background: var(--v2-background-bg-layer-01);
|
|
69
69
|
border-radius: 4px 0 0 4px;
|
|
70
|
+
cursor: default;
|
|
70
71
|
transition: background 85ms ease-out;
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
[data-component="inline-input-v2"]:where([data-disabled]) [data-slot="inline-input-v2-prefix"] {
|
|
75
|
+
cursor: not-allowed;
|
|
76
|
+
}
|
|
77
|
+
|
|
73
78
|
[data-component="inline-input-v2"][data-label-width] [data-slot="inline-input-v2-prefix"] {
|
|
74
79
|
width: var(--inline-input-v2-label-width);
|
|
75
80
|
min-width: var(--inline-input-v2-label-width);
|
|
@@ -89,6 +94,7 @@
|
|
|
89
94
|
letter-spacing: -0.04px;
|
|
90
95
|
color: var(--v2-text-text-muted);
|
|
91
96
|
font-variation-settings: "slnt" 0;
|
|
97
|
+
user-select: none;
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
[data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-prefix-text"] {
|
|
@@ -149,6 +155,7 @@
|
|
|
149
155
|
|
|
150
156
|
[data-component="inline-input-v2"] [data-slot="inline-input-v2-input"]::placeholder {
|
|
151
157
|
color: var(--v2-text-text-faint);
|
|
158
|
+
user-select: none;
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
[data-component="inline-input-v2"][data-numeric] [data-slot="inline-input-v2-input"] {
|
|
@@ -37,6 +37,8 @@ export function InlineInputV2(props: InlineInputV2Props) {
|
|
|
37
37
|
"style",
|
|
38
38
|
])
|
|
39
39
|
|
|
40
|
+
let input: HTMLInputElement | undefined
|
|
41
|
+
|
|
40
42
|
return (
|
|
41
43
|
<div
|
|
42
44
|
data-component="inline-input-v2"
|
|
@@ -59,7 +61,15 @@ export function InlineInputV2(props: InlineInputV2Props) {
|
|
|
59
61
|
: {}),
|
|
60
62
|
}}
|
|
61
63
|
>
|
|
62
|
-
<div
|
|
64
|
+
<div
|
|
65
|
+
data-slot="inline-input-v2-prefix"
|
|
66
|
+
onMouseDown={(event) => {
|
|
67
|
+
if (local.disabled || event.button !== 0) return
|
|
68
|
+
// Keep focus on the input without using a native <label>, so external labels still work.
|
|
69
|
+
event.preventDefault()
|
|
70
|
+
input?.focus()
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
63
73
|
<span data-slot="inline-input-v2-prefix-text">{local.prefix}</span>
|
|
64
74
|
</div>
|
|
65
75
|
<div data-slot="inline-input-v2-divider" aria-hidden="true" />
|
|
@@ -67,6 +77,11 @@ export function InlineInputV2(props: InlineInputV2Props) {
|
|
|
67
77
|
<div data-slot="inline-input-v2-value">
|
|
68
78
|
<input
|
|
69
79
|
{...inputProps}
|
|
80
|
+
ref={(el) => {
|
|
81
|
+
input = el
|
|
82
|
+
const ref = inputProps.ref
|
|
83
|
+
if (typeof ref === "function") ref(el)
|
|
84
|
+
}}
|
|
70
85
|
type={inputProps.type ?? "text"}
|
|
71
86
|
disabled={local.disabled}
|
|
72
87
|
aria-invalid={local.invalid ? true : undefined}
|
|
@@ -98,6 +98,7 @@
|
|
|
98
98
|
|
|
99
99
|
[data-component="text-input-v2"] [data-slot="text-input-v2-input"]::placeholder {
|
|
100
100
|
color: var(--v2-text-text-faint);
|
|
101
|
+
user-select: none;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
[data-component="text-input-v2"] [data-slot="text-input-v2-input"][type="search"]::-webkit-search-cancel-button {
|