Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4585820
UI polish batch: cloud sign-in, onboarding, composer menu
wangchenglong0001 Jul 30, 2026
8a376a1
perf(web): optimize onboarding cloud artwork
lefarcen Jul 30, 2026
f7916a6
fix(web): invalidate project file reads after mutations
lefarcen Jul 30, 2026
f1fc2c6
fix(web): disable readonly project starter mutations
lefarcen Jul 30, 2026
049422f
fix(web): preserve focus for standalone composer panels
lefarcen Jul 30, 2026
1fdc7d7
Merge remote-tracking branch 'origin/feat/workspace-team' into pr/clo…
lefarcen Aug 1, 2026
9bd0e7e
test(e2e): require explicit workspace scope
lefarcen Aug 1, 2026
3842401
fix(web): invalidate file reads on project events
lefarcen Aug 1, 2026
1b4f1b3
test(e2e): seed explicit settings workspace
lefarcen Aug 1, 2026
44079f9
test(e2e): align manual edit with current inspector
lefarcen Aug 1, 2026
3e3b84a
fix(web): refresh deployments when share opens
lefarcen Aug 1, 2026
715083d
test(e2e): follow composer design system entry
lefarcen Aug 1, 2026
e87750d
fix(web): keep local project creation workspace-independent
lefarcen Aug 1, 2026
fe3345a
fix(web): preserve scoped auth recovery state
lefarcen Aug 1, 2026
db1fdc4
test(e2e): follow current entry settings flows
lefarcen Aug 1, 2026
1199dda
fix(web): preserve AMR retry across settings
lefarcen Aug 1, 2026
2e3ccb5
test(e2e): model explicit personal workspace recovery
lefarcen Aug 1, 2026
6f734f5
test(e2e): stabilize AMR logout settings recovery
lefarcen Aug 1, 2026
0d8b858
fix(projects): return workspace scope on create
lefarcen Aug 1, 2026
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/web/public/upgrade/cloud-signin-aurora.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 66 additions & 38 deletions apps/web/src/components/AmrBalanceDialog.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,27 @@

.panel {
position: relative;
width: 400px;
width: min(400px, calc(100vw - 32px));
align-items: center;
text-align: center;
padding: 32px 28px 20px;
padding: 36px 32px 24px;
gap: 0;
overflow: hidden;
}

/* Bleeds to the panel's edges (negative margin cancels .panel's own padding)
* so the artwork reaches the dialog's rounded corners; .panel's overflow:
* hidden clips it to match instead of duplicating the radius here. */
.banner {
margin: -36px -32px 24px;
}

/* No object-fit crop — width:100% + height:auto keeps the source's native
* aspect ratio intact rather than cropping it to fit a fixed box. */
.bannerImage {
display: block;
width: 100%;
height: auto;
}

.closeButton {
Expand Down Expand Up @@ -39,29 +55,16 @@
outline-offset: 2px;
}

.iconBadge {
display: grid;
place-items: center;
width: 48px;
height: 48px;
border-radius: 50%;
color: var(--accent);
background: var(--accent-tint);
/* Soft halo ring so the badge reads as a glow, not a flat chip. */
box-shadow: 0 0 0 8px color-mix(in srgb, var(--accent-tint) 45%, transparent);
margin-bottom: 18px;
}

.title {
margin: 0 0 8px;
font-size: 17px;
margin: 0 0 10px;
font-size: 18px;
font-weight: 600;
letter-spacing: -0.01em;
color: var(--text-strong);
}

.message {
margin: 0 0 18px;
margin: 0 0 24px;
font-size: 13.5px;
line-height: 1.6;
color: var(--text-muted);
Expand All @@ -71,22 +74,23 @@

.benefitsCard {
width: 100%;
margin: 0 0 20px;
padding: 14px 16px;
margin: 0 0 22px;
padding: 16px 18px;
text-align: start;
border: 1px solid var(--border-soft);
border-radius: var(--radius);
background: var(--bg-subtle);
background: var(--bg-panel);
}

/* Eyebrow label naming whose advantages the list below sells. Accent, not
* gray: the brand attribution is the label's whole job, and it ties the card
* to the check icons and CTA without competing with the main title. */
.benefitsTitle {
display: block;
margin-bottom: 10px;
font-size: 11.5px;
margin-bottom: 12px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.02em;
letter-spacing: 0.04em;
color: var(--accent);
}

Expand All @@ -96,15 +100,18 @@
padding: 0;
display: flex;
flex-direction: column;
gap: 10px;
gap: 12px;
}

.benefit {
display: flex;
/* Top-align so the check hugs the first line when an item wraps. */
align-items: flex-start;
display: grid;
/* Fixed icon column so wrapped labels stay aligned to the text, not the
* icon — matches the row rhythm of the artifact-upgrade gate's benefit list. */
grid-template-columns: 22px minmax(0, 1fr);
align-items: center;
gap: 10px;
font-size: 13px;
font-size: 13.5px;
line-height: 1.45;
color: var(--text);
/* Rare dialog → a light cascade adds delight without slowing anyone down. */
opacity: 0;
Expand All @@ -127,26 +134,36 @@
.benefitIcon {
display: grid;
place-items: center;
width: 18px;
height: 18px;
width: 22px;
height: 22px;
flex: none;
border-radius: 50%;
border-radius: var(--radius-sm);
color: var(--accent);
background: var(--accent-tint);
}

.actions {
display: flex;
flex-direction: column;
gap: 6px;
gap: 10px;
width: 100%;
}

.cta {
width: 100%;
height: 38px;
height: 40px;
font-size: 13.5px;
transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
box-shadow:
inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent),
0 8px 20px color-mix(in srgb, var(--accent) 20%, transparent);
transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), box-shadow 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

