Skip to content

🌡 A collection of 13 desert-inspired Neovim colorschemes: one for every color of the rainbow.

License

Notifications You must be signed in to change notification settings

uhs-robert/oasis.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

logo


πŸŒ… Overview

Born from the classic desert.vim, transformed and modernized into something new entirely.

Oasis follows a warm/cool color split philosophy (warm = action/flow, cool = structure/data).

All themes meet AAA WCAG compliance standards. Light themes allow contrast ratio to be customized.

preview

✨ What's New / 🚨 Breaking Changes
🚨 v4.0: Dual Style Themes / Deprecated Themes

✨ Dual Style Themes

Each style now has 5 light theme variants.

🚨 BREAKING CHANGE: Deprecated Light Theme Migration

The following standalone light themes have been deprecated in favor of the dual-mode system:
Dawn Replaced with light_intensity = 1
Dawnlight Replaced with light_intensity = 2
Day Replaced with light_intensity = 3
Dusk Replaced with light_intensity = 4
Dust Replaced with light_intensity = 5
> The best match for the old light themes is night which also resolves accessibility issues.
Deprecated themes will be completely removed around January 1st of 2026.
🚨 v3.0: Themed Syntax

✨ Dual style themes

Each style now uses its signature color for statements and keywords.
Prefer the classic yellow syntax? See how to opt-out under API Commands ↓

πŸŒ™ Dark Styles

Click any card below to view the full preview and syntax sample. ↓ Or click here to view all full previews

Dark Previews

Night (dark)
Night
Night Sky
Midnight (dark)
Midnight
Off Black
Abyss (dark)
Abyss
Black
Starlight (dark)
Starlight
Black Vivid
Desert (dark)
Desert
Grey
Sol (dark)
Sol
Red
Canyon (dark)
Canyon
Orange
Dune (dark)
Dune
Yellow
Cactus (dark)
Cactus
Green
Mirage (dark)
Mirage
Teal
Lagoon (dark)
Lagoon (Default)
Blue
Twilight (dark)
Twilight
Purple
Rose (dark)
Rose
Pink

β˜€οΈ Light Styles

Light styles use a saturation intensity scale from 1-5: set from config or via :OasisIntensity.

Light theme intensity scale (Lagoon example)

Lagoon light intensity 1
1
Lagoon light intensity 2
2
Lagoon light intensity 3
3
Lagoon light intensity 4
4
Lagoon light intensity 5
5

Use :OasisIntensity to step through intensity levels 1 β†’ 5 in light mode.

Note

The Night style uses the darkest light backgrounds (lightness 78-84%) compared to the rest.

This provides a middle ground between traditional light and dark modes.

Light Previews

The examples below use the default intensity of level 3.

Night (light)
Night
Midnight (light)
Midnight
Abyss (light)
Abyss
Starlight (light)
Starlight
Desert (light)
Desert
Sol (light)
Sol
Canyon (light)
Canyon
Dune (light)
Dune
Cactus (light)
Cactus
Mirage (light)
Mirage
Lagoon (light)
Lagoon
Twilight (light)
Twilight
Rose (light)
Rose

✨ Features

  • 13 theme styles with dual modes: Each theme offers both dark and light variants with 5 adjustable intensity levels.
  • Dark/Light Modes: Automatic switching based on your system theme or vim.o.background.
  • Comprehensive highlighting - LSP, Tree-sitter, and plugin support
  • Fast loading - Direct highlight application for optimal performance based on the plugins in your config
  • Zero dependencies - Works out of the box without external plugins
  • Modular architecture - Easy to customize and extend
πŸ’ͺ Supported Plugins
Plugin
fzf-lua
gitsigns.nvim
snacks.nvim
which-key.nvim

Note

Oasis goes beyond Neovim with themes for web browsers, terminals, development tools, and more. Don't miss the Extras!

🍭 Extras

All extra configs for other applications.

To use the extras, refer to their respective documentation.

Tool Extra
Alacritty extras/alacritty
Bat extras/bat
Btop extras/btop
Dark Reader extras/dark-reader
Firefox extras/firefox
Foot extras/foot
FZF extras/fzf
Gemini CLI extras/gemini-cli
Ghostty extras/ghostty
iTerm extras/iterm
JSON-theme extras/json-theme
Kitty extras/kitty
Konsole extras/konsole
LazyGit extras/lazygit
Lua-theme extras/lua-theme
Slack extras/slack
Termux extras/termux
Thunderbird extras/thunderbird
TMUX tmux-oasis
Vimium C extras/vimium-c
Warp extras/warp
WezTerm extras/wezterm
Yazi extras/yazi
Zed extras/zed

If you'd like an extra config added, raise a feature request and I'll put it together.

πŸ“¦ Installation

