From 49cd2e25b384b6d9cb400a6f5de195c3b621f336 Mon Sep 17 00:00:00 2001 From: "R.Eugenio" Date: Tue, 30 Dec 2025 20:24:10 +0100 Subject: [PATCH] feat(tabs): Add 3D bevel effect (Z-Design V3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add bevel: bool option to TabsConfig (default false) - Active tabs: raised effect (light top/left, dark bottom/right) - Inactive tabs: subtle inset for depth contrast - Respects tab_bg color for bevel calculations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/widgets/tabs.zig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/widgets/tabs.zig b/src/widgets/tabs.zig index 6966772..46538b3 100644 --- a/src/widgets/tabs.zig +++ b/src/widgets/tabs.zig @@ -103,6 +103,8 @@ pub const TabsConfig = struct { minimal: bool = false, /// Underline indicator height (for minimal mode) indicator_height: u32 = 2, + /// Z-Design V3: 3D bevel effect on tabs (raised for active, flat for inactive) + bevel: bool = false, }; /// Tabs colors @@ -281,6 +283,25 @@ pub fn tabsRect( } else { ctx.pushCommand(Command.rect(tab_rect.x, tab_rect.y, tab_rect.w, tab_rect.h, tab_bg)); } + + // Z-Design V3: 3D bevel effect + if (config.bevel and tab_rect.h >= 4 and tab_rect.w >= 4 and !tab.disabled) { + const bevel_light = tab_bg.lighten(15); + const bevel_dark = tab_bg.darken(15); + const inner_h = tab_rect.h -| 2; + + if (is_selected) { + // Active tab: raised effect (light on top/left) + ctx.pushCommand(Command.rect(tab_rect.x + 1, tab_rect.y + 1, tab_rect.w - 2, 1, bevel_light)); // Top + ctx.pushCommand(Command.rect(tab_rect.x + 1, tab_rect.y + 1, 1, inner_h, bevel_light)); // Left + ctx.pushCommand(Command.rect(tab_rect.x + 1, tab_rect.y + @as(i32, @intCast(tab_rect.h)) - 2, tab_rect.w - 2, 1, bevel_dark)); // Bottom + ctx.pushCommand(Command.rect(tab_rect.x + @as(i32, @intCast(tab_rect.w)) - 2, tab_rect.y + 1, 1, inner_h, bevel_dark)); // Right + } else { + // Inactive tab: flat or subtle inset (dark on top/left for "recessed" look) + ctx.pushCommand(Command.rect(tab_rect.x + 1, tab_rect.y + 1, tab_rect.w - 2, 1, bevel_dark.darken(5))); // Top (darker) + ctx.pushCommand(Command.rect(tab_rect.x + 1, tab_rect.y + 1, 1, inner_h, bevel_dark.darken(5))); // Left (darker) + } + } } // Draw active indicator (underline)