chore: merge dev into v2 (#35591)

Co-authored-by: Frank <frank@anoma.ly>
Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com>
Co-authored-by: Brendan Allan <git@brendonovich.dev>
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: Jack <jack@anoma.ly>
Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
Co-authored-by: James Long <longster@gmail.com>
Co-authored-by: Dustin Deus <deusdustin@gmail.com>
Co-authored-by: starptech <starptech@starptechs-MBP.fritz.box>
Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 <little-frank@opencord.local>
Co-authored-by: Dax <mail@thdxr.com>
Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com>
Co-authored-by: Jay <53023+jayair@users.noreply.github.com>
Co-authored-by: runvip <164729189+runvip@users.noreply.github.com>
Co-authored-by: opencode <opencode@sst.dev>
Co-authored-by: Julian Coy <julian@ex-machina.co>
Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
Co-authored-by: Kit Langton <kit.langton@gmail.com>
Co-authored-by: Simon Klee <hello@simonklee.dk>
Co-authored-by: Jay <air@live.ca>
Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com>
This commit is contained in:
Aiden Cline 2026-07-06 16:05:29 -05:00 committed by GitHub
commit 9e0d3976e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
332 changed files with 24739 additions and 4586 deletions

View file

@ -0,0 +1,120 @@
[data-component="file-tree-v2"] {
display: flex;
flex-direction: column;
gap: 2px;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"] {
box-sizing: border-box;
width: 100%;
min-width: 0;
height: 28px;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 6px;
padding-right: 8px;
border: none;
border-radius: 6px;
background-color: transparent;
color: var(--v2-text-text-muted);
text-align: left;
cursor: pointer;
transition:
background-color 120ms ease,
color 120ms ease;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-ignored] {
color: var(--v2-text-text-faint);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"]:hover {
background-color: var(--v2-overlay-simple-overlay-hover);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] {
color: var(--v2-text-text-base);
background-color: var(--v2-overlay-simple-overlay-pressed);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected]:hover {
background-color: var(--v2-overlay-simple-overlay-pressed);
}
[data-component="file-tree-v2"] .filetree-icon--mono {
color: var(--v2-icon-icon-muted);
}
[data-component="file-tree-v2"] .filetree-iconpair .filetree-icon--color {
opacity: 0;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] .filetree-iconpair .filetree-icon--color {
opacity: 1;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] .filetree-iconpair .filetree-icon--mono {
opacity: 0;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"] {
color: var(--v2-text-text-muted);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"] svg {
transition: transform 120ms ease;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"]:not([data-expanded]) svg {
transform: rotate(-90deg);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] [data-slot="file-tree-v2-chevron"] {
color: var(--v2-text-text-base);
}
[data-component="file-tree-v2"] .filetree-iconpair {
position: relative;
display: inline-flex;
width: 16px;
height: 16px;
}
[data-component="file-tree-v2"] .filetree-iconpair [data-component="file-icon"] {
position: absolute;
inset: 0;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"] {
box-sizing: border-box;
flex: none;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
font-size: 11px;
font-weight: 530;
line-height: 1;
letter-spacing: -0.04px;
text-align: center;
text-transform: uppercase;
font-variant-numeric: tabular-nums lining-nums;
font-feature-settings:
"tnum" on,
"lnum" on;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="modified"] {
opacity: 0;
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="added"] {
color: var(--v2-state-fg-success);
}
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="deleted"] {
color: var(--v2-state-fg-danger);
}

View file

