FN-7880: shorten Reset Settings button to "Reset" on mobile

Shortens the Settings footer's Reset Settings button label to Reset at the mobile breakpoint to preserve footer space, while desktop/tablet keep the full label; confirmation dialog and reset behavior are unchanged.

- Add settings.reset.buttonShort i18n key (en, zh-CN) and typed resources.d.ts entry
- SettingsModal reset button now renders buttonShort ("Reset") when viewportMode === "mobile", otherwise the existing "Reset Settings" label
- Update settings-mobile.test.tsx to assert the compact mobile label and add coverage across modal/embedded x mobile/desktop viewport combinations
- Update docs/dashboard-guide.md to document the mobile-only compact label
- Add changeset (patch) for @runfusion/fusion

Files changed:
 .changeset/fn-7880-reset-mobile-label.md           |  7 ++++
 docs/dashboard-guide.md                            |  6 ++--
 packages/dashboard/app/components/SettingsModal.tsx |  7 +++-
 packages/dashboard/app/components/__tests__/settings-mobile.test.tsx | 37 +++++++++++++++++++++-
 packages/i18n/locales/en/app.json                  |  1 +
 packages/i18n/locales/zh-CN/app.json               |  1 +
 packages/i18n/src/resources.d.ts                   |  1 +
 7 files changed, 56 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-7880

Fusion-Task-Lineage: e636e73d-172e-4a6e-bb51-078520fd05ab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-12 16:48:04 -07:00
parent 504dc69f02
commit 56c745240a
7 changed files with 56 additions and 4 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Shorten the Settings "Reset Settings" button to "Reset" on mobile.
category: fix
dev: SettingsModal reset button now uses settings.reset.buttonShort at viewportMode==="mobile"; confirmation dialog unchanged.

View File

@@ -24,8 +24,10 @@ Every user-editable setting's help text (the `.settings-description`/`<small>` h
## Reset Settings
<!-- FNXC:SettingsResetDocs 2026-07-04-00:00: Reset Settings is a DESTRUCTIVE action. Document both choices, the scope-precision guarantee, and which sections are excluded so operators understand exactly what a reset does and does not touch before they click it. -->
The Settings footer includes a **Reset Settings** button, next to Import/Export, in both the Settings modal and the embedded Settings page (desktop and mobile). Selecting it opens a confirmation dialog with two destructive choices, plus Cancel:
<!-- FNXC:SettingsResetDocs 2026-07-04-00:00: Reset Settings is a DESTRUCTIVE action. Document both choices, the scope-precision guarantee, and which sections are excluded so operators understand exactly what a reset does and does not touch before they click it.
FNXC:SettingsResetDocs 2026-07-12-00:00: FN-7880 shortens the mobile footer affordance to Reset to keep the Settings action row usable on small screens; desktop and tablet keep the full Reset Settings label while the confirmation choices remain identical. -->
The Settings footer includes a **Reset Settings** button, next to Import/Export, in both the Settings modal and the embedded Settings page. On mobile the same button is labeled **Reset** to preserve footer space; desktop and tablet keep **Reset Settings**. Selecting it opens a confirmation dialog with two destructive choices, plus Cancel:
- **Reset this menu ({{section}})** — resets only the settings owned by the currently active section, at that section's own scope (global or project). A global section (for example Appearance) writes the section's keys back to their canonical defaults. A project section (for example Merge) clears the section's keys back to their inherited/default value. No other section's settings are touched.
- **Reset all project settings** — resets every project-scoped setting for the current project back to its default/inherited value. This never touches global (cross-project) settings.

View File

