diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-15 02:28:50 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-15 02:28:50 -0500 |
| commit | 739ebe9cf6309e08c2e405d370e95ad63c8282bf (patch) | |
| tree | 13bdf94f6973344796f79dc8fd8bf3074aae8490 /modules/org-faces-config.el | |
| parent | 84ce9fb007ce74666f0a1bbb956df7766f241fc0 (diff) | |
| download | dotemacs-739ebe9cf6309e08c2e405d370e95ad63c8282bf.tar.gz dotemacs-739ebe9cf6309e08c2e405d370e95ad63c8282bf.zip | |
feat(org): themeable agenda header-row faces via org-faces-config
Each TODO keyword and priority cookie gets its own named face instead of sharing org's built-in org-todo / org-done / org-priority. org-faces-config.el defines org-faces-<keyword> and org-faces-priority-a..d (plus -dim variants for auto-dim), each with a real default color, and wires them through org-todo-keyword-faces and org-priority-faces once org loads. The file is org-faces-config, not org-faces, because org ships its own org-faces feature that the bare name would shadow.
This re-introduces the per-keyword/priority coloring that was stripped earlier, now as a named, theme-agnostic layer a theme can override. The design and the four resolved decisions are in docs/design/org-faces-spec.org; a theme-studio "org-faces" app and the auto-dim repoint follow in later phases.
Diffstat (limited to 'modules/org-faces-config.el')
| -rw-r--r-- | modules/org-faces-config.el | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/modules/org-faces-config.el b/modules/org-faces-config.el new file mode 100644 index 000000000..e0dfa83fd --- /dev/null +++ b/modules/org-faces-config.el @@ -0,0 +1,129 @@ +;;; org-faces-config.el --- Custom faces for the org agenda header row -*- lexical-binding: t; coding: utf-8; -*- +;; author Craig Jennings <c@cjennings.net> + +;;; Commentary: +;; +;; Layer: 2 (Core UX). +;; Category: C/S. +;; Load shape: eager. +;; Eager reason: the faces must exist before org renders the agenda. +;; Top-level side effects: defines the org-faces-* faces; sets +;; org-todo-keyword-faces and org-priority-faces once org loads. +;; Runtime requires: none (org wiring is deferred via with-eval-after-load). +;; +;; Custom faces for the agenda "header row" -- the TODO keyword and the +;; priority cookie -- so each keyword and each priority is its own themeable +;; element rather than sharing org's built-in org-todo / org-done / org-priority. +;; They are named org-faces-* (not org-*) so it's obvious they are this config's +;; layer, not built-in org. Each carries a real default color so the agenda is +;; legible on any theme; a theme (e.g. one generated by theme-studio's +;; "org-faces" app) overrides them. The -dim variants are the dimmed colors +;; auto-dim-config.el remaps these to in non-selected windows, so keywords stay +;; recognizable when a window recedes. +;; +;; Note: this file is org-faces-CONFIG, not org-faces -- org ships its own +;; `org-faces' feature (lisp/org/org-faces.el), so reusing that name would +;; shadow org's face definitions on the load path. + +;;; Code: + +(eval-when-compile (require 'org)) + +(defgroup org-faces-config nil + "Custom faces for the org agenda header row (keywords and priorities)." + :group 'org) + +;; --------------------------- Keyword faces (focused) ------------------------- + +(defface org-faces-todo '((t (:foreground "#8fbf73" :weight bold))) + "Face for the TODO keyword." :group 'org-faces-config) +(defface org-faces-project '((t (:foreground "#7a9abe" :weight bold))) + "Face for the PROJECT keyword." :group 'org-faces-config) +(defface org-faces-doing '((t (:foreground "#e8c668" :weight bold))) + "Face for the DOING keyword." :group 'org-faces-config) +(defface org-faces-waiting '((t (:foreground "#c9b08a" :weight bold))) + "Face for the WAITING keyword." :group 'org-faces-config) +(defface org-faces-verify '((t (:foreground "#d98a5a" :weight bold))) + "Face for the VERIFY keyword." :group 'org-faces-config) +(defface org-faces-stalled '((t (:foreground "#9a8fb0" :weight bold))) + "Face for the STALLED keyword." :group 'org-faces-config) +(defface org-faces-delegated '((t (:foreground "#7fc0a8" :weight bold))) + "Face for the DELEGATED keyword." :group 'org-faces-config) +(defface org-faces-failed '((t (:foreground "#d05a5a" :weight bold))) + "Face for the FAILED keyword." :group 'org-faces-config) +(defface org-faces-done '((t (:foreground "#6f7a82" :weight bold))) + "Face for the DONE keyword." :group 'org-faces-config) +(defface org-faces-cancelled '((t (:foreground "#6f7a82" :weight bold :strike-through t))) + "Face for the CANCELLED keyword." :group 'org-faces-config) + +;; -------------------------- Priority faces (focused) ------------------------- + +(defface org-faces-priority-a '((t (:foreground "#7aa0d0" :weight bold))) + "Face for the [#A] priority cookie." :group 'org-faces-config) +(defface org-faces-priority-b '((t (:foreground "#e8c668"))) + "Face for the [#B] priority cookie." :group 'org-faces-config) +(defface org-faces-priority-c '((t (:foreground "#8fbf73"))) + "Face for the [#C] priority cookie." :group 'org-faces-config) +(defface org-faces-priority-d '((t (:foreground "#8a8a8a"))) + "Face for the [#D] priority cookie." :group 'org-faces-config) + +;; ----------------------------- Keyword faces (dim) --------------------------- +;; auto-dim-config.el remaps the focused faces above to these in non-selected +;; windows; a darker shade of the same hue keeps the keyword recognizable. + +(defface org-faces-todo-dim '((t (:foreground "#5f7a4d" :weight bold))) + "Dimmed TODO keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-project-dim '((t (:foreground "#4f6680" :weight bold))) + "Dimmed PROJECT keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-doing-dim '((t (:foreground "#9a8544" :weight bold))) + "Dimmed DOING keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-waiting-dim '((t (:foreground "#87745c" :weight bold))) + "Dimmed WAITING keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-verify-dim '((t (:foreground "#8f5a3c" :weight bold))) + "Dimmed VERIFY keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-stalled-dim '((t (:foreground "#665e75" :weight bold))) + "Dimmed STALLED keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-delegated-dim '((t (:foreground "#547d6c" :weight bold))) + "Dimmed DELEGATED keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-failed-dim '((t (:foreground "#8a3c3c" :weight bold))) + "Dimmed FAILED keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-done-dim '((t (:foreground "#4a5158" :weight bold))) + "Dimmed DONE keyword for non-selected windows." :group 'org-faces-config) +(defface org-faces-cancelled-dim '((t (:foreground "#4a5158" :weight bold :strike-through t))) + "Dimmed CANCELLED keyword for non-selected windows." :group 'org-faces-config) + +;; ---------------------------- Priority faces (dim) --------------------------- + +(defface org-faces-priority-a-dim '((t (:foreground "#4f6a8a" :weight bold))) + "Dimmed [#A] priority cookie for non-selected windows." :group 'org-faces-config) +(defface org-faces-priority-b-dim '((t (:foreground "#9a8544"))) + "Dimmed [#B] priority cookie for non-selected windows." :group 'org-faces-config) +(defface org-faces-priority-c-dim '((t (:foreground "#5f7a4d"))) + "Dimmed [#C] priority cookie for non-selected windows." :group 'org-faces-config) +(defface org-faces-priority-d-dim '((t (:foreground "#5a5a5a"))) + "Dimmed [#D] priority cookie for non-selected windows." :group 'org-faces-config) + +;; ---------------------------------- Wiring ----------------------------------- +;; Map each keyword string and priority char to its face once org is loaded, so +;; the values stick regardless of when org initializes. + +(with-eval-after-load 'org + (setq org-todo-keyword-faces + '(("TODO" . org-faces-todo) + ("PROJECT" . org-faces-project) + ("DOING" . org-faces-doing) + ("WAITING" . org-faces-waiting) + ("VERIFY" . org-faces-verify) + ("STALLED" . org-faces-stalled) + ("DELEGATED" . org-faces-delegated) + ("FAILED" . org-faces-failed) + ("DONE" . org-faces-done) + ("CANCELLED" . org-faces-cancelled))) + (setq org-priority-faces + '((?A . org-faces-priority-a) + (?B . org-faces-priority-b) + (?C . org-faces-priority-c) + (?D . org-faces-priority-d)))) + +(provide 'org-faces-config) +;;; org-faces-config.el ends here |
