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)