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:
7
.changeset/fn-7880-reset-mobile-label.md
Normal file
7
.changeset/fn-7880-reset-mobile-label.md
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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()} />);
|
||||
|
||||
@@ -6710,6 +6710,7 @@
|
||||
},
|
||||
"reset": {
|
||||
"button": "Reset Settings",
|
||||
"buttonShort": "Reset",
|
||||
"buttonTitle": "Reset settings to their defaults",
|
||||
"dialogAriaLabel": "Reset settings",
|
||||
"dialogTitle": "Reset Settings",
|
||||
|
||||
@@ -6684,6 +6684,7 @@
|
||||
},
|
||||
"reset": {
|
||||
"button": "Reset Settings",
|
||||
"buttonShort": "Reset",
|
||||
"buttonTitle": "Reset settings to their defaults",
|
||||
"dialogAriaLabel": "Reset settings",
|
||||
"dialogTitle": "Reset Settings",
|
||||
|
||||
1
packages/i18n/src/resources.d.ts
vendored
1
packages/i18n/src/resources.d.ts
vendored
@@ -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.",
|
||||
|
||||
Reference in New Issue
Block a user