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.
This commit is contained in:
Takuya Matsuyama 2026-08-11 11:30:58 +09:00
parent f675d9a5c5
commit b08592c1bb
5 changed files with 51 additions and 1 deletions

View file

@ -0,0 +1 @@
require("solarized-osaka")._load("vivid")

View file

@ -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 {}

View file

@ -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

View file

@ -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