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" > - +
Date: Fri, 24 Jul 2026 15:33:31 -0500 Subject: [PATCH 3/6] fix(theme): let the configured primary apply when a chain sets no theme_color computedChainMenu writes --p inline on . When the current chain defines a theme_color that is the intended per-chain accent, but the else branch set a hardcoded '237.65 100% 70%' - a duplicate of the `primary` already in daisyui.themes. An inline style beats any stylesheet, so on every chain without its own theme_color the configured primary never applied. Found while writing the theming docs: changing `primary` in tailwind.config.js re-themed base-100 but left buttons and the active nav on #666cff. The fallback now clears the inline value so the theme's primary applies. Chains that do set theme_color are unaffected and still override it. cosmos (no theme_color) before #666cff regardless of config after follows daisyui.themes osmosis (has theme_color) rgb(130, 46, 214) before and after One caveat: the fallback now resolves via daisyUI's hex -> HSL conversion, which round-trips #666cff to rgb(102, 107, 255) rather than rgb(102, 108, 255). A one-unit difference in the green channel - imperceptible, but not byte-identical. --- src/stores/useBlockchain.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/stores/useBlockchain.ts b/src/stores/useBlockchain.ts index d1421e8a38..22a3e5ad80 100644 --- a/src/stores/useBlockchain.ts +++ b/src/stores/useBlockchain.ts @@ -63,7 +63,10 @@ export const useBlockchain = defineStore('blockchain', { document.body.style.setProperty('--p', `${themeColor}`); // document.body.style.setProperty('--p', `${this.current?.themeColor}`); } else { - document.body.style.setProperty('--p', '237.65 100% 70%'); + // Fall back to the theme's primary rather than a duplicate of it. Setting + // it inline here beat `daisyui.themes`, so a configured primary never + // applied on any chain without its own theme_color. + document.body.style.removeProperty('--p'); } currNavItem = [ { From 80fc1f2e4332e97a99f46bcd3d2da33169288ee9 Mon Sep 17 00:00:00 2001 From: 2xburnt <169301814+2xburnt@users.noreply.github.com> Date: Fri, 24 Jul 2026 15:33:31 -0500 Subject: [PATCH 4/6] docs: how to change the theme There was no documentation for re-theming, which made the supported path hard to find - the daisyUI themes in tailwind.config.js. Adds a Theming section to installation.md with a worked example, a table of the tokens most people will reach for, and two caveats worth knowing: components that still hardcode a colour will not follow the theme, and the widget's injected stylesheet needs the postcss plugin to be outranked. The example in the docs was applied and verified end to end rather than written from memory; doing so is what surfaced the inline --p override fixed in the previous commit. --- installation.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/installation.md b/installation.md index 0ffb3c5cf3..ee50d0529f 100644 --- a/installation.md +++ b/installation.md @@ -80,3 +80,54 @@ server { } ``` 3. config your blockchain in [./chains/mainnet]() + +# Theming + +Colours live in the daisyUI themes in `tailwind.config.js`. Editing them re-themes +the app; no component changes are needed. + +```js +// tailwind.config.js +daisyui: { + themes: [ + { + light: { + ...require('daisyui/src/theming/themes')['[data-theme=light]'], + primary: '#0f766e', + }, + }, + { + dark: { + ...require('daisyui/src/theming/themes')['[data-theme=dark]'], + primary: '#2dd4bf', + 'base-100': '#0b1220', // cards, sidebar, header + 'base-200': '#111a2e', // page bands, table headers + }, + }, + ], +}, +``` + +Spreading the stock theme first means you only list what you want to change. + +The tokens you will reach for most: + +| token | used for | +| --- | --- | +| `primary` | active nav, buttons, links, chart accent | +| `base-100` | cards, sidebar, header | +| `base-200` / `base-300` | page bands, table headers, hover | +| `base-content` | default text colour | +| `info` `success` `warning` `error` | status text, badges, vote bars | + +Full list: https://daisyui.com/docs/colors/ + +Tailwind reads the config at startup, so restart the dev server after editing. + +Two caveats: + +- A component that hardcodes a colour (`text-gray-400`, `bg-green-500`, ...) will + not follow the theme. Those are gradually being moved onto tokens. +- `@ping-pub/widget` injects its own daisyUI build at runtime, which would + otherwise override these values. `postcss.config.js` re-emits the theme at a + higher specificity so the app's config wins - keep that plugin if you fork. From 4e7a6df2aafea09da1f49b4784784dfc2c8b2db1 Mon Sep 17 00:00:00 2001 From: 2xburnt <169301814+2xburnt@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:15:57 -0500 Subject: [PATCH 5/6] fix(theme): stop inverting the home branding in dark mode The previous commit made the home logo's fill theme-driven (`currentColor` + `text-primary`) but left the pre-existing `dark:invert` in place. A CSS filter does not care where the colour came from, so in dark mode a deployer's configured primary is painted as its complement - with `primary: '#2dd4bf'` the logo renders red - which defeats the customisation this PR documents. Thanks @chatgpt-codex-connector for catching it. The adjacent `

