Skip to content
Merged
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
6 changes: 5 additions & 1 deletion apps/web/src/components/AmrGuidance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ export function AmrGuidance({
tone="brand"
title={t('chat.amrCard.switchTitle')}
detailsLabel={t('brand.viewDetails')}
actions={
// Long localized CTA belongs in the footer row (same shell as run-
// recovery). Head `actions` share a 3-column grid with the title; a
// narrow ChatPane leaves the title a single CJK character wide and
// `overflow-wrap: anywhere` turns "模型调用失败…" into a vertical stack.
footerActions={
<button
type="button"
className="amr-card__cta"
Expand Down
32 changes: 31 additions & 1 deletion apps/web/src/components/UserActionCard.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.card {
/* ChatPane width is independent of the viewport — stack head actions off
the card's own inline size via @container, not @media (max-width). */
container-type: inline-size;
container-name: user-action-card;
display: flex;
flex-direction: column;
gap: 8px;
Expand Down Expand Up @@ -52,7 +56,10 @@
font-weight: 600;
line-height: 1.4;
color: var(--text-strong);
overflow-wrap: anywhere;
/* Prefer soft breaks over `anywhere` so a squeezed title does not stack
every CJK character on its own line (vertical "模型调用失败…" flash). */
overflow-wrap: break-word;
word-break: normal;
}

.actions {
Expand All @@ -62,6 +69,14 @@
justify-content: flex-end;
gap: 7px;
min-width: 0;
/* Cap so a long localized CTA cannot steal the entire title track. */
max-width: min(100%, 16rem);
}

.actions > * {
min-width: 0;
max-width: 100%;
white-space: normal;
}

.footer {
Expand Down Expand Up @@ -158,6 +173,20 @@
}
}

/* Prefer the card's own width: a desktop split with a ~320px ChatPane never
matches viewport max-width:560px, so head CTAs must reflow via @container. */
@container user-action-card (max-width: 420px) {
.head {
grid-template-columns: 24px minmax(0, 1fr);
}

.actions {
grid-column: 2 / -1;
justify-content: flex-start;
max-width: 100%;
}
}

@media (max-width: 560px) {
.head {
grid-template-columns: 24px minmax(0, 1fr);
Expand All @@ -166,6 +195,7 @@
.actions {
grid-column: 2;
justify-content: flex-start;
max-width: 100%;
}

.footerActions {
Expand Down
4 changes: 4 additions & 0 deletions apps/web/src/styles/chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,10 @@
font-size: 13px;
padding: 7px 14px;
border-radius: var(--radius-sm);
max-width: 100%;
white-space: normal;
text-align: left;
line-height: 1.35;
transition:
background 140ms cubic-bezier(0.23, 1, 0.32, 1),
border-color 140ms cubic-bezier(0.23, 1, 0.32, 1);
Expand Down
9 changes: 9 additions & 0 deletions apps/web/tests/components/AmrGuidance.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,13 @@ describe('AmrGuidance', () => {
});
expect(onActivate).toHaveBeenCalledTimes(1);
});

// Long CTA must live in the footer row so a narrow ChatPane does not
// squeeze the Chinese title into a vertical one-character stack.
it('places the switch CTA in the footer rather than the head actions column', () => {
const { container } = renderGuidance();
const cta = screen.getByRole('button', { name: 'Switch to Open Design Cloud & retry' });
const footer = container.querySelector('[data-user-action-footer="true"]');
expect(footer?.contains(cta)).toBe(true);
});
});
Loading