Tab row: fit nine tabs inside the centre column
game-maker / suite (push) Successful in 7m49s

The ninth tab (Shader) pushed the row past the centre column: List
ended at 962 while the column ended at 925, so the last buttons sat
under the inspector and clickText('Container') hit the List tab
instead (CI runs 5 and 6, module 16). Tab buttons now use padding 4
via a new Button padding option; e2e step 14b guards the row width
using the widget box rather than getBounds(), which sees only the
label on an untoggled ghost button.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-12 23:09:30 +02:00
1 parent a32b7c6daa
commit 69615c1f4b
4 files changed
+42 -8

No files matched your search

+7 -3
View File
@@ -12,6 +12,8 @@ export interface ButtonOptions {
/** Floor only – for a button whose label changes between forms and must grow with them. */
minWidth?: number;
align?: 'center' | 'left';
/** Horizontal inset of the label; defaults to the theme padding. */
padding?: number;
/** Text style of the label when the button is not on an accent fill. */
style?: TextStyleToken;
onClick?: () => void;
@@ -28,6 +30,7 @@ export class Button extends Widget {
variant: NonNullable<ButtonOptions['variant']>;
protected readonly align: NonNullable<ButtonOptions['align']>;
protected readonly fixedWidth: number;
private readonly padding: number;
private readonly style: TextStyleToken;
onClick?: () => void;
@@ -41,6 +44,7 @@ export class Button extends Widget {
this.minHeight = Theme.controlHeight;
this.fixedWidth = options.width ?? 0;
this.minWidth = this.fixedWidth || (options.minWidth ?? 0);
this.padding = options.padding ?? Theme.padding;
this.fullText = text;
this.style = options.style ?? 'body';
this.labelText = new Text({ text, style: textStyle(this.variant === 'primary' ? 'accent' : this.style) });
@@ -102,14 +106,14 @@ export class Button extends Widget {
// Measured bold where it can be drawn bold (on an accent fill), or a danger or toggled tab truncates.
const style = textStyle(this.variant === 'default' ? this.style : 'accent');
const metrics = CanvasTextMetrics.measureText(this.fullText, style);
return { w: Math.max(this.minWidth, Math.ceil(metrics.width) + Theme.padding * 2), h };
return { w: Math.max(this.minWidth, Math.ceil(metrics.width) + this.padding * 2), h };
}
/** Width the label may occupy; subclasses that draw inside the button take their room off here. */
protected labelSlot(): number {
// The padding is an inset, not a claim: on a 24 px icon button it would leave 8 px and
// truncate the glyph away entirely. From 48 px up this is the full padding again.
return this.w - Math.min(Theme.padding, Math.floor(this.w / 6)) * 2;
return this.w - Math.min(this.padding, Math.floor(this.w / 6)) * 2;
}
override onKeyDown(event: KeyboardEvent): boolean {
@@ -157,7 +161,7 @@ export class Button extends Widget {
this.labelText.style = textStyle(this.onAccent ? 'accent' : this.style);
const label = this.labelText;
label.text = truncate(this.fullText, label.style, this.labelSlot());
const x = this.align === 'left' ? Theme.padding : (this.w - label.width) / 2;
const x = this.align === 'left' ? this.padding : (this.w - label.width) / 2;
label.position.set(Math.round(x), centreY(this.h, label.height));
}
}