From b08592c1bbc77514e40b8f03a13d0813af0217c3 Mon Sep 17 00:00:00 2001 From: Takuya Matsuyama Date: Tue, 11 Aug 2026 11:30:58 +0900 Subject: [PATCH] feat(vivid): Add a high-contrast style for bright environments Add `vivid`, a dark variant whose text colors are pushed toward white in HSLuv space so hue and saturation stay put and only brightness moves. Comments go from 3.45:1 to 6.21:1 against the background and syntax colors land between 6.8:1 and 8.8:1, which keeps the theme readable outdoors without switching every tool over to a light theme. Background tokens are left alone since brightening those would reduce contrast rather than add it. The boost is proportional to the remaining headroom, so already bright colors barely move and the palette keeps its internal ordering. Also rename the day colorscheme to solarized-osaka-light to match the style name it loads. --- ...saka-day.lua => solarized-osaka-light.lua} | 0 colors/solarized-osaka-vivid.lua | 1 + lua/solarized-osaka/colors.lua | 34 +++++++++++++++++++ lua/solarized-osaka/config.lua | 3 +- lua/solarized-osaka/util.lua | 14 ++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) rename colors/{solarized-osaka-day.lua => solarized-osaka-light.lua} (100%) create mode 100644 colors/solarized-osaka-vivid.lua diff --git a/colors/solarized-osaka-day.lua b/colors/solarized-osaka-light.lua similarity index 100% rename from colors/solarized-osaka-day.lua rename to colors/solarized-osaka-light.lua diff --git a/colors/solarized-osaka-vivid.lua b/colors/solarized-osaka-vivid.lua new file mode 100644 index 0000000..e1b1623 --- /dev/null +++ b/colors/solarized-osaka-vivid.lua @@ -0,0 +1 @@ +require("solarized-osaka")._load("vivid") diff --git a/lua/solarized-osaka/colors.lua b/lua/solarized-osaka/colors.lua index e31dae7..154f036 100644 --- a/lua/solarized-osaka/colors.lua +++ b/lua/solarized-osaka/colors.lua @@ -182,6 +182,40 @@ M.light = { fg = M.default.base01, } +local background_tokens = { + none = true, + bg = true, + bg_highlight = true, + base02 = true, + base03 = true, + base04 = true, +} + +local background_tiers = { + ["700"] = true, + ["900"] = true, + ["950"] = true, +} + +---@param name string +---@return boolean +local function is_background_token(name) + return background_tokens[name] or background_tiers[name:sub(-3)] or false +end + +--- A higher-contrast dark variant for bright environments +---@return Palette +M.vivid = function() + local amount = require("solarized-osaka.config").options.vivid_brightness + local palette = {} + for name, hex in pairs(M.default) do + if not is_background_token(name) then + palette[name] = util.brighten(hex, amount) + end + end + return palette +end + ---@return ColorScheme function M.setup(opts) opts = opts or {} diff --git a/lua/solarized-osaka/config.lua b/lua/solarized-osaka/config.lua index a6121a2..310030d 100644 --- a/lua/solarized-osaka/config.lua +++ b/lua/solarized-osaka/config.lua @@ -4,7 +4,7 @@ local M = {} ---@field on_colors fun(colors: ColorScheme) ---@field on_highlights fun(highlights: Highlights, colors: ColorScheme) local defaults = { - style = "", -- The theme comes in three styles, `storm`, a darker variant `night` and `day` + style = "", -- The default dark style. Set to `vivid` for a higher-contrast variant that stays readable in bright environments light_style = "light", -- The theme is used when the background is set to light transparent = true, -- Enable this to disable setting the background color terminal_colors = true, -- Configure the colors used when opening a `:terminal` in Neovim @@ -21,6 +21,7 @@ local defaults = { }, sidebars = { "qf", "help" }, -- Set a darker background on sidebar-like windows. For example: `["qf", "vista_kind", "terminal", "packer"]` day_brightness = 0.3, -- Adjusts the brightness of the colors of the **Day** style. Number between 0 and 1, from dull to vibrant colors + vivid_brightness = 0.3, -- Adjusts how far the **Vivid** style brightens text colors. Number between 0 and 1, from the default palette to white hide_inactive_statusline = false, -- Enabling this option, will hide inactive statuslines and replace them with a thin border instead. Should work with the standard **StatusLine** and **LuaLine**. dim_inactive = false, -- dims inactive windows lualine_bold = false, -- When `true`, section headers in the lualine theme will be bold diff --git a/lua/solarized-osaka/util.lua b/lua/solarized-osaka/util.lua index d1f5db9..89c2d9f 100644 --- a/lua/solarized-osaka/util.lua +++ b/lua/solarized-osaka/util.lua @@ -36,6 +36,20 @@ function M.lighten(hex, amount, fg) return M.blend(hex, fg or M.fg, amount) end +--- Raises a color's perceptual lightness toward white, leaving hue and saturation untouched +---@param hex string +---@param amount number between 0 and 1, from unchanged to white +---@return string +function M.brighten(hex, amount) + if hex == "NONE" then + return hex + end + local hsluv = require("solarized-osaka.hsluv") + local color = hsluv.hex_to_hsluv(hex) + color[3] = color[3] + (100 - color[3]) * amount + return hsluv.hsluv_to_hex(color) +end + function M.invert_color(color) local hsluv = require("solarized-osaka.hsluv") if color ~= "NONE" then