` is included even though this PR did not introduce it: the two are siblings in the same hero lockup and carry the same `text-primary dark:invert`, so removing the inversion from only the logo would leave the mark and the wordmark in complementary colours next to each other. Verified with the reviewer's example value: both now compute rgb(43, 212, 189) with `filter: none`, matching the configured #2dd4bf, where before the filter painted them rgb(212, 43, 66). Note this leaves ~30 other `text-primary dark:invert` pairs elsewhere in the codebase untouched. They predate this PR and have the same conflict with a customised theme, but they are outside the branding this change concerns. --- src/pages/index.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/index.vue b/src/pages/index.vue index 326c2178ba..a9cf1bdbcb 100644 --- a/src/pages/index.vue +++ b/src/pages/index.vue @@ -49,7 +49,7 @@ const chainStore = useBlockchain();

-

+

{{ $t('pages.title') }}

From 5c96a0009ee03a0429c3d91e03f9c8381638c64f Mon Sep 17 00:00:00 2001 From: 2xburnt <169301814+2xburnt@users.noreply.github.com> Date: Sat, 25 Jul 2026 12:09:40 -0500 Subject: [PATCH 6/6] fix(theme): preserve primary color in dark mode --- src/components/dynamic/TxsElement.vue | 2 +- src/modules/[chain]/account/[address].vue | 16 ++++++++-------- .../[chain]/cosmwasm/[code_id]/transactions.vue | 2 +- src/modules/[chain]/cosmwasm/index.vue | 2 +- .../[chain]/ibc/connection/[connection_id].vue | 2 +- src/modules/[chain]/staking/index.vue | 2 +- src/modules/[chain]/tx/[hash].vue | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/dynamic/TxsElement.vue b/src/components/dynamic/TxsElement.vue index fa38232eb2..19fdd14061 100644 --- a/src/components/dynamic/TxsElement.vue +++ b/src/components/dynamic/TxsElement.vue @@ -47,7 +47,7 @@ const chain = useBlockchain(); {{ item.injected }} {{ item.hash }} - {{ + {{ item.hash }} diff --git a/src/modules/[chain]/account/[address].vue b/src/modules/[chain]/account/[address].vue index e8c7bc597d..514da598a6 100644 --- a/src/modules/[chain]/account/[address].vue +++ b/src/modules/[chain]/account/[address].vue @@ -185,7 +185,7 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str {{ format.calculatePercent(format.tokenAmountNumber(balanceItem), totalAmount) }}
-
+
${{ format.tokenValue(balanceItem) }}
@@ -204,7 +204,7 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str {{ format.calculatePercent(format.tokenAmountNumber(delegationItem?.balance), totalAmount) }}
-
+
${{ format.tokenValue(delegationItem?.balance) }}
@@ -223,7 +223,7 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str {{ format.calculatePercent(format.tokenAmountNumber(rewardItem), totalAmount) }}
-
+
${{ format.tokenValue(rewardItem) }} @@ -256,7 +256,7 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str }}
-
+
${{ format.tokenValue({ @@ -450,14 +450,14 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str {{ v.height }} {{ v.txhash }} @@ -502,14 +502,14 @@ function mapAmount(events: { type: string; attributes: { key: string; value: str {{ v.height }} {{ v.txhash }} diff --git a/src/modules/[chain]/cosmwasm/[code_id]/transactions.vue b/src/modules/[chain]/cosmwasm/[code_id]/transactions.vue index 3d8631409b..3c663abf68 100644 --- a/src/modules/[chain]/cosmwasm/[code_id]/transactions.vue +++ b/src/modules/[chain]/cosmwasm/[code_id]/transactions.vue @@ -265,7 +265,7 @@ const tab = ref('detail'); {{ resp.height }} -
+
{{ resp.txhash }}
diff --git a/src/modules/[chain]/cosmwasm/index.vue b/src/modules/[chain]/cosmwasm/index.vue index a1dc246f63..566a0daa4f 100644 --- a/src/modules/[chain]/cosmwasm/index.vue +++ b/src/modules/[chain]/cosmwasm/index.vue @@ -76,7 +76,7 @@ function gotoHistory() { {{ v.data_hash }} diff --git a/src/modules/[chain]/ibc/connection/[connection_id].vue b/src/modules/[chain]/ibc/connection/[connection_id].vue index 042fb920e4..40678aeb01 100644 --- a/src/modules/[chain]/ibc/connection/[connection_id].vue +++ b/src/modules/[chain]/ibc/connection/[connection_id].vue @@ -338,7 +338,7 @@ function color(v: string) { {{ resp.height }} -
+
{{ resp.txhash }}
- + {{ tx.tx_response.height }}