Skip to content

Palette Customization

alsi-lawr edited this page Jul 11, 2026 · 1 revision

Palette customization

Neotheme highlights consume a complete semantic palette. Semantic roles describe what a color does, not which built-in theme supplied it.

Use configure_palette to modify the selected built-in palette before highlights are applied:

require("neotheme").setup({
	theme = "gruber-dark",
	configure_palette = function(palette)
		palette.ui.accent = palette.syntax.function_name
		palette.diagnostic.warning = "#e0a84e"
		palette.surface.selected = palette.surface.raised
	end,
})

The function receives a private copy. Mutating it cannot alter the registered built-in theme.

Surface roles

Role Intended use
surface.deepest Deep shadows and the lowest visual layer
surface.dark Sidebars, fold columns, inactive recessed areas
surface.base Main editor and terminal background
surface.raised Floats, menus, cursor lines, and elevated panels
surface.selected Selected rows, active references, and focused items
surface.border Window, float, and menu borders
surface.muted Low-contrast UI marks and ignored content
surface.addition Added-line background and read references
surface.error Error-message background

Text roles

Role Intended use
text.primary Normal editor and UI text
text.bright Brighter punctuation, completion text, and stdout
text.strong High-emphasis text and selected labels
text.muted Inactive, secondary, concealed, and hint text
text.on_accent Text drawn on accent, cursor, or search backgrounds
text.on_error Text drawn on error backgrounds

Syntax roles

Role Intended use
syntax.comment Comments, folds, preprocessor text, and quotes
syntax.string Strings and successful or added states
syntax.keyword Keywords, statements, and primary accents
syntax.function_name Functions, methods, modules, and directories
syntax.type Types, classes, attributes, and interfaces
syntax.property Fields, properties, and secondary metadata
syntax.literal Numbers, constants, booleans, and literals
syntax.operator Operators
syntax.punctuation Delimiters and punctuation
syntax.regexp Regular expressions
syntax.special Escapes, special characters, and special syntax
syntax.attribute Tags and attribute names
syntax.tag Markup tags

Diagnostic roles

Role Intended use
diagnostic.error Errors, removals, and failed states
diagnostic.warning Warnings and todo markers
diagnostic.information Information messages and command mode
diagnostic.hint Hints and visual mode
diagnostic.success Success messages and insert mode

Each severity drives its base, virtual text, virtual line, underline, floating, and sign highlight groups.

Markup roles

Role Intended use
markup.heading_1 through markup.heading_6 Heading levels
markup.quote Quoted text
markup.math Mathematical notation
markup.link Link text and URLs
markup.link_label Link labels
markup.raw Inline and block raw content
markup.list List markers
markup.checked Checked task items
markup.unchecked Unchecked task items

Version-control roles

Role Intended use
version_control.added Added content and insert-mode status
version_control.changed Changed content
version_control.removed Removed content
version_control.ignored Ignored or intentionally hidden content
version_control.conflict Merge conflicts and substitutions

UI roles

Role Intended use
ui.accent Primary UI accent and normal-mode status
ui.cursor Cursor background
ui.directory Directory names and navigation targets
ui.search Search matches and completion matches
ui.current_search Current search match
ui.match Parenthesis and incremental-search matches
ui.focus Strong focus indicators

Inspect the resolved palette

local palette = require("neotheme").palette()
print(vim.inspect(palette))

palette() returns a deep copy. It is safe to inspect or mutate, but changes to that returned table do not affect active highlights or Neotheme state.

Reuse roles or provide colors directly

Both approaches are valid:

configure_palette = function(palette)
	palette.ui.search = palette.syntax.keyword
	palette.diagnostic.error = "#ff5f5f"
end

Direct colors must use six-digit #RRGGBB strings.

Validation rules

The configurator must:

  • Mutate the supplied table
  • Return nil
  • Use existing categories and fields only
  • Assign six-digit #RRGGBB strings to supplied fields

Built-in palettes already contain every required role. Removing a value creates a missing-role warning when the palette is resolved.

Use Custom Themes when you want to start from an empty palette instead of modifying a built-in theme.

Clone this wiki locally