@ -57,6 +57,10 @@ const icons = {
viewBox: "0 0 16 16",
body: `<path d="M5 6.5L8 9.5L11 6.5" stroke="currentColor"/>`,
},
collapse: {
viewBox: "0 0 16 16",
body: `<path d="M8 1V6M11 3L8 6L5 3" stroke="currentColor"/><path d="M8 15V10M11 13L8 10L5 13" stroke="currentColor"/><path d="M4 8H6" stroke="currentColor"/><path d="M7 8H9" stroke="currentColor"/><path d="M10 8H12" stroke="currentColor"/>`,
},
check: {
viewBox: "0 0 16 16",
body: `<path d="M3.53613 8.17857L6.39328 11.75L12.4647 4.25" stroke="currentColor"/>`,
@ -93,6 +97,26 @@ const icons = {
viewBox: "0 0 16 16",
body: `<path d="M2.5 7.5H3.5V8.5H2.5V7.5Z" stroke="currentColor"/><path d="M7.5 7.5H8.5V8.5H7.5V7.5Z" stroke="currentColor"/><path d="M12.5 7.5H13.5V8.5H12.5V7.5Z" stroke="currentColor"/>`,
},
expand: {
viewBox: "0 0 16 16",
body: `<path d="M8.25 6.17773V1.17773M11.25 4.17773L8.25 1.17773L5.25 4.17773" stroke="currentColor"/><path d="M8.25 9.17773V14.1777M11.25 11.1777L8.25 14.1777L5.25 11.1777" stroke="currentColor"/><path d="M4.25 7.67773H12.25" stroke="currentColor"/>`,
},
filetree: {
viewBox: "0 0 16 16",
body: `<path d="M2.5 1.5V12.2484H6.75M2.5 4.74838H6.75" stroke="currentColor"/><rect x="8.5" y="3.2168" width="6" height="3" fill="none" stroke="currentColor"/><rect x="8.5" y="10.75" width="6" height="3" fill="none" stroke="currentColor"/>`,
},
split: {
viewBox: "0 0 16 16",
body: `<path d="M1 14H15L15 2H1V14Z" stroke="currentColor"/><rect x="3" y="4" width="4" height="8" fill="currentColor" fill-opacity="0.5"/><rect x="9" y="4" width="4" height="8" fill="currentColor" fill-opacity="0.5"/>`,
},
unified: {
viewBox: "0 0 16 16",
body: `<path d="M3.00001 4.00045L12.9998 4L13 6.99955L3 7L3.00001 4.00045Z" fill="currentColor" fill-opacity="0.5"/><path d="M3.0001 9H13L12.9999 12H3L3.0001 9Z" fill="currentColor" fill-opacity="0.5"/><path d="M1 14H15L15 2H1V14Z" stroke="currentColor"/>`,
},
review: {
viewBox: "0 0 20 20",
body: `<path d="M7 14.5H13M7 7.99512H10.0049M10.0049 7.99512H13M10.0049 7.99512V5M10.0049 7.99512V11M18 18V2L2 2L2 18H18Z" stroke="currentColor"/>`,
},
"outline-sliders": {
viewBox: "0 0 16 16",
body: `<path d="M11.7779 4.66675H14.4446M11.7779 4.66675C11.7779 5.77132 10.8825 6.66675 9.77789 6.66675C8.67332 6.66675 7.77789 5.77132 7.77789 4.66675M11.7779 4.66675C11.7779 3.56218 10.8825 2.66675 9.77789 2.66675C8.67332 2.66675 7.77789 3.56218 7.77789 4.66675M1.55566 4.66675H7.77789M4.22233 11.3334H1.55566M4.22233 11.3334C4.22233 12.438 5.11776 13.3334 6.22233 13.3334C7.3269 13.3334 8.22233 12.438 8.22233 11.3334M4.22233 11.3334C4.22233 10.2288 5.11776 9.33341 6.22233 9.33341C7.3269 9.33341 8.22233 10.2288 8.22233 11.3334M14.4446 11.3334H8.22233" stroke="currentColor"/>`,

View file

@ -81,6 +81,13 @@
--project-avatar-border: var(--v2-avatar-border-gray);
}
[data-slot="project-avatar-surface"][data-variant="outline"] {
--project-avatar-bg: var(--v2-background-bg-base);
--project-avatar-border: var(--v2-border-border-strong);
color: var(--v2-text-text-muted);
text-shadow: none;
}
[data-slot="project-avatar-surface"][data-has-image] {
background: var(--project-avatar-bg);
}

View file

@ -11,6 +11,7 @@ Saturated 16px project avatar with color variants and optional unread dot.
### Variants
- Color: orange, yellow, cyan, green, red, pink, blue, purple, gray.
- Outline: neutral, muted style for de-emphasized projects (e.g. recently closed).
- Image vs initial content state.
- Unread dot with corner mask when \`unread\` is set.
@ -33,7 +34,7 @@ export default {
argTypes: {
variant: {
control: "select",
options: [...PROJECT_AVATAR_VARIANTS],
options: [...PROJECT_AVATAR_VARIANTS, "outline"],
},
},
args: {
@ -62,6 +63,13 @@ export const AllVariants = {
),
}
export const Outline = {
args: {
fallback: "O",
variant: "outline",
},
}
export const Unread = {
args: {
fallback: "O",

View file

@ -26,10 +26,13 @@ export const PROJECT_AVATAR_VARIANTS = [
export type ProjectAvatarVariant = (typeof PROJECT_AVATAR_VARIANTS)[number]
// "outline" is a neutral, muted style (e.g. recently closed projects) and is not part of the color rotation.
export type ProjectAvatarStyle = ProjectAvatarVariant | "outline"
export interface ProjectAvatarProps extends ComponentProps<"div"> {
fallback: string
src?: string
variant?: ProjectAvatarVariant
variant?: ProjectAvatarStyle
unread?: boolean
}

View file

@ -53,11 +53,30 @@
align-items: center;
align-self: stretch;
padding: 0;
gap: 6px;
min-width: 0;
flex: 1 1 auto;
min-height: 0;
}
[data-component="text-input-v2"] [data-slot="text-input-v2-leading-icon"] {
display: flex;
flex: none;
align-items: center;
justify-content: center;
padding-left: 8px;
color: var(--v2-icon-icon-muted);
}
[data-component="text-input-v2"] [data-slot="text-input-v2-leading-icon"] :is(svg, [data-slot="icon-svg"]) {
display: block;
flex: none;
}
[data-component="text-input-v2"][data-leading-icon] [data-slot="text-input-v2-input"] {
padding-left: 0;
}
[data-component="text-input-v2"] [data-slot="text-input-v2-input"] {
display: block;
width: 100%;
@ -81,6 +100,12 @@
color: var(--v2-text-text-faint);
}
[data-component="text-input-v2"] [data-slot="text-input-v2-input"][type="search"]::-webkit-search-cancel-button {
-webkit-appearance: none;
appearance: none;
display: none;
}
[data-component="text-input-v2"][data-numeric] [data-slot="text-input-v2-input"] {
font-variant-numeric: tabular-nums;
}
@ -134,6 +159,14 @@
color: currentColor;
}
[data-component="text-input-v2"] [data-slot="text-input-v2-icon-button"][data-variant="clear"] {
width: 28px;
height: 28px;
padding: 0;
border-radius: 6px;
margin-right: -8px;
}
[data-component="text-input-v2"][data-invalid]:not([data-disabled]) [data-slot="text-input-v2-input"] {
color: var(--v2-state-fg-danger);
caret-color: var(--v2-state-fg-danger);

View file

@ -1,13 +1,20 @@
import { type ComponentProps, Show, splitProps } from "solid-js"
import { type ComponentProps, type JSX, Show, splitProps } from "solid-js"
import { Icon } from "./icon"
import "./text-input-v2.css"
export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type"> {
/** Icon or adornment shown before the field value. */
leadingIcon?: JSX.Element
/** Show the trailing copy action. */
showCopyButton?: boolean
/** Show the trailing clear action. */
showClearButton?: boolean
/** Accessible label for the copy button. */
copyLabel?: string
/** Accessible label for the clear button. */
clearLabel?: string
onCopyClick?: (event: MouseEvent) => void
onClearClick?: (event: MouseEvent) => void
/** Apply tabular numerals to the field value. */
numeric?: boolean
/** Error styling for the field and value text. */
@ -21,9 +28,13 @@ export function TextInputV2(props: TextInputV2Props) {
const [local, inputProps] = splitProps(props, [
"class",
"classList",
"leadingIcon",
"showCopyButton",
"showClearButton",
"copyLabel",
"clearLabel",
"onCopyClick",
"onClearClick",
"numeric",
"invalid",
"appearance",
@ -37,12 +48,16 @@ export function TextInputV2(props: TextInputV2Props) {
data-invalid={local.invalid ? "" : undefined}
data-numeric={local.numeric ? "" : undefined}
data-appearance={local.appearance ?? "base"}
data-leading-icon={local.leadingIcon ? "" : undefined}
classList={{
...local.classList,
[local.class ?? ""]: !!local.class,
}}
>
<div data-slot="text-input-v2-value">
<Show when={local.leadingIcon}>
<span data-slot="text-input-v2-leading-icon">{local.leadingIcon}</span>
</Show>
<input
{...inputProps}
type={inputProps.type ?? "text"}
@ -51,15 +66,26 @@ export function TextInputV2(props: TextInputV2Props) {
data-slot="text-input-v2-input"
/>
</div>
<Show when={local.showCopyButton}>
<Show when={local.showClearButton || local.showCopyButton}>
<button
type="button"
data-slot="text-input-v2-icon-button"
aria-label={local.copyLabel ?? "Copy"}
data-variant={local.showClearButton ? "clear" : "copy"}
aria-label={local.showClearButton ? (local.clearLabel ?? "Clear") : (local.copyLabel ?? "Copy")}
disabled={local.disabled}
onClick={local.onCopyClick}
onMouseDown={(event) => {
if (!local.showClearButton) return
event.preventDefault()
}}
onClick={(event) => {
if (local.showClearButton) {
local.onClearClick?.(event)
return
}
local.onCopyClick?.(event)
}}
>
<Icon name="copy" />
<Icon name={local.showClearButton ? "xmark-small" : "copy"} />
</button>
</Show>
</div>

View file

@ -97,44 +97,46 @@ export interface ToastV2Options {
export function showToastV2(options: ToastV2Options | string) {
const opts = typeof options === "string" ? { description: options } : options
const resolvedIcon = children(() => opts.icon)
return toaster.show((props) => (
<ToastV2 toastId={props.toastId} duration={opts.duration} persistent={opts.persistent}>
<div data-slot="toast-v2-header">
<Show when={resolvedIcon()}>
<ToastV2.Icon>{resolvedIcon()}</ToastV2.Icon>
return toaster.show((props) => {
const resolvedIcon = children(() => opts.icon)
return (
<ToastV2 toastId={props.toastId} duration={opts.duration} persistent={opts.persistent}>
<div data-slot="toast-v2-header">
<Show when={resolvedIcon()}>
<ToastV2.Icon>{resolvedIcon()}</ToastV2.Icon>
</Show>
<ToastV2.Content>
<Show when={opts.title}>
<ToastV2.Title>{opts.title}</ToastV2.Title>
</Show>
<Show when={opts.description}>
<ToastV2.Description>{opts.description}</ToastV2.Description>
</Show>
</ToastV2.Content>
<ToastV2.CloseButton />
</div>
<Show when={opts.actions?.length}>
<ToastV2.Actions>
{opts.actions!.map((action) => (
<ButtonV2
variant={action.variant === "secondary" ? "ghost" : "neutral"}
size="small"
data-action-variant={action.variant ?? "primary"}
onClick={() => {
if (typeof action.onClick === "function") {
action.onClick()
}
toaster.dismiss(props.toastId)
}}
>
{action.label}
</ButtonV2>
))}
</ToastV2.Actions>
</Show>
<ToastV2.Content>
<Show when={opts.title}>
<ToastV2.Title>{opts.title}</ToastV2.Title>
</Show>
<Show when={opts.description}>
<ToastV2.Description>{opts.description}</ToastV2.Description>
</Show>
</ToastV2.Content>
<ToastV2.CloseButton />
</div>
<Show when={opts.actions?.length}>
<ToastV2.Actions>
{opts.actions!.map((action) => (
<ButtonV2
variant={action.variant === "secondary" ? "ghost" : "neutral"}
size="small"
data-action-variant={action.variant ?? "primary"}
onClick={() => {
if (typeof action.onClick === "function") {
action.onClick()
}
toaster.dismiss(props.toastId)
}}
>
{action.label}
</ButtonV2>
))}
</ToastV2.Actions>
</Show>
</ToastV2>
))
</ToastV2>
)
})
}
export interface ToastV2PromiseOptions<T, U = unknown> {

View file

@ -2,7 +2,12 @@
display: flex;
}
[data-popper-positioner]:has([data-component="tooltip-v2"]) {
z-index: 1000;
}
[data-component="tooltip-v2"] {
z-index: 1000;
box-sizing: border-box;
display: inline-flex;
flex-direction: row;

View file

@ -77,6 +77,16 @@
--v2-state-fg-info: var(--v2-blue-800);
--v2-state-border-info: var(--v2-blue-300);
--v2-agent-plan-solid: var(--v2-pink-900);
--v2-agent-plan-border: rgba(200, 61, 139, 0.5);
--v2-agent-plan-background: rgba(253, 236, 243, 0.33);
--v2-agent-build-solid: var(--v2-blue-900);
--v2-agent-build-border: rgba(59, 92, 246, 0.5);
--v2-agent-build-background: rgba(236, 241, 254, 0.33);
--v2-agent-explore-solid: var(--v2-yellow-900);
--v2-agent-explore-border: rgba(142, 114, 49, 0.5);
--v2-agent-explore-background: rgba(254, 250, 236, 0.33);
/* ── Project avatar (fixed; theme-independent) ── */
--v2-avatar-fg: #ffffffff;
--v2-avatar-bg-orange: #ee7330ff;
@ -193,6 +203,16 @@
--v2-state-fg-info: var(--v2-blue-500);
--v2-state-border-info: var(--v2-blue-900);
--v2-agent-plan-solid: var(--v2-pink-400);
--v2-agent-plan-border: rgba(250, 188, 216, 0.5);
--v2-agent-plan-background: rgba(247, 213, 228, 0.1);
--v2-agent-build-solid: var(--v2-blue-400);
--v2-agent-build-border: rgba(215, 226, 252, 0.5);
--v2-agent-build-background: rgba(215, 226, 252, 0.1);
--v2-agent-explore-solid: var(--v2-yellow-400);
--v2-agent-explore-border: rgba(247, 229, 181, 0.5);
--v2-agent-explore-background: rgba(252, 239, 208, 0.1);
--v2-elevation-raised:
0px 2px 4px 0px var(--v2-alpha-dark-30),
0px 1px 2px 0px var(--v2-alpha-dark-30),
@ -296,6 +316,16 @@
--v2-state-fg-info: var(--v2-blue-800);
--v2-state-border-info: var(--v2-blue-300);
--v2-agent-plan-solid: var(--v2-pink-900);
--v2-agent-plan-border: rgba(200, 61, 139, 0.5);
--v2-agent-plan-background: rgba(253, 236, 243, 0.33);
--v2-agent-build-solid: var(--v2-blue-900);
--v2-agent-build-border: rgba(59, 92, 246, 0.5);
--v2-agent-build-background: rgba(236, 241, 254, 0.33);
--v2-agent-explore-solid: var(--v2-yellow-900);
--v2-agent-explore-border: rgba(142, 114, 49, 0.5);
--v2-agent-explore-background: rgba(254, 250, 236, 0.33);
--v2-elevation-raised:
0px 2px 4px 0px var(--v2-alpha-dark-4), 0px 1px 2px -1px var(--v2-alpha-dark-8),
0px 0px 0px 0.5px var(--v2-alpha-dark-12), 0px 0px 0px 0px var(--v2-alpha-dark-0);
@ -406,6 +436,16 @@
--v2-state-fg-info: var(--v2-blue-500);
--v2-state-border-info: var(--v2-blue-900);
--v2-agent-plan-solid: var(--v2-pink-400);
--v2-agent-plan-border: rgba(250, 188, 216, 0.5);
--v2-agent-plan-background: rgba(247, 213, 228, 0.1);
--v2-agent-build-solid: var(--v2-blue-400);
--v2-agent-build-border: rgba(215, 226, 252, 0.5);
--v2-agent-build-background: rgba(215, 226, 252, 0.1);
--v2-agent-explore-solid: var(--v2-yellow-400);
--v2-agent-explore-border: rgba(247, 229, 181, 0.5);
--v2-agent-explore-background: rgba(252, 239, 208, 0.1);
--v2-avatar-fg: #ffffffff;
--v2-avatar-bg-orange: #723d22ff;
--v2-avatar-border-orange: #ff8648ff;