feat: tableur mobile — barres repliées par défaut, bascule unique #189
Sous 768 px, la barre de menus, le ruban et le groupe Recherche sont repliés par défaut : la barre de formule (fx), les onglets et Enregistrer restent visibles et la grille récupère la hauteur d'écran. Un bouton unique (#xlsx-tools-toggle) dans la barre des feuilles déplie/replie l'ensemble (aria-expanded, état actif) ; desktop inchangé. Ergonomie tactile : cibles ≥ 44 px, onglets en défilement horizontal, champs de la barre de formule en 16 px (anti-zoom iOS), barre de formule en 2 lignes quand les outils sont ouverts. Tests : JSDOM xlsx-viewer.test.mjs (+2, 165/165), E2E mobile (repli par défaut, dépliage, no-overflow ruban, cibles 44 px) ; openXlsx() déplie automatiquement ≤ 768 px pour les tests desktop.
This commit is contained in:
@@ -2775,6 +2775,54 @@ await test("a read-only workbook keeps the view menus but drops the editing ones
|
||||
assert.ok(area.querySelector('[data-xlsx-action="toggle-grid"]'), "Gridlines stay");
|
||||
});
|
||||
|
||||
// ── #189 — mise en page mobile : barres repliées derrière un basculeur ──────
|
||||
|
||||
await test("the sheet strip carries the tools toggle that flips the toolbar (#189)", () => {
|
||||
const area = mountGrid();
|
||||
const strip = area.querySelector(".xlsx-sheetbar");
|
||||
const toggle = area.querySelector("#xlsx-tools-toggle");
|
||||
assert.ok(toggle, "toggle rendered");
|
||||
assert.equal(toggle.closest(".xlsx-sheetbar"), strip, "it lives in the sheet strip");
|
||||
assert.equal(toggle.getAttribute("aria-expanded"), "false", "starts collapsed");
|
||||
const toolbar = area.querySelector(".xlsx-toolbar");
|
||||
assert.ok(!toolbar.classList.contains("xlsx-tools-open"), "toolbar starts closed");
|
||||
toggle.click();
|
||||
assert.ok(toolbar.classList.contains("xlsx-tools-open"), "one click opens the tools");
|
||||
assert.equal(toggle.getAttribute("aria-expanded"), "true");
|
||||
assert.ok(toggle.classList.contains("active"), "the toggle shows its own state");
|
||||
toggle.click();
|
||||
assert.ok(!toolbar.classList.contains("xlsx-tools-open"), "a second click closes them");
|
||||
assert.equal(toggle.getAttribute("aria-expanded"), "false");
|
||||
});
|
||||
|
||||
await test("style.css hides menus/ribbon/find by default under 768px and reveals them on .xlsx-tools-open (#189)", () => {
|
||||
const css = readFileSync(path.join(REPO_ROOT, "frontend", "style.css"), "utf8");
|
||||
// The desktop default: the toggle itself is out of the way.
|
||||
assert.match(css, /\.xlsx-tools-toggle\s*\{\s*display:\s*none/, "toggle hidden on desktop");
|
||||
// Mobile block: collapsed by default… (CRLF-safe slice, from the #189
|
||||
// comment up to the next top-level rule).
|
||||
const from = css.indexOf("/* #189");
|
||||
assert.ok(from > 0, "the #189 mobile block exists after the coarse-pointer rules");
|
||||
const to = css.indexOf(".xlsx-context-item", from);
|
||||
assert.ok(to > from, "the #189 block is followed by the next rule");
|
||||
const block = css.slice(from, to);
|
||||
for (const cls of [".xlsx-menubar", ".xlsx-cmdbar", ".xlsx-find-group"]) {
|
||||
const hidden = new RegExp(cls.replace(".", "\\.") + "[^}]*display:\\s*none").test(block)
|
||||
|| new RegExp(cls.replace(".", "\\.") + ",[\\s\\S]{0,120}?display:\\s*none").test(block);
|
||||
assert.ok(hidden, `${cls} hidden by default on mobile`);
|
||||
assert.ok(
|
||||
block.includes(`.xlsx-toolbar.xlsx-tools-open ${cls}`),
|
||||
`${cls} revealed by .xlsx-tools-open`,
|
||||
);
|
||||
}
|
||||
// The formula bar always stays, and the open state can wrap it (find group).
|
||||
assert.ok(block.includes(".xlsx-toolbar.xlsx-tools-open .xlsx-formula-bar"), "formula bar wraps when open");
|
||||
// Touch: 44px targets, tabs on one scrollable row, 16px inputs (no iOS zoom).
|
||||
assert.match(block, /min-width:\s*44px/, "44px touch targets");
|
||||
assert.match(block, /\.xlsx-sheetbar \.xlsx-tabs\s*\{[^}]*overflow-x:\s*auto/, "tabs scroll horizontally");
|
||||
assert.match(block, /font-size:\s*16px/, "inputs at 16px avoid the iOS focus zoom");
|
||||
});
|
||||
|
||||
// ── Report ──────────────────────────────────────────────────────────────────
|
||||
console.log(`\n${passCount}/${testCount} tests passed\n`);
|
||||
process.exit(passCount === testCount ? 0 : 1);
|
||||
|
||||
Reference in New Issue
Block a user