Install the theme with your preferred package manager, such as folke/lazy.nvim:

{
  "uhs-robert/oasis.nvim",
  lazy = false,
  priority = 1000,
  config = function()
    require("oasis").setup()      -- (see Configuration below for all customization options)
    vim.cmd.colorscheme("oasis")  -- After setup, apply theme (or any style like "oasis-night")
  end
}

πŸš€ Usage

After calling setup(), use :colorscheme to apply or swap styles:

vim.cmd.colorscheme("oasis")         -- Use your config settings
vim.cmd.colorscheme("oasis-desert")  -- Or load any specific style
πŸ–ŒοΈ All colorscheme commands
" Uses your config settings
colorscheme oasis

" Or load a specific style - must be prefixed with `oasis-`
colorscheme oasis-night
colorscheme oasis-midnight
colorscheme oasis-abyss
colorscheme oasis-starlight
colorscheme oasis-desert
colorscheme oasis-sol
colorscheme oasis-canyon
colorscheme oasis-dune
colorscheme oasis-cactus
colorscheme oasis-mirage
colorscheme oasis-lagoon
colorscheme oasis-twilight
colorscheme oasis-rose
πŸ•΅οΈβ€β™‚οΈ Different Themes for Different Environments

Don't just pick a favorite. Assign themes based on variables like sudo to easily differentiate between your NeoVim environments. For example:

  • Use sol when root and/or doing a sudoedit
  • Use mirage when remote
  • And/or use any theme for any combination above, the only limit is your imagination
local uid = (vim.uv or vim.loop).getuid()
local is_root = uid == 0
local is_remote = vim.env.SSH_CONNECTION ~= nil or vim.env.SSH_TTY ~= nil
local is_sudoedit = (not is_root) and vim.env.SUDOEDIT == "1" -- This requires your shell's config to export a flag like: SUDO_EDITOR="env SUDOEDIT=1 /usr/bin/nvim"

local function pick_colorscheme()
  local is_elevated = is_root or is_sudoedit
  if is_remote then
    return is_elevated and "oasis-abyss" or "oasis-mirage"
  else
    return is_elevated and "oasis-sol" or "oasis"
  end
end

return {
    "uhs-robert/oasis.nvim",
    lazy = false,
    priority = 1000,
    config = function()
      require("oasis").setup()
      vim.cmd.colorscheme(pick_colorscheme())
    end
  }
🌡 Some plugins may need extra configuration to work

LazyVim

To override the tokyonight default and start fresh in the oasis:

-- No need to apply vim.cmd.colorscheme(), just use this instead! Also works with the different themes for different environments example above.
  {
  "LazyVim/LazyVim",
  opts = {
    colorscheme = "oasis",
  },
},

Lualine

To include automatic Lualine theme integration:

require("lualine").setup {
  options = {
    theme = "oasis"  -- Automatically matches your current Oasis style
  }
}

Tabby (Tab Bar)

To include tab bar theme integration:

require("tabby").setup({
  theme = "oasis" -- Automatically matches your current Oasis style
})
⚑ API Commands

Toggle Transparency

Toggle transparency on-the-fly without restarting:

:OasisTransparency
-- Or use the Lua API
require("oasis").toggle_transparency()

-- Example: bind to a keymap
vim.keymap.set("n", "<leader>tt", require("oasis").toggle_transparency, { desc = "Toggle transparency" })

Toggle Themed Syntax

Toggle the themed_syntax option on-the-fly to switch between themed and classic syntax highlighting (dark themes only):

:OasisThemedSyntax
-- Or use the Lua API
require("oasis").toggle_themed_syntax()

-- Example: bind to a keymap
vim.keymap.set("n", "<leader>ts", require("oasis").toggle_themed_syntax, { desc = "Toggle themed syntax" })

⚠️ v3.0 Breaking Change: Themed syntax is now enabled by default. To restore classic syntax highlighting, disable it:

require("oasis").setup({
  themed_syntax = false,  -- Use traditional yellow/khaki for all styles
})

This option controls how statement/keyword colors are rendered:

  • Enabled (default): Statements and keywords use the theme's primary color (e.g., blue in lagoon, teal in mirage, orange in canyon)
  • Disabled: Statements and keywords use traditional yellow/khaki tones across all styles

Cycle Light Intensity

Cycle the light background intensity (1–5) without reloading to test the waters:

:OasisIntensity
-- Or use the Lua API
require("oasis").cycle_intensity()

-- Example: bind to a keymap
vim.keymap.set("n", "<leader>uB", function()
  require("oasis").cycle_intensity() -- nil|true shows ui picker, false will cycle
end, { desc = "Select light mode intensity" })
  • Applies to light palettes only (dark palettes ignore intensity).
  • Default intensity is configurable via light_intensity in setup().

