This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 60db2692bd8 Add support for globalCss to custom theme (#61161)
60db2692bd8 is described below
commit 60db2692bd85bbb37fc82cd323cf4f3cb30b5382
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Thu Jan 29 16:40:11 2026 +0100
Add support for globalCss to custom theme (#61161)
* Add support for globalCss to custom theme
* Fix CI
---
airflow-core/docs/howto/customize-ui.rst | 32 +++++++++++++++++++++-
.../src/airflow/api_fastapi/common/types.py | 1 +
.../api_fastapi/core_api/openapi/_private_ui.yaml | 8 ++++++
.../src/airflow/config_templates/config.yml | 3 +-
.../airflow/ui/openapi-gen/requests/schemas.gen.ts | 15 ++++++++++
.../airflow/ui/openapi-gen/requests/types.gen.ts | 5 ++++
airflow-core/src/airflow/ui/src/theme.ts | 17 ++++++++++--
.../api_fastapi/core_api/routes/ui/test_config.py | 10 ++++++-
docs/spelling_wordlist.txt | 1 +
9 files changed, 87 insertions(+), 5 deletions(-)
diff --git a/airflow-core/docs/howto/customize-ui.rst
b/airflow-core/docs/howto/customize-ui.rst
index 8b93b4b6178..ef330a80517 100644
--- a/airflow-core/docs/howto/customize-ui.rst
+++ b/airflow-core/docs/howto/customize-ui.rst
@@ -70,9 +70,10 @@ We can provide a JSON configuration to customize the UI.
.. important::
- - Currently only the ``brand`` color palette can be customized.
+ - Currently only the ``brand`` color palette and ``globalCss`` can be
customized.
- You must supply ``50``-``950`` OKLCH color values for ``brand`` color.
- OKLCH colors must have next format ``oklch(l c h)`` For more info see
:ref:`config:api__theme`
+ - There is also the ability to provide custom global CSS for a fine grained
theme control.
.. note::
@@ -150,6 +151,35 @@ Dark Mode
.. image:: ../img/change-theme/exmaple_theme_configuration_dark_mode.png
+3. To add custom CSS rules to the airflow UI, you can include a ``globalCss``
key in the theme configuration. More information
https://chakra-ui.com/docs/theming/customization/global-css
+
+.. code-block::
+
+ AIRFLOW__API__THEME='{
+ "tokens": {
+ "colors": {
+ "brand": {
+ "50": { "value": "oklch(0.971 0.013 17.38)" },
+ "100": { "value": "oklch(0.936 0.032 17.717)" },
+ "200": { "value": "oklch(0.885 0.062 18.334)" },
+ "300": { "value": "oklch(0.808 0.114 19.571)" },
+ "400": { "value": "oklch(0.704 0.191 22.216)" },
+ "500": { "value": "oklch(0.637 0.237 25.331)" },
+ "600": { "value": "oklch(0.577 0.245 27.325)" },
+ "700": { "value": "oklch(0.505 0.213 27.518)" },
+ "800": { "value": "oklch(0.444 0.177 26.899)" },
+ "900": { "value": "oklch(0.396 0.141 25.723)" },
+ "950": { "value": "oklch(0.258 0.092 26.042)" }
+ }
+ }
+ },
+ "globalCss": {
+ "button": {
+ "text-transform": "uppercase"
+ }
+ }
+ }'
+
|
Adding Dashboard Alert Messages
diff --git a/airflow-core/src/airflow/api_fastapi/common/types.py
b/airflow-core/src/airflow/api_fastapi/common/types.py
index a09f1c9b383..c19dd632343 100644
--- a/airflow-core/src/airflow/api_fastapi/common/types.py
+++ b/airflow-core/src/airflow/api_fastapi/common/types.py
@@ -178,3 +178,4 @@ class Theme(BaseModel):
],
],
]
+ globalCss: dict[str, dict] | None = None
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
index 503f5f3dc71..7d11ce58776 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
+++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
@@ -2739,6 +2739,14 @@ components:
const: colors
type: object
title: Tokens
+ globalCss:
+ anyOf:
+ - additionalProperties:
+ additionalProperties: true
+ type: object
+ type: object
+ - type: 'null'
+ title: Globalcss
type: object
required:
- tokens
diff --git a/airflow-core/src/airflow/config_templates/config.yml
b/airflow-core/src/airflow/config_templates/config.yml
index 59eb620257d..d4f2bdb54aa 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -1379,9 +1379,10 @@ api:
theme:
description: |
JSON config to customize the Chakra UI theme.
- Currently only supports ``brand`` color customization.
+ Currently only supports ``brand`` color customization and
``globalCss``.
Must supply ``50``-``950`` OKLCH color values for ``brand`` color.
+
For usage see :ref:`customizing-ui-theme`
.. important::
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
index cf35d310853..6012fae8c8c 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts
@@ -8382,6 +8382,21 @@ export const $Theme = {
},
type: 'object',
title: 'Tokens'
+ },
+ globalCss: {
+ anyOf: [
+ {
+ additionalProperties: {
+ additionalProperties: true,
+ type: 'object'
+ },
+ type: 'object'
+ },
+ {
+ type: 'null'
+ }
+ ],
+ title: 'Globalcss'
}
},
type: 'object',
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index 7d679bbff9f..90e75ac0e76 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -2078,6 +2078,11 @@ export type Theme = {
};
};
};
+ globalCss?: {
+ [key: string]: {
+ [key: string]: unknown;
+ };
+} | null;
};
/**
diff --git a/airflow-core/src/airflow/ui/src/theme.ts
b/airflow-core/src/airflow/ui/src/theme.ts
index 3dfe839174c..fc9c07a99b8 100644
--- a/airflow-core/src/airflow/ui/src/theme.ts
+++ b/airflow-core/src/airflow/ui/src/theme.ts
@@ -20,7 +20,13 @@
/* eslint-disable perfectionist/sort-objects */
/* eslint-disable max-lines */
-import { createSystem, defaultConfig, defineConfig, mergeConfigs } from
"@chakra-ui/react";
+import {
+ createSystem,
+ defaultConfig,
+ defineConfig,
+ mergeConfigs,
+ type SystemStyleObject,
+} from "@chakra-ui/react";
import type { CSSProperties } from "react";
import type { Theme } from "openapi/requests/types.gen";
@@ -400,7 +406,14 @@ const defaultAirflowTheme = {
export const createTheme = (userTheme?: Theme) => {
const defaultAirflowConfig = defineConfig({ theme: defaultAirflowTheme });
- const userConfig = defineConfig({ theme: userTheme ?? {} });
+ const userConfig = defineConfig(
+ userTheme
+ ? {
+ theme: { tokens: userTheme.tokens },
+ globalCss: userTheme.globalCss as Record<string, SystemStyleObject>,
+ }
+ : {},
+ );
const mergedConfig = mergeConfigs(defaultConfig, defaultAirflowConfig,
userConfig);
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
index e1b973e9855..6ffe5932fbe 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
@@ -42,7 +42,15 @@ THEME = {
"950": {"value": "oklch(0.179 0.05 265.487)"},
}
}
- }
+ },
+ "globalCss": {
+ "button": {
+ "text-transform": "uppercase",
+ },
+ "a": {
+ "text-transform": "uppercase",
+ },
+ },
}
expected_config_response = {
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
index 7390ccf842c..10886aa879b 100644
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -789,6 +789,7 @@ Gitter
gitter
gke
Glassdoor
+globalCSS
globstring
glyphicon
Gmail