@@ -4130,6 +4130,9 @@ export function SettingsModal({
embedded (SettingsView) presentations — the footer is not gated by isEmbedded
(only Cancel is), so this button renders in both automatically (FN-7506
Surface Enumeration: modal + embedded).
FNXC:SettingsReset 2026-07-12-00:00:
The mobile Settings footer needs the compact Reset label to preserve horizontal space alongside Help, version, Import, Export, Cancel, and Save. Desktop and tablet keep the full Reset Settings wording while the existing destructive confirmation dialog remains unchanged.
*/}
<button
type="button"
@@ -4139,7 +4142,9 @@ export function SettingsModal({
disabled={loading}
title={t("settings.reset.buttonTitle", "Reset settings to their defaults")}
>
{t("settings.reset.button", "Reset Settings")}
{viewportMode === "mobile"
? t("settings.reset.buttonShort", "Reset")
: t("settings.reset.button", "Reset Settings")}
</button>
</div>
<div className="modal-actions-right">

View File

@@ -241,14 +241,21 @@ describe("SettingsModal mobile adaptations", () => {
FN-7506 mobile surface coverage: the Reset Settings button and its confirmation
dialog must be reachable and usable at the mobile breakpoint, with no horizontal
overflow, mirroring the desktop assertions in SettingsModal.general.test.tsx.
FNXC:SettingsReset 2026-07-12-00:00:
FN-7880 mobile label coverage: the same footer affordance renders in modal and
embedded SettingsView presentations, but only the mobile viewport shortens the
visible label to Reset. Desktop and tablet keep Reset Settings.
*/
it("renders and operates the Reset Settings button/dialog at the mobile breakpoint", async () => {
it("renders and operates the compact Reset button/dialog at the mobile breakpoint", async () => {
mockSettingsViewport(true);
const { findByTestId, container } = render(<SettingsModal onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
const resetBtn = await findByTestId("settings-reset");
expect(container.querySelector(".modal-actions")?.contains(resetBtn)).toBe(true);
expect(resetBtn).toHaveTextContent(/^Reset$/);
expect(resetBtn).not.toHaveTextContent("Reset Settings");
const user = userEvent.setup({ delay: null, pointerEventsCheck: 0 });
await user.click(resetBtn);
@@ -261,6 +268,34 @@ describe("SettingsModal mobile adaptations", () => {
expect(updateSettings).not.toHaveBeenCalled();
});
it("uses viewport-specific reset labels in modal and embedded footers", async () => {
mockSettingsViewport(true);
const mobileModal = render(<SettingsModal onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
expect(await mobileModal.findByTestId("settings-reset")).toHaveTextContent(/^Reset$/);
mobileModal.unmount();
vi.clearAllMocks();
mockSettingsViewport(true);
const mobileEmbedded = render(<SettingsView onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
expect(await mobileEmbedded.findByTestId("settings-reset")).toHaveTextContent(/^Reset$/);
mobileEmbedded.unmount();
vi.clearAllMocks();
mockSettingsViewport(false);
const desktopModal = render(<SettingsModal onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
expect(await desktopModal.findByTestId("settings-reset")).toHaveTextContent(/^Reset Settings$/);
desktopModal.unmount();
vi.clearAllMocks();
mockSettingsViewport(false);
const desktopEmbedded = render(<SettingsView onClose={vi.fn()} addToast={vi.fn()} />);
await waitFor(() => expect(fetchSettings).toHaveBeenCalled());
expect(await desktopEmbedded.findByTestId("settings-reset")).toHaveTextContent(/^Reset Settings$/);
});
it("renders the compact app version label in mobile layout", async () => {
mockSettingsViewport(true);
const { findByText, queryByText, container } = render(<SettingsModal onClose={vi.fn()} addToast={vi.fn()} />);

View File

@@ -6710,6 +6710,7 @@
},
"reset": {
"button": "Reset Settings",
"buttonShort": "Reset",
"buttonTitle": "Reset settings to their defaults",
"dialogAriaLabel": "Reset settings",
"dialogTitle": "Reset Settings",

View File

@@ -6684,6 +6684,7 @@
},
"reset": {
"button": "Reset Settings",
"buttonShort": "Reset",
"buttonTitle": "Reset settings to their defaults",
"dialogAriaLabel": "Reset settings",
"dialogTitle": "Reset Settings",

View File

@@ -6538,6 +6538,7 @@ export default interface Resources {
"reset": {
"allProjectResetSuccess": "All project settings reset to defaults",
"button": "Reset Settings",
"buttonShort": "Reset",
"buttonTitle": "Reset settings to their defaults",
"dialogAriaLabel": "Reset settings",
"dialogBody": "Choose what to reset to its defaults. This cannot be undone.",