WCAG Accessibility Checker

Check WCAG 2.1 contrast compliance for palettes:

" Check all palettes
:OasisWCAG

" Check specific palette
:OasisWCAG oasis_lagoon
-- Lua API
local wcag = require("oasis.tools.wcag_checker")

-- Analyze all palettes
local all_results = wcag.analyze_all()
wcag.print_comparison_table(all_results)

-- Analyze specific palette
local results = wcag.analyze_palette("oasis_lagoon")
wcag.print_palette_results(results)

-- Calculate contrast ratio between two colors
local ratio = wcag.get_contrast_ratio("#e0def4", "#191724")  -- Returns: 12.44

-- Get compliance level
local level = wcag.get_compliance_level(ratio, false)  -- Returns: "AAA"

WCAG Standards:

  • AAA (7.0:1): Enhanced contrast for normal text
  • AA (4.5:1): Minimum contrast for normal text
  • AA Large (3.0:1): Minimum for large text (18pt+ or 14pt+ bold)

Reference: WCAG 2.1 Guidelines

[!NOTE] Light themes can appear muddy and make syntax hard to distinguish when everything is AAA.

If you need AAA compliance then set force_aaa = true otherwise tune the min_ratio to meet your needs.

βš™οΈ Configuration

Oasis offers many different styles to choose from. Have fun customizing with setup()!

🍦 Default Options
-- Oasis.nvim
-- Styles: "night", "midnight", "abyss", "starlight", "desert", "sol", "canyon", "dune", "cactus", "mirage", "lagoon", "twilight", "rose"
require("oasis").setup({
  style = "lagoon",                     -- Primary style, default used when colorscheme is set to "oasis"
  dark_style = "auto",                  -- Applies to your primary style only: "auto" uses `style`. Or override with another dark theme (e.g., "abyss")
  light_style = "auto",                 -- Applies to your primary style only: "auto" uses `style`. Or override with another light theme (e.g., "dune")
  light_intensity = 3,                  -- Light background intensity (1-5): 1=subtle, 5=saturated
  use_legacy_comments = false,          -- For "desert" style only, uses the loud skyblue comment color from desert.vim for a more retro experience
  themed_syntax = true,                 -- Uses the theme's primary color for statements/keywords. Set to false for the classic yellow syntax from desert.vim for a more retro experience

  -- Text styling - toggle individual styles
  styles = {
    bold = true,                        -- Enable bold text (keywords, functions, etc.)
    italic = true,                      -- Enable italics (comments, certain keywords)
    underline = true,                   -- Enable underlined text (matching words)
    undercurl = true,                   -- Enable undercurl for diagnostics/spelling
    strikethrough = true,               -- Enable strikethrough text (deprecations)
  },

  -- Display options
  transparent = false,                  -- Set to true for transparent backgrounds (bye-bye theme backgrounds)
  terminal_colors = true,               -- Apply Oasis colors to Neovim's built-in terminal

  -- Contrast controls (WCAG: AA = 4.5, AAA = 7.0)
  contrast = {
    -- Note: Light themes obey the targets below. All dark themes target 7.0 by default with only a couple of exceptions that dip to 6.5.
    min_ratio = 5.8,                    -- Clamp 4.5–7.0; target contrast for syntax/terminal colors. Increase for more contrast, decrease for more pop.
    force_aaa = false,                  -- When true, forces AAA (7.0) wherever possible; as a result some colors will appear muddy (bye bye non-primary colors).
  },

  palette_overrides = {},               -- Override colors in specific palettes
  highlight_overrides = {},             -- Override specific highlight groups
})

πŸͺ“ Overriding Colors & Highlight Groups

Thirsty for total control? You can override whatever you like.

Whoever drinketh of the water that I shall give him, shall never thirst...

🎨 Changing Palette Colors for Each Style

palette_overrides - Customize colors in palettes. Supports two methods for updating:

Static Table (no access to palette)

require("oasis").setup({
  palette_overrides = {
    -- Global light overrides (applies to ALL themes)
    light = {
      bg = { core = "#FFF8F0" }
    },

    -- Global light intensity 3 (applies to ALL themes)
    light_3 = {
      bg = { core = "#FFEFE0" }
    },

    -- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
    lagoon = {
      syntax = { string = "#FFA0A0", punctuation = "#F89D82", comment = "#665D55" },
      ui = { border = "#FFA247" },

      -- Light mode for this theme
      light = {
        syntax = { comment = "#404040" }
      },

      -- Specific intensity for this theme
      light_5 = {
        bg = { core = "#FFE8D0" }
      }
    }
  }
})

Function (with palette access)

