Skip to content

Commit 67e132d

Browse files
committed
feat: resonsive toggle button layout
1 parent 382ef4a commit 67e132d

4 files changed

Lines changed: 79 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
## [Unreleased]
22

3+
### New Features
4+
5+
- **Responsive toggle button layout**: The virtual keyboard toggle and menu
6+
button now automatically switch from horizontal (side-by-side) to vertical
7+
(stacked) layout when the mathfield height is 100px or greater. This happens
8+
dynamically as you add content to the mathfield.
9+
310
### Resolved Issues
411

512
- Fixed virtual keyboard toggle requiring triple-click to activate.

css/mathfield.less

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,19 @@
2626
}
2727
}
2828

29+
:host {
30+
display: block;
31+
}
32+
2933
// The .ML__container includes the visible parts of the math-field:
30-
// the .ML__content and the .ML__virtual-keyboard-toggle.
34+
// the .ML__content and the toggle buttons (wrapped in .ML__toggles).
3135
// .ML__container
3236
// > .ML__content
3337
// > .ML__latex > .ML__base
3438
// > .ML__selection
35-
// > .ML__virtual-keyboard-toggle
36-
// > .ML__menu-toggle
39+
// > .ML__toggles
40+
// > .ML__virtual-keyboard-toggle
41+
// > .ML__menu-toggle
3742
.ML__container {
3843
display: inline-flex;
3944
flex-flow: row;
@@ -44,7 +49,7 @@
4449
padding: 4px;
4550
box-sizing: border-box;
4651

47-
/* This attribute is necessary to work around a Firefox issue where
52+
/* This attribute is necessary to work around a Firefox issue where
4853
where clicking multiple times on the border leads to a focused mathfield that cannot be edited until focus is lost and regained (also fixes the multiple cursor issue on firefox that can occur with the same sequence of events).
4954
*/
5055
pointer-events: auto;
@@ -194,6 +199,27 @@
194199
}
195200
}
196201

202+
/* Container for the virtual keyboard toggle and menu toggle buttons */
203+
.ML__toggles {
204+
display: flex;
205+
flex-direction: row;
206+
align-items: flex-start;
207+
gap: 0;
208+
align-self: flex-start;
209+
}
210+
211+
/* Vertical layout modifier */
212+
.ML__toggles--vertical {
213+
flex-direction: column;
214+
align-items: center;
215+
gap: 4px;
216+
217+
.ML__virtual-keyboard-toggle,
218+
.ML__menu-toggle {
219+
margin-right: 0;
220+
}
221+
}
222+
197223
.ML__virtual-keyboard-toggle,
198224
.ML__menu-toggle {
199225
box-sizing: border-box;

src/editor-mathfield/mathfield-private.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,10 @@ export class _Mathfield implements Mathfield, KeyboardDelegateInterface {
332332
markup.push(contentMarkup(this));
333333
markup.push('</span>');
334334

335-
// 2.1/ The virtual keyboard toggle
335+
// 2.1/ Wrapper for toggle buttons
336+
markup.push('<div class=ML__toggles>');
337+
338+
// 2.1.1/ The virtual keyboard toggle
336339
if (window.mathVirtualKeyboard) {
337340
markup.push(
338341
`<div part=virtual-keyboard-toggle class=ML__virtual-keyboard-toggle role=button ${
@@ -343,13 +346,15 @@ export class _Mathfield implements Mathfield, KeyboardDelegateInterface {
343346
markup.push('</div>');
344347
}
345348

346-
// 2.2// The menu toggle
349+
// 2.1.2/ The menu toggle
347350
markup.push(
348351
`<div part=menu-toggle class=ML__menu-toggle role=button data-l10n-tooltip="tooltip.menu">`
349352
);
350353
markup.push(MENU_GLYPH);
351354
markup.push('</div>');
352355

356+
markup.push('</div>'); // end toggles wrapper
357+
353358
markup.push('</span>'); // end container
354359

355360
// 3.1/ The aria-live region for announcements
@@ -419,8 +424,9 @@ If you are using Vue, this may be because you are using the runtime-only build o
419424
}
420425
}
421426

422-
const virtualKeyboardToggle =
423-
this.element.querySelector<HTMLElement>('[part=virtual-keyboard-toggle]');
427+
const virtualKeyboardToggle = this.element.querySelector<HTMLElement>(
428+
'[part=virtual-keyboard-toggle]'
429+
);
424430
virtualKeyboardToggle?.addEventListener(
425431
'pointerdown',
426432
(ev) => {
@@ -463,7 +469,6 @@ If you are using Vue, this may be because you are using the runtime-only build o
463469
);
464470

465471
if (
466-
this.model.atoms.length <= 1 ||
467472
this.disabled ||
468473
(this.readOnly && !this.hasEditableContent) ||
469474
this.userSelect === 'none'
@@ -491,10 +496,15 @@ If you are using Vue, this may be because you are using the runtime-only build o
491496
this.resizeObserverStarted = false;
492497
return;
493498
}
499+
this.updateToggleLayout();
494500
requestUpdate(this);
495501
});
496502
this.resizeObserverStarted = true;
497503
this.resizeObserver.observe(this.field);
504+
this.resizeObserver.observe(this.container);
505+
506+
// Initial toggle layout check (delayed to ensure rendering is complete)
507+
setTimeout(() => this.updateToggleLayout(), 100);
498508

499509
window.mathVirtualKeyboard.addEventListener(
500510
'virtual-keyboard-toggle',
@@ -924,6 +934,26 @@ If you are using Vue, this may be because you are using the runtime-only build o
924934
}
925935
}
926936

937+
/** Update toggle button layout based on mathfield height */
938+
updateToggleLayout(): void {
939+
if (!this.element || !this.host) return;
940+
941+
const toggles = this.element.querySelector<HTMLElement>('.ML__toggles');
942+
if (!toggles) return;
943+
944+
// Use host height to account for both content height and CSS-specified height
945+
const height = this.host.offsetHeight;
946+
const hasVerticalClass = toggles.classList.contains(
947+
'ML__toggles--vertical'
948+
);
949+
950+
// Automatically apply vertical layout when mathfield is tall (>= 100px)
951+
if (height >= 100 && !hasVerticalClass)
952+
toggles.classList.add('ML__toggles--vertical');
953+
else if (height < 100 && hasVerticalClass)
954+
toggles.classList.remove('ML__toggles--vertical');
955+
}
956+
927957
dispose(): void {
928958
if (!isValidMathfield(this)) return;
929959

src/editor-mathfield/render.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ export function render(
203203
mathfield.userSelect === 'none'
204204
)
205205
hideMenu = true;
206-
// If the width of the element is less than 50px, hide the menu
207-
if (!hideMenu && field.offsetWidth < 50) hideMenu = true;
206+
// If the width of the mathfield element is less than 50px, hide the menu
207+
if (!hideMenu && mathfield.element.offsetWidth < 50) hideMenu = true;
208208

209209
menuToggle.style.display = hideMenu ? 'none' : '';
210210
}
@@ -229,6 +229,11 @@ export function render(
229229
//
230230
renderSelection(mathfield, renderOptions.interactive);
231231

232+
//
233+
// 5. Update toggle button layout based on content height
234+
//
235+
mathfield.updateToggleLayout();
236+
232237
mathfield.dirty = false;
233238
}
234239

0 commit comments

Comments
 (0)