refactor(frontend): move stylings out of logic into centralized file
This commit is contained in:
42
frontend/src/styles/stats/appLayout.ts
Normal file
42
frontend/src/styles/stats/appLayout.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const appLayoutStyles: StyleMap = {
|
||||
appHeaderWrap: {
|
||||
padding: "16px 24px 0",
|
||||
},
|
||||
|
||||
appHeaderBrandRow: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 10,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
|
||||
appTitle: {
|
||||
margin: 0,
|
||||
color: palette.textPrimary,
|
||||
fontSize: 18,
|
||||
fontWeight: 600,
|
||||
},
|
||||
|
||||
authStatusBadge: {
|
||||
padding: "3px 8px",
|
||||
borderRadius: 6,
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
fontFamily: '"IBM Plex Sans", "Noto Sans", "Liberation Sans", "Segoe UI", sans-serif',
|
||||
},
|
||||
|
||||
authStatusSignedIn: {
|
||||
border: `1px solid ${palette.statusPositiveBorder}`,
|
||||
background: palette.statusPositiveBg,
|
||||
color: palette.statusPositiveText,
|
||||
},
|
||||
|
||||
authStatusSignedOut: {
|
||||
border: `1px solid ${palette.statusNegativeBorder}`,
|
||||
background: palette.statusNegativeBg,
|
||||
color: palette.statusNegativeText,
|
||||
},
|
||||
};
|
||||
92
frontend/src/styles/stats/auth.ts
Normal file
92
frontend/src/styles/stats/auth.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const authStyles: StyleMap = {
|
||||
containerAuth: {
|
||||
maxWidth: 560,
|
||||
margin: "0 auto",
|
||||
padding: "48px 24px",
|
||||
},
|
||||
|
||||
headingXl: {
|
||||
margin: 0,
|
||||
color: palette.textPrimary,
|
||||
fontSize: 28,
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.1,
|
||||
},
|
||||
|
||||
headingBlock: {
|
||||
marginBottom: 22,
|
||||
textAlign: "center",
|
||||
},
|
||||
|
||||
mutedText: {
|
||||
margin: "8px 0 0",
|
||||
color: palette.textSecondary,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
authCard: {
|
||||
padding: 28,
|
||||
},
|
||||
|
||||
authForm: {
|
||||
display: "grid",
|
||||
gap: 12,
|
||||
maxWidth: 380,
|
||||
margin: "0 auto",
|
||||
},
|
||||
|
||||
inputFullWidth: {
|
||||
width: "100%",
|
||||
maxWidth: "100%",
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
|
||||
authControl: {
|
||||
width: "100%",
|
||||
maxWidth: "100%",
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
|
||||
authErrorText: {
|
||||
color: palette.dangerText,
|
||||
margin: "12px auto 0",
|
||||
fontSize: 14,
|
||||
maxWidth: 380,
|
||||
textAlign: "center",
|
||||
},
|
||||
|
||||
authInfoText: {
|
||||
color: palette.successText,
|
||||
margin: "12px auto 0",
|
||||
fontSize: 14,
|
||||
maxWidth: 380,
|
||||
textAlign: "center",
|
||||
},
|
||||
|
||||
authSwitchRow: {
|
||||
marginTop: 16,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
gap: 8,
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
|
||||
authSwitchLabel: {
|
||||
color: palette.textSecondary,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
authSwitchButton: {
|
||||
border: "none",
|
||||
background: "transparent",
|
||||
color: palette.brandGreenBorder,
|
||||
fontSize: 14,
|
||||
fontWeight: 600,
|
||||
cursor: "pointer",
|
||||
padding: 0,
|
||||
},
|
||||
};
|
||||
42
frontend/src/styles/stats/cards.ts
Normal file
42
frontend/src/styles/stats/cards.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const cardStyles: StyleMap = {
|
||||
cardBase: {
|
||||
background: palette.surface,
|
||||
border: `1px solid ${palette.borderDefault}`,
|
||||
borderRadius: 8,
|
||||
padding: 14,
|
||||
boxShadow: `0 1px 0 ${palette.shadowSubtle}`,
|
||||
minHeight: 88,
|
||||
},
|
||||
|
||||
cardTopRow: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
cardLabel: {
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: palette.textSecondary,
|
||||
letterSpacing: "0.02em",
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
|
||||
cardValue: {
|
||||
fontSize: 24,
|
||||
fontWeight: 700,
|
||||
marginTop: 6,
|
||||
letterSpacing: "-0.02em",
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
cardSubLabel: {
|
||||
marginTop: 6,
|
||||
fontSize: 12,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
};
|
||||
55
frontend/src/styles/stats/datasets.ts
Normal file
55
frontend/src/styles/stats/datasets.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const datasetStyles: StyleMap = {
|
||||
sectionHeaderTitle: {
|
||||
margin: 0,
|
||||
color: palette.textPrimary,
|
||||
fontSize: 28,
|
||||
fontWeight: 600,
|
||||
},
|
||||
|
||||
sectionHeaderSubtitle: {
|
||||
margin: "8px 0 0",
|
||||
color: palette.textSecondary,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
listNoBullets: {
|
||||
listStyle: "none",
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
},
|
||||
|
||||
datasetListItem: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: 12,
|
||||
padding: "14px 16px",
|
||||
borderBottom: `1px solid ${palette.borderMuted}`,
|
||||
},
|
||||
|
||||
datasetName: {
|
||||
fontWeight: 600,
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
datasetMeta: {
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
marginTop: 4,
|
||||
},
|
||||
|
||||
datasetMetaSecondary: {
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
marginTop: 2,
|
||||
},
|
||||
|
||||
subtleBodyText: {
|
||||
margin: "10px 0 0",
|
||||
fontSize: 13,
|
||||
color: palette.textBody,
|
||||
},
|
||||
};
|
||||
51
frontend/src/styles/stats/emotional.ts
Normal file
51
frontend/src/styles/stats/emotional.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const emotionalStyles: StyleMap = {
|
||||
emotionalSummaryRow: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: 10,
|
||||
fontSize: 13,
|
||||
color: palette.textTertiary,
|
||||
marginTop: 6,
|
||||
},
|
||||
|
||||
emotionalTopicLabel: {
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: palette.textSecondary,
|
||||
letterSpacing: "0.02em",
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
|
||||
emotionalTopicValue: {
|
||||
fontSize: 24,
|
||||
fontWeight: 800,
|
||||
marginTop: 4,
|
||||
lineHeight: 1.2,
|
||||
},
|
||||
|
||||
emotionalMetricRow: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 10,
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
emotionalMetricRowCompact: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginTop: 4,
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
emotionalMetricValue: {
|
||||
fontWeight: 600,
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
};
|
||||
34
frontend/src/styles/stats/feedback.ts
Normal file
34
frontend/src/styles/stats/feedback.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const feedbackStyles: StyleMap = {
|
||||
alertCardError: {
|
||||
borderColor: palette.alertErrorBorder,
|
||||
background: palette.alertErrorBg,
|
||||
color: palette.alertErrorText,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
alertCardInfo: {
|
||||
borderColor: palette.alertInfoBorder,
|
||||
background: palette.surface,
|
||||
color: palette.textBody,
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
statusMessageCard: {
|
||||
marginTop: 12,
|
||||
boxShadow: "none",
|
||||
},
|
||||
|
||||
dashboardMeta: {
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
tabsRow: {
|
||||
display: "flex",
|
||||
gap: 8,
|
||||
marginTop: 12,
|
||||
},
|
||||
};
|
||||
157
frontend/src/styles/stats/foundations.ts
Normal file
157
frontend/src/styles/stats/foundations.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const foundationStyles: StyleMap = {
|
||||
appShell: {
|
||||
minHeight: "100vh",
|
||||
background: palette.canvas,
|
||||
fontFamily: '"IBM Plex Sans", "Noto Sans", "Liberation Sans", "Segoe UI", sans-serif',
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
page: {
|
||||
width: "100%",
|
||||
minHeight: "100vh",
|
||||
padding: 20,
|
||||
background: palette.canvas,
|
||||
fontFamily: '"IBM Plex Sans", "Noto Sans", "Liberation Sans", "Segoe UI", sans-serif',
|
||||
color: palette.textPrimary,
|
||||
overflowX: "hidden",
|
||||
boxSizing: "border-box",
|
||||
},
|
||||
|
||||
container: {
|
||||
maxWidth: 1240,
|
||||
margin: "0 auto",
|
||||
},
|
||||
|
||||
containerWide: {
|
||||
maxWidth: 1100,
|
||||
margin: "0 auto",
|
||||
},
|
||||
|
||||
containerNarrow: {
|
||||
maxWidth: 720,
|
||||
margin: "0 auto",
|
||||
},
|
||||
|
||||
card: {
|
||||
background: palette.surface,
|
||||
borderRadius: 8,
|
||||
padding: 16,
|
||||
border: `1px solid ${palette.borderDefault}`,
|
||||
boxShadow: `0 1px 0 ${palette.shadowSubtle}`,
|
||||
},
|
||||
|
||||
headerBar: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
controls: {
|
||||
display: "flex",
|
||||
gap: 8,
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
controlsWrapped: {
|
||||
display: "flex",
|
||||
gap: 8,
|
||||
alignItems: "center",
|
||||
flexWrap: "wrap",
|
||||
},
|
||||
|
||||
input: {
|
||||
width: 280,
|
||||
maxWidth: "70vw",
|
||||
padding: "8px 10px",
|
||||
borderRadius: 6,
|
||||
border: `1px solid ${palette.borderDefault}`,
|
||||
outline: "none",
|
||||
fontSize: 14,
|
||||
background: palette.surface,
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
buttonPrimary: {
|
||||
padding: "8px 12px",
|
||||
borderRadius: 6,
|
||||
border: `1px solid ${palette.brandGreenBorder}`,
|
||||
background: palette.brandGreen,
|
||||
color: palette.surface,
|
||||
fontWeight: 600,
|
||||
cursor: "pointer",
|
||||
boxShadow: "none",
|
||||
},
|
||||
|
||||
buttonSecondary: {
|
||||
padding: "8px 12px",
|
||||
borderRadius: 6,
|
||||
border: `1px solid ${palette.borderDefault}`,
|
||||
background: palette.canvas,
|
||||
color: palette.textPrimary,
|
||||
fontWeight: 600,
|
||||
cursor: "pointer",
|
||||
},
|
||||
|
||||
grid: {
|
||||
marginTop: 12,
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(12, 1fr)",
|
||||
gap: 12,
|
||||
},
|
||||
|
||||
sectionTitle: {
|
||||
margin: 0,
|
||||
fontSize: 17,
|
||||
fontWeight: 600,
|
||||
},
|
||||
|
||||
sectionSubtitle: {
|
||||
margin: "6px 0 14px",
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
chartWrapper: {
|
||||
width: "100%",
|
||||
height: 350,
|
||||
},
|
||||
|
||||
heatmapWrapper: {
|
||||
width: "100%",
|
||||
height: 320,
|
||||
},
|
||||
|
||||
topUsersList: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
topUserItem: {
|
||||
padding: "10px 12px",
|
||||
borderRadius: 8,
|
||||
background: palette.canvas,
|
||||
border: `1px solid ${palette.borderMuted}`,
|
||||
},
|
||||
|
||||
topUserName: {
|
||||
fontWeight: 600,
|
||||
fontSize: 14,
|
||||
color: palette.textPrimary,
|
||||
},
|
||||
|
||||
topUserMeta: {
|
||||
fontSize: 13,
|
||||
color: palette.textSecondary,
|
||||
},
|
||||
|
||||
scrollArea: {
|
||||
maxHeight: 420,
|
||||
overflowY: "auto",
|
||||
},
|
||||
};
|
||||
28
frontend/src/styles/stats/modal.ts
Normal file
28
frontend/src/styles/stats/modal.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { palette } from "./palette";
|
||||
import type { StyleMap } from "./types";
|
||||
|
||||
export const modalStyles: StyleMap = {
|
||||
modalRoot: {
|
||||
position: "relative",
|
||||
zIndex: 50,
|
||||
},
|
||||
|
||||
modalBackdrop: {
|
||||
position: "fixed",
|
||||
inset: 0,
|
||||
background: palette.modalBackdrop,
|
||||
},
|
||||
|
||||
modalContainer: {
|
||||
position: "fixed",
|
||||
inset: 0,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: 16,
|
||||
},
|
||||
|
||||
modalPanel: {
|
||||
width: "min(520px, 95vw)",
|
||||
},
|
||||
};
|
||||
26
frontend/src/styles/stats/palette.ts
Normal file
26
frontend/src/styles/stats/palette.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export const palette = {
|
||||
canvas: "#f6f8fa",
|
||||
surface: "#ffffff",
|
||||
textPrimary: "#24292f",
|
||||
textSecondary: "#57606a",
|
||||
textTertiary: "#4b5563",
|
||||
textBody: "#374151",
|
||||
borderDefault: "#d0d7de",
|
||||
borderMuted: "#d8dee4",
|
||||
shadowSubtle: "rgba(27, 31, 36, 0.04)",
|
||||
brandGreen: "#2da44e",
|
||||
brandGreenBorder: "#1f883d",
|
||||
statusPositiveBorder: "#b7dfc8",
|
||||
statusPositiveBg: "#edf9f1",
|
||||
statusPositiveText: "#1f6f43",
|
||||
statusNegativeBorder: "#f3c1c1",
|
||||
statusNegativeBg: "#fff2f2",
|
||||
statusNegativeText: "#9a2929",
|
||||
dangerText: "#b91c1c",
|
||||
successText: "#166534",
|
||||
alertErrorBorder: "rgba(185, 28, 28, 0.28)",
|
||||
alertErrorBg: "#fff5f5",
|
||||
alertErrorText: "#991b1b",
|
||||
alertInfoBorder: "rgba(0,0,0,0.06)",
|
||||
modalBackdrop: "rgba(0,0,0,0.45)",
|
||||
} as const;
|
||||
3
frontend/src/styles/stats/types.ts
Normal file
3
frontend/src/styles/stats/types.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import type { CSSProperties } from "react";
|
||||
|
||||
export type StyleMap = Record<string, CSSProperties>;
|
||||
@@ -1,136 +1,22 @@
|
||||
import type { CSSProperties } from "react";
|
||||
import { appLayoutStyles } from "./stats/appLayout";
|
||||
import { authStyles } from "./stats/auth";
|
||||
import { cardStyles } from "./stats/cards";
|
||||
import { datasetStyles } from "./stats/datasets";
|
||||
import { emotionalStyles } from "./stats/emotional";
|
||||
import { feedbackStyles } from "./stats/feedback";
|
||||
import { foundationStyles } from "./stats/foundations";
|
||||
import { modalStyles } from "./stats/modal";
|
||||
|
||||
const StatsStyling: Record<string, CSSProperties> = {
|
||||
page: {
|
||||
width: "100%",
|
||||
minHeight: "100vh",
|
||||
padding: 24,
|
||||
background: "#f6f7fb",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Inter, Arial, sans-serif',
|
||||
color: "#111827",
|
||||
overflowX: "hidden",
|
||||
boxSizing: "border-box"
|
||||
},
|
||||
|
||||
|
||||
container: {
|
||||
maxWidth: 1400,
|
||||
margin: "0 auto",
|
||||
},
|
||||
|
||||
card: {
|
||||
background: "white",
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
border: "1px solid rgba(0,0,0,0.06)",
|
||||
boxShadow: "0 6px 20px rgba(0,0,0,0.06)",
|
||||
},
|
||||
|
||||
headerBar: {
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: 12,
|
||||
},
|
||||
|
||||
controls: {
|
||||
display: "flex",
|
||||
gap: 10,
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
input: {
|
||||
width: 320,
|
||||
maxWidth: "70vw",
|
||||
padding: "10px 12px",
|
||||
borderRadius: 12,
|
||||
border: "1px solid rgba(0,0,0,0.12)",
|
||||
outline: "none",
|
||||
fontSize: 14,
|
||||
background: "#fff",
|
||||
color: "black"
|
||||
},
|
||||
|
||||
buttonPrimary: {
|
||||
padding: "10px 14px",
|
||||
borderRadius: 12,
|
||||
border: "1px solid rgba(0,0,0,0.08)",
|
||||
background: "#2563eb",
|
||||
color: "white",
|
||||
fontWeight: 600,
|
||||
cursor: "pointer",
|
||||
boxShadow: "0 6px 16px rgba(37,99,235,0.25)",
|
||||
},
|
||||
|
||||
buttonSecondary: {
|
||||
padding: "10px 14px",
|
||||
borderRadius: 12,
|
||||
border: "1px solid rgba(0,0,0,0.12)",
|
||||
background: "#fff",
|
||||
color: "#111827",
|
||||
fontWeight: 600,
|
||||
cursor: "pointer",
|
||||
},
|
||||
|
||||
grid: {
|
||||
marginTop: 18,
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(12, 1fr)",
|
||||
gap: 16,
|
||||
},
|
||||
|
||||
sectionTitle: {
|
||||
margin: 0,
|
||||
fontSize: 16,
|
||||
fontWeight: 700,
|
||||
},
|
||||
|
||||
sectionSubtitle: {
|
||||
margin: "6px 0 14px",
|
||||
fontSize: 13,
|
||||
color: "#6b7280",
|
||||
},
|
||||
|
||||
chartWrapper: {
|
||||
width: "100%",
|
||||
height: 350,
|
||||
},
|
||||
|
||||
heatmapWrapper: {
|
||||
width: "100%",
|
||||
height: 320,
|
||||
},
|
||||
|
||||
topUsersList: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
topUserItem: {
|
||||
padding: "10px 12px",
|
||||
borderRadius: 12,
|
||||
background: "#f9fafb",
|
||||
border: "1px solid rgba(0,0,0,0.06)",
|
||||
},
|
||||
|
||||
topUserName: {
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
color: "black"
|
||||
},
|
||||
|
||||
topUserMeta: {
|
||||
fontSize: 13,
|
||||
color: "#6b7280",
|
||||
},
|
||||
|
||||
scrollArea: {
|
||||
maxHeight: 450,
|
||||
overflowY: "auto",
|
||||
},
|
||||
...foundationStyles,
|
||||
...appLayoutStyles,
|
||||
...authStyles,
|
||||
...datasetStyles,
|
||||
...feedbackStyles,
|
||||
...cardStyles,
|
||||
...emotionalStyles,
|
||||
...modalStyles,
|
||||
};
|
||||
|
||||
export default StatsStyling;
|
||||
export default StatsStyling;
|
||||
|
||||
Reference in New Issue
Block a user