diff --git a/apps/dashboard/features/governance/components/proposal-overview/ProposalSection.tsx b/apps/dashboard/features/governance/components/proposal-overview/ProposalSection.tsx
index abf7448d8..e55705f07 100644
--- a/apps/dashboard/features/governance/components/proposal-overview/ProposalSection.tsx
+++ b/apps/dashboard/features/governance/components/proposal-overview/ProposalSection.tsx
@@ -41,7 +41,6 @@ import { HoldersAndDelegatesDrawer } from "@/features/holders-and-delegates";
import { ProposalHeaderProvider } from "@/features/governance/context/ProposalHeaderContext";
import { Button } from "@/shared/components";
import { ConnectWalletCustom } from "@/shared/components/wallet/ConnectWalletCustom";
-import { TelegramBotMessage } from "@/shared/components/messages";
import daoConfig from "@/shared/dao-config";
import { DaoIdEnum } from "@/shared/types/daos";
@@ -276,11 +275,6 @@ export const ProposalSection = ({
proposal={proposal}
isOffchain={isOffchain}
/>
- {!isOffchain && supportValue !== undefined ? (
-
-
-
- ) : null}
= {
const KPI_COUNT = 3;
+const PERCENTAGE_POINTS_TOOLTIP =
+ "Percentage points: the absolute change between two percentages. Going from 30% to 39% is +9pp, not +9%.";
+
export const KpiRow = () => {
const [timePeriod, setTimePeriod] = useState("1y");
@@ -116,23 +119,9 @@ export const KpiRow = () => {
"border-border-default border-b lg:border-b-0 lg:border-r",
)}
>
-
-
- {kpi.title}
-
- {kpi.tooltip && (
-
- {kpi.tooltip}
-
- }
- triggerClassName="inline-flex cursor-help items-center border-0 bg-transparent p-0"
- >
-
-
- )}
-
+
+ {kpi.title}
+
{kpi.value}
@@ -152,7 +141,29 @@ export const KpiRow = () => {
: "text-secondary"
}
>
- {kpi.subtext}
+ {kpi.delta ? (
+ <>
+ {kpi.delta.value}
+ {kpi.delta.unit === "pp" ? (
+
+ {PERCENTAGE_POINTS_TOOLTIP}
+
+ }
+ triggerClassName="cursor-help underline decoration-dotted underline-offset-2"
+ >
+ {kpi.delta.unit}
+
+ ) : (
+ kpi.delta.unit
+ )}{" "}
+ {kpi.delta.comparison}
+ >
+ ) : (
+ kpi.subtext
+ )}
diff --git a/apps/dashboard/features/revenue/types.ts b/apps/dashboard/features/revenue/types.ts
index 97d6349ba..5deb94a0d 100644
--- a/apps/dashboard/features/revenue/types.ts
+++ b/apps/dashboard/features/revenue/types.ts
@@ -22,6 +22,10 @@ export type KpiCard = {
title: string;
value: string;
subtext: string;
+ delta?: {
+ value: string;
+ unit: string;
+ comparison: string;
+ };
trend?: "up" | "down";
- tooltip?: string;
};
diff --git a/apps/dashboard/features/revenue/utils/transform/kpis.ts b/apps/dashboard/features/revenue/utils/transform/kpis.ts
index cd85155f6..07a5d3dcc 100644
--- a/apps/dashboard/features/revenue/utils/transform/kpis.ts
+++ b/apps/dashboard/features/revenue/utils/transform/kpis.ts
@@ -35,7 +35,6 @@ function buildFlowKpi(args: {
/** "pct" for sums, "pp" for averages-of-percentages */
deltaKind: "pct" | "pp";
window: KpiWindow;
- tooltip?: string;
}): KpiCard {
const sinceLabel = buildSinceLabel(args.items);
const { current, previous } = splitIntoWindows(
@@ -55,17 +54,23 @@ function buildFlowKpi(args: {
const presentation =
args.window.months !== null && rawDelta !== null
- ? presentDelta(rawDelta, args.deltaKind === "pct" ? "%" : "pp")
+ ? presentDelta(rawDelta)
: null;
+ const unit = args.deltaKind === "pct" ? "%" : "pp";
+
return {
title: args.title,
value: current.length > 0 ? args.formatValue(currentValue) : "—",
- subtext: presentation
- ? `${presentation.text} vs prev. ${args.window.label}`
- : sinceLabel,
+ subtext: sinceLabel,
+ delta: presentation
+ ? {
+ value: presentation.text,
+ unit,
+ comparison: `vs prev. ${args.window.label}`,
+ }
+ : undefined,
trend: presentation?.trend,
- tooltip: args.tooltip,
};
}
@@ -99,8 +104,6 @@ export function computeKpis(
formatValue: (n) => `${n.toFixed(0)}%`,
deltaKind: "pp",
window,
- tooltip:
- "Share of expiring names that were renewed. 'pp' (percentage points) is the absolute change between two percentages.",
}),
buildFlowKpi({
title: "Revenue",
diff --git a/apps/dashboard/features/revenue/utils/window.ts b/apps/dashboard/features/revenue/utils/window.ts
index e12916d58..cdf2ab446 100644
--- a/apps/dashboard/features/revenue/utils/window.ts
+++ b/apps/dashboard/features/revenue/utils/window.ts
@@ -51,25 +51,15 @@ export type DeltaPresentation = {
trend: "up" | "down" | undefined;
};
-/**
- * Formats a percentage-ish delta with adaptive precision: up to 2 decimals
- * for small magnitudes (<0.1), 1 decimal for [0.1, 1), 0 decimals otherwise.
- * Returns the trend in lockstep with the rendered value — when the value
- * rounds to 0 at the chosen precision, the trend is `undefined` (neutral).
- *
- * The point: a real +0.4% change should display as "+0.4%" with an up arrow,
- * not "+0%" (which would erase the signal) and not "+0%" with an arrow
- * (which would conflict with the rendered value).
- */
-export function presentDelta(value: number, suffix: string): DeltaPresentation {
+export function presentDelta(value: number): DeltaPresentation {
const abs = Math.abs(value);
const precision = abs >= 1 ? 0 : abs >= 0.1 ? 1 : 2;
// Snap to display precision so text and trend can never disagree.
const snapped = Number(value.toFixed(precision));
- if (snapped === 0) return { text: `0${suffix}`, trend: undefined };
+ if (snapped === 0) return { text: "0", trend: undefined };
const prefix = snapped > 0 ? "+" : "";
return {
- text: `${prefix}${snapped.toFixed(precision)}${suffix}`,
+ text: `${prefix}${snapped.toFixed(precision)}`,
trend: snapped > 0 ? "up" : "down",
};
}
diff --git a/apps/dashboard/shared/components/messages/TelegramBotMessage.tsx b/apps/dashboard/shared/components/messages/TelegramBotMessage.tsx
deleted file mode 100644
index d6d648007..000000000
--- a/apps/dashboard/shared/components/messages/TelegramBotMessage.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-"use client";
-
-import { ArrowRight, Send } from "lucide-react";
-import { useParams } from "next/navigation";
-
-import { ANTICAPTURE_TELEGRAM_BOT } from "@/shared/constants/social-media";
-import daoConfigByDaoId from "@/shared/dao-config";
-import type { DaoIdEnum } from "@/shared/types/daos";
-
-export const TelegramBotMessage = () => {
- const { daoId } = useParams() as { daoId: string };
- return (
-
-
-
-
-
- RECEIVE REAL-TIME{" "}
- {daoConfigByDaoId[
- daoId.toUpperCase() as DaoIdEnum
- ].name.toUpperCase()}{" "}
- SECURITY UPDATES.
-
-
-
-
-
- );
-};
diff --git a/apps/dashboard/shared/components/messages/index.ts b/apps/dashboard/shared/components/messages/index.ts
deleted file mode 100644
index c51609159..000000000
--- a/apps/dashboard/shared/components/messages/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "@/shared/components/messages/TelegramBotMessage";
diff --git a/apps/dashboard/widgets/WhitelabelSidebar.tsx b/apps/dashboard/widgets/WhitelabelSidebar.tsx
index f860b2eba..4e4379346 100644
--- a/apps/dashboard/widgets/WhitelabelSidebar.tsx
+++ b/apps/dashboard/widgets/WhitelabelSidebar.tsx
@@ -233,7 +233,7 @@ export const WhitelabelSidebar = ({
rel="noopener noreferrer"
className="text-link"
>
- Blockful
+ blockful
)}