Move constant inline styles into makeStyles

This commit is contained in:
2026-04-21 18:47:18 +02:00
parent 86a7336ac0
commit 4da2703966
7 changed files with 67 additions and 14 deletions

View File

@@ -354,7 +354,11 @@ const source = timeRange === "24h" ? "fail2ban" : "archive";
--- ---
### TASK-018 — Move inline `style={{…}}` objects to `makeStyles` ### TASK-018 — Move inline `style={{…}}` objects to `makeStyles` (done)
**Where fixed:** `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, `frontend/src/pages/jails/jailsPageStyles.ts`
**Summary:** Moved constant inline style objects into `makeStyles` classes and used `mergeClasses` for dynamic button layout in `MainLayout`. Kept runtime-dependent opacity and collapse state as conditional class application.
**Where found:** 30+ instances across `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/map/MapBansTable.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, and others. **Where found:** 30+ instances across `frontend/src/pages/MapPage.tsx`, `frontend/src/pages/map/MapBansTable.tsx`, `frontend/src/pages/DashboardPage.tsx`, `frontend/src/pages/jail/PatternsSection.tsx`, `frontend/src/pages/jails/BanUnbanForm.tsx`, `frontend/src/layouts/MainLayout.tsx`, and others.

View File

@@ -145,6 +145,13 @@ const useStyles = makeStyles({
padding: tokens.spacingVerticalS, padding: tokens.spacingVerticalS,
flexShrink: 0, flexShrink: 0,
}, },
logoutButton: {
width: "100%",
justifyContent: "flex-start",
},
logoutButtonCollapsed: {
justifyContent: "center",
},
versionText: { versionText: {
display: "block", display: "block",
color: tokens.colorNeutralForeground4, color: tokens.colorNeutralForeground4,
@@ -326,7 +333,10 @@ export function MainLayout(): React.JSX.Element {
icon={<SignOutRegular />} icon={<SignOutRegular />}
onClick={() => void handleLogout()} onClick={() => void handleLogout()}
aria-label="Sign out" aria-label="Sign out"
style={{ width: "100%", justifyContent: collapsed ? "center" : "flex-start" }} className={mergeClasses(
styles.logoutButton,
collapsed && styles.logoutButtonCollapsed,
)}
> >
{!collapsed && "Sign out"} {!collapsed && "Sign out"}
</Button> </Button>

View File

@@ -31,6 +31,12 @@ const useStyles = makeStyles({
flexDirection: "column", flexDirection: "column",
gap: tokens.spacingVerticalM, gap: tokens.spacingVerticalM,
}, },
filterRow: {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalM,
flexWrap: "wrap",
},
sectionHeader: { sectionHeader: {
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
@@ -89,7 +95,7 @@ export function DashboardPage(): React.JSX.Element {
{/* ------------------------------------------------------------------ */} {/* ------------------------------------------------------------------ */}
{/* Global filter bar */} {/* Global filter bar */}
{/* ------------------------------------------------------------------ */} {/* ------------------------------------------------------------------ */}
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM, flexWrap: "wrap" }}> <div className={styles.filterRow}>
<DashboardFilterBar <DashboardFilterBar
timeRange={timeRange} timeRange={timeRange}
onTimeRangeChange={setTimeRange} onTimeRangeChange={setTimeRange}

View File

@@ -14,6 +14,7 @@ import {
Spinner, Spinner,
Text, Text,
makeStyles, makeStyles,
mergeClasses,
tokens, tokens,
} from "@fluentui/react-components"; } from "@fluentui/react-components";
import { import {
@@ -71,6 +72,29 @@ const useStyles = makeStyles({
borderRadius: tokens.borderRadiusMedium, borderRadius: tokens.borderRadiusMedium,
backgroundColor: tokens.colorNeutralBackground2, backgroundColor: tokens.colorNeutralBackground2,
}, },
headerActions: {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalM,
flexWrap: "wrap",
},
initialLoad: {
display: "flex",
justifyContent: "center",
padding: tokens.spacingVerticalXL,
},
summaryRow: {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalS,
},
summaryText: {
color: tokens.colorNeutralForeground3,
},
tableWrapperLoading: {
opacity: 0.5,
transition: "opacity 150ms",
},
pagination: { pagination: {
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
@@ -158,7 +182,7 @@ export function MapPage(): React.JSX.Element {
World Map World Map
</Text> </Text>
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM, flexWrap: "wrap" }}> <div className={styles.headerActions}>
<DashboardFilterBar <DashboardFilterBar
timeRange={range} timeRange={range}
onTimeRangeChange={(value) => { onTimeRangeChange={(value) => {
@@ -193,7 +217,7 @@ export function MapPage(): React.JSX.Element {
{/* Initial load spinner — only shown before the first data arrives. */} {/* Initial load spinner — only shown before the first data arrives. */}
{loading && !error && !hasLoadedOnce && ( {loading && !error && !hasLoadedOnce && (
<div style={{ display: "flex", justifyContent: "center", padding: tokens.spacingVerticalXL }}> <div className={styles.initialLoad}>
<Spinner label="Loading map data…" /> <Spinner label="Loading map data…" />
</div> </div>
)} )}
@@ -242,8 +266,8 @@ export function MapPage(): React.JSX.Element {
{/* Summary line */} {/* Summary line */}
{/* ---------------------------------------------------------------- */} {/* ---------------------------------------------------------------- */}
{!error && hasLoadedOnce && ( {!error && hasLoadedOnce && (
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}> <div className={styles.summaryRow}>
<Text size={300} style={{ color: tokens.colorNeutralForeground3 }}> <Text size={300} className={styles.summaryText}>
{String(total)} total ban{total !== 1 ? "s" : ""} in the selected period {String(total)} total ban{total !== 1 ? "s" : ""} in the selected period
{" · "} {" · "}
{String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected {String(Object.keys(countries).length)} countr{Object.keys(countries).length !== 1 ? "ies" : "y"} affected
@@ -256,7 +280,7 @@ export function MapPage(): React.JSX.Element {
{/* Companion bans table */} {/* Companion bans table */}
{/* ---------------------------------------------------------------- */} {/* ---------------------------------------------------------------- */}
{!error && hasLoadedOnce && ( {!error && hasLoadedOnce && (
<div className={styles.tableWrapper} style={{ opacity: loading ? 0.5 : 1, transition: "opacity 150ms" }}> <div className={mergeClasses(styles.tableWrapper, loading && styles.tableWrapperLoading)}>
<MapBansTable <MapBansTable
pageBans={pageBans} pageBans={pageBans}
visibleCount={visibleBans.length} visibleCount={visibleBans.length}

View File

@@ -1,4 +1,4 @@
import { Text } from "@fluentui/react-components"; import { Text, makeStyles, tokens } from "@fluentui/react-components";
import { useCommonSectionStyles } from "../../components/commonStyles"; import { useCommonSectionStyles } from "../../components/commonStyles";
import type { Jail } from "../../types/jail"; import type { Jail } from "../../types/jail";
import { CodeList } from "./CodeList"; import { CodeList } from "./CodeList";
@@ -7,8 +7,15 @@ interface PatternsSectionProps {
jail: Jail; jail: Jail;
} }
const useStyles = makeStyles({
spacedHeading: {
marginTop: tokens.spacingVerticalS,
},
});
export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Element { export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Element {
const sectionStyles = useCommonSectionStyles(); const sectionStyles = useCommonSectionStyles();
const styles = useStyles();
return ( return (
<div className={sectionStyles.section}> <div className={sectionStyles.section}>
@@ -23,19 +30,19 @@ export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Eleme
</Text> </Text>
<CodeList items={jail.log_paths} empty="No log paths configured." /> <CodeList items={jail.log_paths} empty="No log paths configured." />
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}> <Text size={300} weight="semibold" className={styles.spacedHeading}>
Fail Regex Fail Regex
</Text> </Text>
<CodeList items={jail.fail_regex} empty="No fail-regex patterns." /> <CodeList items={jail.fail_regex} empty="No fail-regex patterns." />
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}> <Text size={300} weight="semibold" className={styles.spacedHeading}>
Ignore Regex Ignore Regex
</Text> </Text>
<CodeList items={jail.ignore_regex} empty="No ignore-regex patterns." /> <CodeList items={jail.ignore_regex} empty="No ignore-regex patterns." />
{jail.actions.length > 0 && ( {jail.actions.length > 0 && (
<> <>
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}> <Text size={300} weight="semibold" className={styles.spacedHeading}>
Actions Actions
</Text> </Text>
<CodeList items={jail.actions} empty="" /> <CodeList items={jail.actions} empty="" />

View File

@@ -7,7 +7,6 @@ import {
MessageBarBody, MessageBarBody,
Select, Select,
Text, Text,
tokens,
} from "@fluentui/react-components"; } from "@fluentui/react-components";
import { LockClosedRegular, LockOpenRegular } from "@fluentui/react-icons"; import { LockClosedRegular, LockOpenRegular } from "@fluentui/react-icons";
import { useCommonSectionStyles } from "../../components/commonStyles"; import { useCommonSectionStyles } from "../../components/commonStyles";
@@ -142,7 +141,7 @@ export function BanUnbanForm({ jailNames, onBan, onUnban }: BanUnbanFormProps):
</Button> </Button>
</div> </div>
<Text size={300} weight="semibold" style={{ marginTop: tokens.spacingVerticalS }}> <Text size={300} weight="semibold" className={styles.sectionHeadingSpacing}>
Unban an IP Unban an IP
</Text> </Text>
<div className={styles.formRow}> <div className={styles.formRow}>

View File

@@ -43,4 +43,7 @@ export const useJailsPageStyles = makeStyles({
alignItems: "center", alignItems: "center",
}, },
lookupLabel: { fontWeight: tokens.fontWeightSemibold }, lookupLabel: { fontWeight: tokens.fontWeightSemibold },
sectionHeadingSpacing: {
marginTop: tokens.spacingVerticalS,
},
}); });