From fee8fa5a22408ee6baec2cfff06bb272ae9bea23 Mon Sep 17 00:00:00 2001
From: 2xburnt <169301814+2xburnt@users.noreply.github.com>
Date: Fri, 24 Jul 2026 14:57:16 -0500
Subject: [PATCH 1/6] fix(theme): keep custom daisyUI themes from being
overridden at runtime
@ping-pub/widget bundles its own Tailwind + daisyUI build and injects it into
the document at runtime. That stylesheet re-declares [data-theme=light] and
[data-theme=dark]; because it lands after the app's stylesheet and has equal
specificity (0,1,0), it wins. Any value customised in `daisyui.themes` is
therefore silently discarded in the browser.
It goes unnoticed here because the widget is built from this repo's own theme,
so the two agree. It breaks immediately for anyone re-theming a fork: their
config is correct, the CSS is emitted correctly, and the browser still paints
ping.pub's colours.
Reproduced by setting dark `base-100` to #123456:
before --b1 resolves to 224 29% 23% (the widget's value)
after --b1 resolves to 210 65% 20% (the configured value)
This duplicates each daisyUI theme rule with an `html` prefix, raising it to
(0,1,1). Values are copied verbatim by PostCSS rather than recomputed, so where
the app and widget already agree the output is byte-identical and there is no
visual change. The original rule is kept, so element-level theming
(`
`) still works.
---
postcss.config.js | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/postcss.config.js b/postcss.config.js
index 12a703d900..20965316b4 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,6 +1,31 @@
-module.exports = {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
+// @ping-pub/widget bundles its own Tailwind + daisyUI build and injects it into
+// the document at runtime. That stylesheet re-declares [data-theme=light] and
+// [data-theme=dark], and because it lands after the app's stylesheet it wins on
+// equal specificity - so a project that customises `daisyui.themes` silently
+// gets the widget's values back in the browser.
+//
+// This duplicates each daisyUI theme rule with an `html` prefix, raising it from
+// specificity (0,1,0) to (0,1,1) so the app's own theme wins. Values are copied
+// verbatim, so there is no visual change wherever the two already agree. The
+// original rule is kept, which preserves daisyUI's element-level theming
+// (`
`).
+const raiseThemeSpecificity = () => ({
+ postcssPlugin: 'raise-theme-specificity',
+ OnceExit(root) {
+ const clones = [];
+ root.walkRules((rule) => {
+ if (rule.__themeSpecificityRaised) return;
+ const targets = rule.selectors.filter((s) => /^\[data-theme=/.test(s.trim()));
+ if (!targets.length) return;
+ const clone = rule.clone({ selectors: targets.map((s) => `html${s.trim()}`) });
+ clone.__themeSpecificityRaised = true;
+ clones.push([rule, clone]);
+ });
+ clones.forEach(([rule, clone]) => rule.after(clone));
},
+});
+raiseThemeSpecificity.postcss = true;
+
+module.exports = {
+ plugins: [require('tailwindcss'), raiseThemeSpecificity(), require('autoprefixer')],
};
From daa6fec65de44e4e9a989e79338b314e7631c371 Mon Sep 17 00:00:00 2001
From: 2xburnt <169301814+2xburnt@users.noreply.github.com>
Date: Fri, 24 Jul 2026 15:17:14 -0500
Subject: [PATCH 2/6] refactor(theme): resolve the primary colour through the
theme, not a literal
Four places hardcode #666CFF, which is the same value `daisyui.themes` already
sets as `primary`. Duplicating it means a project that changes primary in the
config still gets #666CFF in these spots.
Routed through the theme instead. CSS contexts use hsl(var(--p)); the SVG cases
go through fill="currentColor" with text-primary, because var() is not
substituted in SVG presentation attributes.
apexChartConfig.ts is deliberately left alone: its value is handed to ApexCharts
as a plain string and written into SVG attributes, where neither var() nor a
Tailwind class would resolve. Making that theme-aware needs a runtime lookup and
belongs in its own change.
Verified against ping.pub in dark mode: sidebar, active nav, nav text and svg
fills are computed-style identical before and after.
---
src/components/dynamic/TextElement.vue | 2 +-
src/modules/[chain]/faucet/index.vue | 2 +-
src/modules/wallet/accounts.vue | 3 ++-
src/pages/index.vue | 4 ++--
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/components/dynamic/TextElement.vue b/src/components/dynamic/TextElement.vue
index d214603026..bb6b6dd553 100644
--- a/src/components/dynamic/TextElement.vue
+++ b/src/components/dynamic/TextElement.vue
@@ -142,7 +142,7 @@ const isConvertable = computed(() => {
margin-bottom: 1rem;
}
a {
- color: #666cff !important;
+ color: hsl(var(--p)) !important;
}
.h1 > a,
.h2 > a,
diff --git a/src/modules/[chain]/faucet/index.vue b/src/modules/[chain]/faucet/index.vue
index 82b8954e1b..f1a453e233 100644
--- a/src/modules/[chain]/faucet/index.vue
+++ b/src/modules/[chain]/faucet/index.vue
@@ -87,7 +87,7 @@ onMounted(() => {
viewBox="0 0 150.000000 132.000000"
preserveAspectRatio="xMidYMid meet"
>
-
+