require("oasis").setup({
  palette_overrides = function(c, colors)
    ---@type OasisPaletteOverrides
    return {
      -- c = current palette
      -- colors = base palette from palette.lua (Tailwind-style colors and access to all palettes)

      -- Global light overrides (applies to ALL themes)
      light = {
        syntax = {
          comment = c.fg.dim,          -- Reference current palette
          string = colors.rose[500]    -- Reference global colors
        }
      },

      -- Global light intensity 3 (applies to ALL themes)
      light_3 = {
        bg = { core = "#FFEFE0" }
      },

      -- Global palette overrides
      syntax = {
        comment = c.fg.dim,
        statement = colors.khaki[500],
      },

      -- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
      lagoon = {
        syntax = {
          string = colors.rose[500],
          punctuation = colors.peach[500],
          comment = c.fg.dim
        },

        -- Light mode for this theme
        light = {
          syntax = { string = colors.red[800] }
        },

        -- Specific intensity for this theme
        light = {
          syntax = { string = colors.red[800] }
        }
      }
    }
  end
})

Precedence: Global β†’ Global light β†’ Global light_N β†’ Theme β†’ Theme light β†’ Theme light_N

See Color Palettes for each theme's palette structure and Palette for all base colors.

πŸ’… Changing Colors for Highlight Groups

highlight_overrides - Override or add highlight groups. Supports two methods for updating:

Static Table (no access to palette)

require("oasis").setup({
  highlight_overrides = {
    -- Global (applies to all themes, all modes)
    Comment = { fg = "#808080", italic = true },
    Function = { fg = "#E06C75", bold = true },
    Identifier = "Function",  -- Link to another group

    -- Global light mode (all themes, all intensities)
    light = {
      Comment = { fg = "#606060" },
      Normal = { bg = "#000000" },
    },

    -- Global light intensity 3 (all themes)
    light_3 = {
      Normal = { bg = "#FFF8F0" }
    },

    -- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
    desert = {
      String = { fg = "#FFA0A0" },

      -- Desert light mode
      light = {
        String = { fg = "#6BA5C8" }
      },

      -- Desert light intensity 3
      light_3 = {
        Normal = { bg = "#FFF0E0" }
      }
    }
  }
})

Function (with palette access)

require("oasis").setup({
  highlight_overrides = function(c, colors)
    ---@type OasisHighlightOverrides
    return {
      -- c = current palette
      -- colors = base palette from palette.lua (Tailwind-style colors)

      Comment = { fg = c.fg.dim, italic = true },
      String = { fg = colors.red[500] },
      Function = { fg = c.theme.primary },

      -- Global light overrides
      light = {
        Comment = { fg = c.fg.muted }
      },

      -- Per-theme with palette access
      desert = {
        String = { fg = colors.sky[500] },
        light = {
          String = { fg = colors.sky[700] }
        }
      }
    }
  end
})

Precedence: Global β†’ Global light β†’ Global light_N β†’ Theme β†’ Theme light β†’ Theme light_N

See Theme Generator for all highlight groups.

See Color Palettes for each theme's palette structure and Palette for all base colors.

πŸ‘€ View All Theme Styles

All styles (click to collapse)
πŸŒ•οΈ Dark Previews

Night (Dark Β· Night Sky)

↑ Back to Dark Styles

Midnight (Dark Β· Off Black)

↑ Back to Dark Styles

Abyss (Dark Β· Black)

↑ Back to Dark Styles

Starlight (Dark Β· Black Vivid)

↑ Back to Dark Styles

Desert (Dark Β· Grey)

↑ Back to Dark Styles

Sol (Dark Β· Red)

↑ Back to Dark Styles

Canyon (Dark Β· Orange)

↑ Back to Dark Styles

Dune (Dark Β· Yellow)

↑ Back to Dark Styles

Cactus (Dark Β· Green)

↑ Back to Dark Styles

Mirage (Dark Β· Teal)

↑ Back to Dark Styles

Lagoon (Dark Β· Default)

↑ Back to Dark Styles

Twilight (Dark Β· Purple)

↑ Back to Dark Styles

Rose (Dark Β· Pink)

↑ Back to Dark Styles

🌞 Light Previews

Night (Light)

↑ Back to Light Styles

Midnight (Light)

↑ Back to Light Styles

Abyss (Light)

↑ Back to Light Styles

Starlight (Light)

↑ Back to Light Styles

Desert (Light)

↑ Back to Light Styles

Sol (Light)

↑ Back to Light Styles

Canyon (Light)

↑ Back to Light Styles

Dune (Light)

↑ Back to Light Styles

Cactus (Light)

↑ Back to Light Styles

Mirage (Light)

↑ Back to Light Styles

Lagoon (Light)

↑ Back to Light Styles

Twilight (Light)

↑ Back to Light Styles

Rose (Light)

↑ Back to Light Styles