๐จ Color Utilities
April 21, 2026 ยท View on GitHub
Manipulation Functions
Neopywal offers a neat set of utility functions that allows the user to manipulate Neopywal's colors in case you want, for example, a darker color than color1. Or a brighter and more saturated version of the color color3.
These functions are all present under utils/color.lua module and can be required like so:
local U = require("neopywal.utils.color")
U.darken(color, factor)
U.lighten(color, factor)
U.blend(color1, color2, percentage)
U.brighten(color, percentage)
U.blacken(color, percentage)
U.saturate(color, percentage)
U.invert(color)
Important
All color parameters for the functions have to be in hexadecimal format (e.g.: "#000000").
Darken and Lighten
As the name suggests, the darken() and lighten() functions are able to create new colors by darkening/lightening existing colors.
Both functions take two parameters, the first one is the hexadecimal code of color you want to modify, the second is an integer from 0 to 100 that defines how much said color will be darken/lighten.
local C = require("neopywal").get_colors() -- Using catppuccin-mocha theme.
local U = require("neopywal.utils.color")
print(C.color1) -- For comparison: #F38BA8"
print(U.darken(C.color1, 70)) -- Output: "#AD4562"
print(U.lighten(C.color1, 70)) -- Output: "#FFD1EE"
Here's some visual interpretation for the colors.
| Normal vs Darken/Lighten | Hex | Color |
|
Hex: "#AD4562" | |
|
Hex: "#F38BA8" | |
|
Hex: "#FFD1EE" | |
It is important to know that these functions do NOT modify the color based on percentage values.
Instead they work in a more linear way by converting the hexadecimal color to it's numeric RGB values and then subtracting/adding the value present on the factor argument given to them.
Blend
The blend() function combines two colors to create a new color that is a mixture of the two colors specified.
The function takes three parameters, the first two parameters define the colors to be blended.
While the third percentage parameter is a number between 0 and 1 that determines the proportion of each color in the final output.
Where 1 means "use the exact same color as the first parameter" and 0 means "use the exact same color as the second parameter".
local C = require("neopywal").get_colors() -- Using catppuccin-mocha theme.
local U = require("neopywal.utils.color")
-- In this example:
-- `U.blend(C.color1, C.color3, 0)` will be identical to `C.color3`.
-- `U.blend(C.color1, C.color3, 1)` will be identical to `C.color1`.
-- `U.blend(C.color1, C.color3, 0.5)` will be a 50/50 mix of `C.color1` and `C.color3`.
print(C.color1) -- For comparison: #F38BA8"
print(C.color3) -- For comparison: "#F9E2AF"
print(U.blend(C.color1, C.color3, 0)) -- Output: "#F9E2AF"
print(U.blend(C.color1, C.color3, 1)) -- Output: "#F38BA8"
print(U.blend(C.color1, C.color3, 0.5)) -- Output: "#F6B7AC"
Here's some visual interpretation for the colors.
| Normal vs Blend | Hex | Color |
|
Hex: "#F38BA8" | |
|
Hex: "#F9E2AF" | |
|
Hex: "#F6B7AC" | |
Blacken and Brighten
The blacken() and the brighten() functions are similar to the darken() and lighten() functions. However they work in completely different ways.
While darken()/lighten() first convert the input hexadecimal color as a RGB number before manipulating it. blacken()/brighten() instead take the hexadecimal color and convert it to the HSL color space, were it will be manipulated by increasing/decreasing the "L" lightness value of the color based on a percentage.
Both functions take two parameters, the first one is the hexadecimal code of color you want to modify, and the second is an number from 0 to 1 that defines how much said color will be brightened/blackened out.
local C = require("neopywal").get_colors() -- Using catppuccin-mocha theme.
local U = require("neopywal.utils.color")
print(C.color1) -- For comparison: #F38BA8"
print(U.darken(C.color1, 70)) -- For comparison: "#AD4562"
print(U.blacken(C.color1, 0.7)) -- Output: "#621130"
print(U.darken(C.color1, 100)) -- For comparison: "#8F2744"
print(U.blacken(C.color1, 1)) -- Output: "#000000"
print(U.lighten(C.color1, 70)) -- For comparison: "#FFD1EE"
print(U.brighten(C.color1, 0.7)) -- Output: "#FBDEE4"
print(U.lighten(C.color1, 100)) -- For comparison: "#FFEFFF"
print(U.brighten(C.color1, 1)) -- Output: "#FFFFFF"
If you want to see the difference in the outputs of darken()/lighten() vs blacken()/brighten(), here's an table that compares the output of all functions using the catppuccin-mocha theme as the main Neopywal source palette.
| Darken vs Blacken | Hex | Color |
|
Hex: "#F38BA8" | |
|
Hex: "#AD4562" | |
|
Hex: "#621130" | |
|
Hex: "#8F2744" | |
|
Hex: "#000000" | |
| Lighten vs Brighten | Hex | Color |
|
Hex: "#F38BA8" | |
|
Hex: "#FFD1EE" | |
|
Hex: "#FBDEE4" | |
|
Hex: "#FFEFFF" | |
|
Hex: "#FFFFFF" | |
Saturate
The saturate() function increases/decreases the saturation of a given color.
It take two parameters, the first one is the hexadecimal code of color you want to modify, and the second is an number between -1 and 1 that defines how much said color will be saturated/desaturated.
local C = require("neopywal").get_colors() -- Using catppuccin-mocha theme.
local U = require("neopywal.utils.color")
print(C.color4) -- For comparison: "#89B4FA"
print(U.saturate(C.color4, 0.7)) -- Output: "#FA4B8D"
print(U.saturate(C.color4, -0.7)) -- Output: "#A1ADC6"
Here's some visual interpretation for the colors.
| Normal vs Saturated | Hex | Color |
|
Hex: "#89B4FA" | |
|
Hex: "#FA4B8D" | |
|
hex: "#A1ADC6" | |
Invert
The invert() simply takes an hexadecimal color code and, well ..., inverts it's color.
local C = require("neopywal").get_colors() -- Using catppuccin-mocha theme.
local U = require("neopywal.utils.color")
print(C.background) -- For comparison: "#1E1E2E"
print(U.invert(C.background)) -- Output: "#DCDCD4"
Here's some visual interpretation for the colors.
| Normal vs Invert | Hex | Color |
|
Hex: "#1E1E2E" | |
|
Hex: "#DCDCD4" | |