fix(buttons): Completar efecto bisel 3D con 4 lados

- Añadir líneas verticales (izquierda + derecha) al bisel
- Antes: solo 2 líneas horizontales (arriba + abajo)
- Ahora: 4 líneas formando marco 3D completo

Z-Design V2: Bisel con las 4 esquinas completas.
Normal: claro arriba/izquierda, oscuro abajo/derecha.
Pressed: invierte colores para efecto "hundido".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
R.Eugenio 2025-12-30 20:01:10 +01:00
parent 8f577e02b0
commit dd249d2b2d

View file

@ -105,20 +105,29 @@ pub fn buttonRect(ctx: *Context, bounds: Layout.Rect, text: []const u8, config:
ctx.pushCommand(Command.rectOutline(bounds.x, bounds.y, bounds.w, bounds.h, theme.border));
}
// Bisel 3D sutil: invierte cuando está pulsado (micro-interacción)
// Bisel 3D completo: 4 lados (invierte cuando está pulsado)
// Z-Design V2: Efecto 3D con las 4 esquinas completas
if (bounds.h >= 4 and bounds.w >= 4 and !config.disabled) {
const bevel_light = bg_color.lighten(15);
const bevel_dark = bg_color.darken(15);
const inner_h = bounds.h -| 2; // Altura interior para líneas verticales
if (pressed) {
// Pressed: bisel invertido (oscuro arriba, claro abajo) = "hundido"
const bevel_dark = bg_color.darken(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_dark));
const bevel_light = bg_color.lighten(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_light));
// Pressed: bisel invertido = "hundido"
// Arriba + izquierda: oscuro (sombra interior)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_dark)); // Top
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, 1, inner_h, bevel_dark)); // Left
// Abajo + derecha: claro (luz interior)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_light)); // Bottom
ctx.pushCommand(Command.rect(bounds.x + @as(i32, @intCast(bounds.w)) - 2, bounds.y + 1, 1, inner_h, bevel_light)); // Right
} else {
// Normal: bisel claro arriba, oscuro abajo = "elevado"
const bevel_light = bg_color.lighten(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_light));
const bevel_dark = bg_color.darken(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_dark));
// Normal: bisel = "elevado"
// Arriba + izquierda: claro (iluminado)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_light)); // Top
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, 1, inner_h, bevel_light)); // Left
// Abajo + derecha: oscuro (sombra)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_dark)); // Bottom
ctx.pushCommand(Command.rect(bounds.x + @as(i32, @intCast(bounds.w)) - 2, bounds.y + 1, 1, inner_h, bevel_dark)); // Right
}
}
@ -211,20 +220,29 @@ pub fn buttonStatefulRect(
ctx.pushCommand(Command.rectOutline(bounds.x, bounds.y, bounds.w, bounds.h, theme.border));
}
// Bisel 3D sutil: invierte cuando está pulsado (micro-interacción)
// Bisel 3D completo: 4 lados (invierte cuando está pulsado)
// Z-Design V2: Efecto 3D con las 4 esquinas completas
if (bounds.h >= 4 and bounds.w >= 4 and !config.disabled) {
const bevel_light = bg_color.lighten(15);
const bevel_dark = bg_color.darken(15);
const inner_h = bounds.h -| 2; // Altura interior para líneas verticales
if (pressed) {
// Pressed: bisel invertido (oscuro arriba, claro abajo) = "hundido"
const bevel_dark = bg_color.darken(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_dark));
const bevel_light = bg_color.lighten(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_light));
// Pressed: bisel invertido = "hundido"
// Arriba + izquierda: oscuro (sombra interior)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_dark)); // Top
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, 1, inner_h, bevel_dark)); // Left
// Abajo + derecha: claro (luz interior)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_light)); // Bottom
ctx.pushCommand(Command.rect(bounds.x + @as(i32, @intCast(bounds.w)) - 2, bounds.y + 1, 1, inner_h, bevel_light)); // Right
} else {
// Normal: bisel claro arriba, oscuro abajo = "elevado"
const bevel_light = bg_color.lighten(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_light));
const bevel_dark = bg_color.darken(15);
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_dark));
// Normal: bisel = "elevado"
// Arriba + izquierda: claro (iluminado)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, bounds.w - 2, 1, bevel_light)); // Top
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + 1, 1, inner_h, bevel_light)); // Left
// Abajo + derecha: oscuro (sombra)
ctx.pushCommand(Command.rect(bounds.x + 1, bounds.y + @as(i32, @intCast(bounds.h)) - 2, bounds.w - 2, 1, bevel_dark)); // Bottom
ctx.pushCommand(Command.rect(bounds.x + @as(i32, @intCast(bounds.w)) - 2, bounds.y + 1, 1, inner_h, bevel_dark)); // Right
}
}
@ -273,8 +291,8 @@ test "button generates commands" {
_ = button(&ctx, "Click me");
// Should generate: rect (background) + rect_outline (border) + 2 bevel lines + text
try std.testing.expectEqual(@as(usize, 5), ctx.commands.items.len);
// Should generate: rect (background) + rect_outline (border) + 4 bevel lines + text = 7
try std.testing.expectEqual(@as(usize, 7), ctx.commands.items.len);
ctx.endFrame();
}