UI and Aesthetics Plugins
A polished UI makes long editing sessions more enjoyable and reduces cognitive friction. These plugins transform Neovim from a plain terminal editor into a visually refined tool.
1. Colorschemes
Catppuccin — The Most Popular Modern Theme
lua/plugins/colorscheme.lua
return {
{
"catppuccin/nvim",
name = "catppuccin",
lazy = false,
priority = 1000,
opts = {
flavour = "mocha", -- latte | frappe | macchiato | mocha
background = {
light = "latte",
dark = "mocha",
},
transparent_background = false,
show_end_of_buffer = false,
term_colors = true,
dim_inactive = {
enabled = false,
shade = "dark",
percentage = 0.15,
},
integrations = {
cmp = true,
gitsigns = true,
nvimtree = false,
neo_tree = true,
treesitter = true,
telescope = { enabled = true },
which_key = true,
indent_blankline = { enabled = true },
lsp_trouble = true,
mason = true,
bufferline = true,
noice = true,
notify = true,
mini = { enabled = true },
},
},
config = function(_, opts)
require("catppuccin").setup(opts)
vim.cmd.colorscheme("catppuccin")
end,
},
}
Tokyo Night — Dark and Clean
{
"folke/tokyonight.nvim",
lazy = false,
priority = 1000,
opts = {
style = "night", -- storm | night | moon | day
transparent = false,
terminal_colors = true,
styles = {
comments = { italic = true },
keywords = { italic = true },
functions = {},
variables = {},
},
sidebars = { "qf", "help", "neo-tree", "aerial" },
on_highlights = function(hl, c)
-- customize individual highlight groups
hl.LineNr = { fg = c.dark5 }
end,
},
config = function(_, opts)
require("tokyonight").setup(opts)
vim.cmd.colorscheme("tokyonight-night")
end,
},
Other Notable Colorschemes
| Plugin | Style | Notes |
|---|---|---|
rose-pine/neovim | Warm pastels | Great for focus |
EdenEast/nightfox.nvim | Multiple variants | Nordfox, Dawnfox |
rebelot/kanagawa.nvim | Japanese art-inspired | Elegant earthtones |
navarasu/onedark.nvim | Atom One Dark | Familiar and solid |
sainnhe/everforest | Nature-inspired green | Easy on the eyes |
bluz71/vim-moonfly-colors | Dark and vibrant | Excellent contrast |
projekt0n/github-nvim-theme | GitHub-accurate | Light and dark |
2. Lualine — Status Line
lua/plugins/ui.lua
{
"nvim-lualine/lualine.nvim",
event = "VeryLazy",
dependencies = { "nvim-tree/nvim-web-devicons" },
opts = {
options = {
icons_enabled = true,
theme = "catppuccin", -- matches your colorscheme
component_separators = { left = "", right = "" },
section_separators = { left = "", right = "" },
disabled_filetypes = {
statusline = { "dashboard", "alpha", "ministarter" },
},
always_divide_middle = true,
globalstatus = true, -- single status bar for all windows
},
sections = {
lualine_a = { "mode" },
lualine_b = {
{ "branch", icon = "" },
{
"diff",
symbols = { added = " ", modified = " ", removed = " " },
},
{
"diagnostics",
symbols = { error = " ", warn = " ", info = " ", hint = " " },
},
},
lualine_c = {
{ "filename", path = 1, symbols = { modified = " ●", readonly = " ", unnamed = "" } },
},
lualine_x = {
{
-- Show active LSP clients
function()
local clients = vim.lsp.get_clients({ bufnr = 0 })
if #clients == 0 then return "" end
local names = vim.tbl_map(function(c) return c.name end, clients)
return " " .. table.concat(names, ", ")
end,
},
"encoding",
{ "fileformat", symbols = { unix = "LF", dos = "CRLF", mac = "CR" } },
"filetype",
},
lualine_y = { "progress" },
lualine_z = { "location" },
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = { "filename" },
lualine_x = { "location" },
lualine_y = {},
lualine_z = {},
},
tabline = {},
extensions = { "neo-tree", "lazy", "fugitive", "aerial" },
},
},
3. Bufferline — Buffer Tabs
{
"akinsho/bufferline.nvim",
event = "VeryLazy",
dependencies = { "nvim-tree/nvim-web-devicons" },
keys = {
{ "<leader>bp", "<cmd>BufferLineTogglePin<cr>", desc = "Pin buffer" },
{ "<leader>bP", "<cmd>BufferLineGroupClose ungrouped<cr>", desc = "Close unpinned" },
{ "<Tab>", "<cmd>BufferLineCycleNext<cr>", desc = "Next buffer" },
{ "<S-Tab>", "<cmd>BufferLineCyclePrev<cr>", desc = "Prev buffer" },
},
opts = {
options = {
mode = "buffers",
numbers = "none",
close_command = "bdelete! %d",
right_mouse_command = "bdelete! %d",
indicator = { style = "icon", icon = "▎" },
buffer_close_icon = "",
modified_icon = "●",
close_icon = "",
left_trunc_marker = "",
right_trunc_marker = "",
diagnostics = "nvim_lsp",
diagnostics_indicator = function(count, level)
local icon = level:match("error") and " " or " "
return " " .. icon .. count
end,
offsets = {
{
filetype = "neo-tree",
text = " File Explorer",
highlight = "Directory",
separator = true,
},
},
color_icons = true,
show_buffer_icons = true,
show_buffer_close_icons = false,
show_close_icon = false,
show_tab_indicators = true,
persist_buffer_sort = true,
separator_style = "slant", -- slant | thick | thin | padded_slant
enforce_regular_tabs = true,
always_show_bufferline = false,
hover = { enabled = true, delay = 200, reveal = { "close" } },
sort_by = "insert_after_current",
},
},
},
4. Noice.nvim — Completely Replace the UI
noice.nvim replaces Neovim's default cmdline, messages, and popupmenu with a beautiful floating UI.
{
"folke/noice.nvim",
event = "VeryLazy",
dependencies = {
"MunifTanjim/nui.nvim",
"rcarriga/nvim-notify",
},
opts = {
lsp = {
override = {
-- Override markdown rendering with Treesitter
["vim.lsp.util.convert_input_to_markdown_lines"] = true,
["vim.lsp.util.stylize_markdown"] = true,
["cmp.entry.get_documentation"] = true,
},
signature = { enabled = true, auto_open = { enabled = true } },
},
presets = {
bottom_search = true, -- classic bottom search bar
command_palette = true, -- position cmdline + popupmenu together
long_message_to_split = true, -- long messages go to split
inc_rename = false,
lsp_doc_border = true, -- add border to hover docs
},
routes = {
-- Suppress "written" message
{ filter = { event = "msg_show", kind = "", find = "written" }, opts = { skip = true } },
-- Suppress search count messages
{ filter = { event = "msg_show", kind = "search_count" }, opts = { skip = true } },
},
views = {
cmdline_popup = {
position = { row = "40%", col = "50%" },
size = { width = 60, height = "auto" },
border = { style = "rounded", padding = { 0, 1 } },
},
},
},
},
5. nvim-notify — Beautiful Notifications
{
"rcarriga/nvim-notify",
opts = {
timeout = 3000,
render = "wrapped-compact",
stages = "fade_in_slide_out",
top_down = true,
max_height = function() return math.floor(vim.o.lines * 0.75) end,
max_width = function() return math.floor(vim.o.columns * 0.75) end,
on_open = function(win)
vim.api.nvim_win_set_config(win, { zindex = 100 })
end,
icons = {
DEBUG = "",
ERROR = "",
INFO = "",
TRACE = "✎",
WARN = "",
},
},
config = function(_, opts)
require("notify").setup(opts)
vim.notify = require("notify")
end,
},
6. Alpha-nvim — Startup Dashboard
{
"goolord/alpha-nvim",
event = "VimEnter",
config = function()
local alpha = require("alpha")
local dashboard = require("alpha.themes.dashboard")
-- Custom header (ASCII art)
dashboard.section.header.val = {
" ",
" ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗",
" ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║",
" ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║",
" ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║",
" ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║",
" ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝",
" ",
}
-- Buttons
dashboard.section.buttons.val = {
dashboard.button("f", " Find file", ":Telescope find_files<CR>"),
dashboard.button("g", " Find text", ":Telescope live_grep<CR>"),
dashboard.button("r", " Recent files", ":Telescope oldfiles<CR>"),
dashboard.button("s", " Restore session", ":lua require('persistence').load()<CR>"),
dashboard.button("c", " Config", ":e ~/.config/nvim/init.lua<CR>"),
dashboard.button("l", " Lazy plugins", ":Lazy<CR>"),
dashboard.button("q", " Quit", ":qa<CR>"),
}
-- Footer: plugin count
local function footer()
local stats = require("lazy").stats()
return string.format(" %d plugins — loaded in %.0fms", stats.count, stats.startuptime)
end
dashboard.section.footer.val = footer()
dashboard.section.footer.opts.hl = "Type"
alpha.setup(dashboard.opts)
-- Close alpha when a file is opened
vim.api.nvim_create_autocmd("User", {
pattern = "LazyVimStarted",
callback = function()
dashboard.section.footer.val = footer()
pcall(vim.cmd.AlphaRedraw)
end,
})
end,
},
7. Indent Blankline v3 — Indent Guides
{
"lukas-reineke/indent-blankline.nvim",
main = "ibl",
event = { "BufReadPost", "BufNewFile" },
opts = {
indent = {
char = "│",
tab_char = "│",
},
scope = {
enabled = true,
show_start = true,
show_end = false,
injected_languages = false,
highlight = { "Function", "Label" },
priority = 500,
},
exclude = {
filetypes = {
"help", "alpha", "dashboard", "neo-tree",
"Trouble", "lazy", "mason", "notify",
"toggleterm", "lazyterm", "TelescopePrompt",
},
},
},
},
8. vim-illuminate — Highlight Word Under Cursor
{
"RRethy/vim-illuminate",
event = { "BufReadPost", "BufNewFile" },
opts = {
delay = 200,
large_file_cutoff = 2000,
large_file_overrides = { providers = { "lsp" } },
providers = { "lsp", "treesitter", "regex" },
},
config = function(_, opts)
require("illuminate").configure(opts)
-- Navigate illuminated matches
vim.keymap.set("n", "]]", function()
require("illuminate").goto_next_reference(false)
end, { desc = "Next reference" })
vim.keymap.set("n", "[[", function()
require("illuminate").goto_prev_reference(false)
end, { desc = "Prev reference" })
end,
},
9. Dressing.nvim — Better vim.ui
{
"stevearc/dressing.nvim",
lazy = true,
init = function()
---@diagnostic disable-next-line: duplicate-set-field
vim.ui.select = function(...)
require("lazy").load({ plugins = { "dressing.nvim" } })
return vim.ui.select(...)
end
---@diagnostic disable-next-line: duplicate-set-field
vim.ui.input = function(...)
require("lazy").load({ plugins = { "dressing.nvim" } })
return vim.ui.input(...)
end
end,
opts = {
input = {
default_prompt = "➤ ",
win_options = { winhighlight = "Normal:Normal,NormalNC:Normal" },
},
select = {
backend = { "telescope", "fzf_lua", "builtin" },
builtin = {
win_options = { winhighlight = "Normal:Normal,NormalNC:Normal" },
},
},
},
},