.cta:hover:not(:disabled) {
transform: translateY(-1px);
box-shadow:
inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent),
0 10px 24px color-mix(in srgb, var(--accent) 26%, transparent);
}

.cta:active {
Expand All @@ -167,29 +184,40 @@

.signInPill :global(.amr-account-control__action) {
width: 100%;
height: 38px;
height: 40px;
font-size: 13.5px;
border-radius: var(--radius-sm);
border: none;
background: var(--accent);
color: #fff;
font-weight: 500;
transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background 120ms ease;
box-shadow:
inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent),
0 8px 20px color-mix(in srgb, var(--accent) 20%, transparent);
transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background 120ms ease, box-shadow 160ms cubic-bezier(0.23, 1, 0.32, 1);
}

.signInPill :global(.amr-account-control__action:hover) {
background: var(--accent-hover);
transform: translateY(-1px);
box-shadow:
inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent),
0 10px 24px color-mix(in srgb, var(--accent) 26%, transparent);
}

.signInPill :global(.amr-account-control__action:active) {
transform: scale(0.98);
}

/* Quiet text button: the bordered ghost chrome would compete with the CTA.
* Scoped under .actions to outrank the shared Button variant class. */
* Scoped under .actions to outrank the shared Button variant class. Sits a
* size step down from the CTA so the pair reads as primary/secondary, not
* two equally-weighted buttons stacked back to back. */
.actions .later {
width: 100%;
padding-top: 2px;
color: var(--text-muted);
font-size: 12.5px;
border-color: transparent;
background: transparent;
box-shadow: none;
Expand Down
12 changes: 10 additions & 2 deletions apps/web/src/components/AmrBalanceDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,16 @@ export function AmrBalanceDialog({
>
<Icon name="close" size={14} />
</button>
<div className={styles.iconBadge} aria-hidden>
<Icon name="sparkles" size={22} />
<div className={styles.banner}>
<img
className={styles.bannerImage}
src="/upgrade/cloud-signin-aurora.jpg"
alt=""
width={1680}
height={720}
decoding="async"
draggable={false}
/>
</div>
<h2 className={styles.title}>
{signedOut ? t('chat.amrBalanceGate.signedOutTitle') : t('chat.amrBalanceGate.title')}
Expand Down
50 changes: 46 additions & 4 deletions apps/web/src/components/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3244,10 +3244,52 @@ export const ChatComposer = forwardRef<ChatComposerHandle, Props>(
trackComposerBar({ element: 'design_system_open' });
openDesignSystemPicker();
} : undefined}
// No toolboxLabel / renderToolbox, and hidePluginsRow: 插件 and
// 设计百宝箱 left this menu — the quick pills above the input
// open their standalone popovers instead.
hidePluginsRow
// 插件 and 设计百宝箱 live inside the "+" menu (right below
// 工作目录) as hover-expand submenus. The toolbox flyout reuses
// the same DesignToolboxPanel the standalone popover renders.
toolboxLabel={t('chat.designToolbox.title')}
renderToolbox={(close) => (
<DesignToolboxPanel
actions={DESIGN_TOOLBOX_ACTIONS}
skills={skills}
plugins={pluginsForComposer}
mcpServers={enabledMcpServers}
mcpTemplates={mcpTemplates}
connectors={connectors}
projectFiles={projectFiles}
activeSkillIds={stagedSkills.map((skill) => skill.id)}
activePluginId={activeAppliedPlugin?.pluginId ?? pinnedPluginId ?? null}
activeMcpServerIds={stagedMcpServers.map((server) => server.id)}
activeConnectorIds={stagedConnectors.map((connector) => connector.id)}
activeFilePaths={staged.map((item) => item.path)}
onOpened={() => trackDesignToolbox({ element: 'design_toolbox_open' })}
onPickAction={(action) => {
trackDesignToolbox({
element: 'design_toolbox_action',
toolbox_action_id: action.id,
});
applyDesignToolboxAction(action);
close();
}}
onPickSkill={(skill) => {
trackDesignToolbox({
element: 'design_toolbox_resource',
resource_kind: 'skill',
resource_id: skill.id,
});
applyDesignToolboxSkill(skill);
close();
}}
onPickResource={(resource) => {
trackDesignToolbox({
element: 'design_toolbox_resource',
...designToolboxResourceTracking(resource),
});
applyDesignToolboxResource(resource);
close();
}}
/>
)}
/>
{/* #5517: the design-system picker sits inline in the composer's
icon row (palette icon) instead of the staged-context bar. */}
Expand Down
Loading
Loading