From 61683d8bda0adebc25155da93971ea8b35ef4df9 Mon Sep 17 00:00:00 2001
From: "Abdullah." <125115953+mabdullahabaid@users.noreply.github.com>
Date: Thu, 14 May 2026 12:48:14 +0500
Subject: [PATCH] [Website] Replace product page hero visual with interactive
CRM depicting AI chat in action. (#20566)
Before:
After:
https://github.com/user-attachments/assets/c019586f-ef9f-4ae0-8afe-14f08e8cb057
---
.../shared/people/avatars/sam-altman.webp | Bin 0 -> 7572 bytes
.../src/app/[locale]/product/page.tsx | 7 +-
.../src/content/site/asset-paths.ts | 1 +
.../src/sections/Feature/visuals/BarChart.tsx | 202 ++++++--
.../Feature/visuals/DashboardVisual.tsx | 159 +++++-
.../sections/Feature/visuals/DonutChart.tsx | 2 +-
.../Feature/visuals/dashboard-visual.data.ts | 24 +-
.../Hero/components/ProductVisual.tsx | 11 -
.../ProductVisual/ProductVisual.tsx | 469 ++++++++++++++++++
.../ProductVisual/product-visual.data.tsx | 127 +++++
.../use-product-visual-autoplay.ts | 118 +++++
.../src/sections/Hero/components/index.ts | 2 +-
12 files changed, 1034 insertions(+), 88 deletions(-)
create mode 100644 packages/twenty-website-new/public/images/shared/people/avatars/sam-altman.webp
delete mode 100644 packages/twenty-website-new/src/sections/Hero/components/ProductVisual.tsx
create mode 100644 packages/twenty-website-new/src/sections/Hero/components/ProductVisual/ProductVisual.tsx
create mode 100644 packages/twenty-website-new/src/sections/Hero/components/ProductVisual/product-visual.data.tsx
create mode 100644 packages/twenty-website-new/src/sections/Hero/components/ProductVisual/use-product-visual-autoplay.ts
diff --git a/packages/twenty-website-new/public/images/shared/people/avatars/sam-altman.webp b/packages/twenty-website-new/public/images/shared/people/avatars/sam-altman.webp
new file mode 100644
index 0000000000000000000000000000000000000000..01e10dde700bbeaf336c66c7063f80c6acf310a4
GIT binary patch
literal 7572
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
literal 0
HcmV?d00001
diff --git a/packages/twenty-website-new/src/app/[locale]/product/page.tsx b/packages/twenty-website-new/src/app/[locale]/product/page.tsx
index 2eb2d22a5fa..fb53bd5e9d3 100644
--- a/packages/twenty-website-new/src/app/[locale]/product/page.tsx
+++ b/packages/twenty-website-new/src/app/[locale]/product/page.tsx
@@ -98,11 +98,6 @@ export default async function ProductPage({ params }: ProductPageProps) {
i18n.locale as AppLocale,
)}
/>
-
-
+
(null);
- const rawMax = Math.max(...data.map((datum) => datum.value));
- const maxValue = rawMax * 1.3;
+ const allValues = data.flatMap((datum) => [datum.value, datum.value2]);
+ const maxValue = Math.max(...allValues) * 1.05;
+ const tickStep = Math.ceil(maxValue / Y_TICK_COUNT);
+ const yTicks = Array.from(
+ { length: Y_TICK_COUNT + 1 },
+ (_, i) => i * tickStep,
+ );
return (
- Monthly volume
-
- {data.map((datum, index) => {
- const heightPercent = (datum.value / maxValue) * 100;
- const isHovered = hoveredIndex === index;
+ Widget name
+
+
+ Values
+
+ {[...yTicks].reverse().map((tick) => (
+ {tick === 0 ? '0' : `${tick}K`}
+ ))}
+
+
+
+ {data.map((datum, index) => {
+ const h1 = (datum.value / maxValue) * 100;
+ const h2 = (datum.value2 / maxValue) * 100;
+ const isHovered = hoveredIndex === index;
- return (
-
- {active ? (
-
- {datum.value}
-
- ) : null}
- setHoveredIndex(index)}
- onPointerLeave={() => setHoveredIndex(null)}
- style={{
- backgroundColor: ACCENT,
- filter: isHovered ? 'brightness(1.3)' : 'none',
- height: active ? `${heightPercent}%` : '0%',
- transitionDelay: active ? `${index * 50}ms` : '0ms',
- }}
- />
- {datum.label}
-
- );
- })}
-
+ return (
+ setHoveredIndex(index)}
+ onPointerLeave={() => setHoveredIndex(null)}
+ >
+
+
+ {active ? (
+
+ {datum.value}
+
+ ) : null}
+
+
+
+ {active ? (
+
+ {datum.value2}
+
+ ) : null}
+
+
+
+ {datum.label}
+
+ );
+ })}
+
+ Months
+
+
+
);
}
diff --git a/packages/twenty-website-new/src/sections/Feature/visuals/DashboardVisual.tsx b/packages/twenty-website-new/src/sections/Feature/visuals/DashboardVisual.tsx
index bd9c40cae3a..f04866141b8 100644
--- a/packages/twenty-website-new/src/sections/Feature/visuals/DashboardVisual.tsx
+++ b/packages/twenty-website-new/src/sections/Feature/visuals/DashboardVisual.tsx
@@ -5,20 +5,109 @@ import { styled } from '@linaria/react';
import { BarChart } from './BarChart';
import { BAR_DATA, DONUT_VALUE } from './dashboard-visual.data';
import { DonutChart } from './DonutChart';
-import { WindowChrome } from './WindowChrome';
+import {
+ BG_DARK,
+ BG_PANEL,
+ BORDER_COLOR,
+ TEXT_MUTED,
+ TEXT_PRIMARY,
+ TEXT_SECONDARY,
+} from './visual-tokens';
+
+const Window = styled.div`
+ background-color: ${BG_DARK};
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ overflow: hidden;
+ width: 100%;
+`;
+
+const Topbar = styled.div`
+ align-items: center;
+ border-bottom: 1px solid ${BORDER_COLOR};
+ display: flex;
+ flex-shrink: 0;
+ gap: 8px;
+ padding: 10px 16px;
+`;
+
+const BreadcrumbNav = styled.div`
+ align-items: center;
+ display: flex;
+ gap: 6px;
+`;
+
+const BreadcrumbIcon = styled.span`
+ align-items: center;
+ color: ${TEXT_SECONDARY};
+ display: flex;
+`;
+
+const BreadcrumbText = styled.span`
+ color: ${TEXT_SECONDARY};
+ font-size: 12px;
+ letter-spacing: 0.01em;
+`;
+
+const BreadcrumbBold = styled.span`
+ color: ${TEXT_PRIMARY};
+ font-size: 12px;
+ font-weight: 600;
+ letter-spacing: 0.01em;
+`;
+
+const TopbarActions = styled.div`
+ align-items: center;
+ display: flex;
+ gap: 8px;
+ margin-left: auto;
+`;
+
+const ActionBtn = styled.span`
+ align-items: center;
+ border: 1px solid ${BORDER_COLOR};
+ border-radius: 4px;
+ color: ${TEXT_SECONDARY};
+ display: flex;
+ font-size: 11px;
+ gap: 4px;
+ padding: 4px 8px;
+`;
+
+const ActionIcon = styled.span`
+ color: ${TEXT_MUTED};
+ display: flex;
+`;
const Body = styled.div`
display: grid;
flex: 1;
gap: 12px;
grid-template-columns: 200px 1fr;
+ grid-template-rows: 1fr 60px;
min-height: 0;
padding: 14px;
+`;
- @media (max-width: 600px) {
- grid-template-columns: 1fr;
- grid-template-rows: auto 1fr;
- }
+const BarChartCell = styled.div`
+ grid-column: 2;
+ grid-row: 1 / -1;
+ min-height: 0;
+`;
+
+const BottomPanel = styled.div`
+ background-color: ${BG_PANEL};
+ border: 1px solid ${BORDER_COLOR};
+ border-radius: 10px;
+ padding: 14px 16px;
+`;
+
+const WidgetTitle = styled.span`
+ color: ${TEXT_SECONDARY};
+ font-size: 12px;
+ font-weight: 500;
+ letter-spacing: 0.02em;
`;
type DashboardVisualProps = {
@@ -27,15 +116,61 @@ type DashboardVisualProps = {
export function DashboardVisual({ active }: DashboardVisualProps) {
return (
-
+
+
+
+
+
+
+ Dashboard /
+ Sales performances
+
+
+
+
+ Delete
+
+
+
+
+ ⌘K
+
+
-
+
+
+
+
+ Widget name
+
-
+
);
}
diff --git a/packages/twenty-website-new/src/sections/Feature/visuals/DonutChart.tsx b/packages/twenty-website-new/src/sections/Feature/visuals/DonutChart.tsx
index 8fda9580ae6..7b42a0ef214 100644
--- a/packages/twenty-website-new/src/sections/Feature/visuals/DonutChart.tsx
+++ b/packages/twenty-website-new/src/sections/Feature/visuals/DonutChart.tsx
@@ -92,7 +92,7 @@ export function DonutChart({ active, value }: DonutChartProps) {
return (
- Conversion rate
+ Widget name
|