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.

View File

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

View File

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

View File

@@ -14,6 +14,7 @@ import {
Spinner,
Text,
makeStyles,
mergeClasses,
tokens,
} from "@fluentui/react-components";
import {
@@ -71,6 +72,29 @@ const useStyles = makeStyles({
borderRadius: tokens.borderRadiusMedium,
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: {
display: "flex",
alignItems: "center",
@@ -158,7 +182,7 @@ export function MapPage(): React.JSX.Element {
World Map
</Text>
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalM, flexWrap: "wrap" }}>
<div className={styles.headerActions}>
<DashboardFilterBar
timeRange={range}
onTimeRangeChange={(value) => {
@@ -193,7 +217,7 @@ export function MapPage(): React.JSX.Element {
{/* Initial load spinner — only shown before the first data arrives. */}
{loading && !error && !hasLoadedOnce && (
<div style={{ display: "flex", justifyContent: "center", padding: tokens.spacingVerticalXL }}>
<div className={styles.initialLoad}>
<Spinner label="Loading map data…" />
</div>
)}
@@ -242,8 +266,8 @@ export function MapPage(): React.JSX.Element {
{/* Summary line */}
{/* ---------------------------------------------------------------- */}
{!error && hasLoadedOnce && (
<div style={{ display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS }}>
<Text size={300} style={{ color: tokens.colorNeutralForeground3 }}>
<div className={styles.summaryRow}>
<Text size={300} className={styles.summaryText}>
{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
@@ -256,7 +280,7 @@ export function MapPage(): React.JSX.Element {
{/* Companion bans table */}
{/* ---------------------------------------------------------------- */}
{!error && hasLoadedOnce && (
<div className={styles.tableWrapper} style={{ opacity: loading ? 0.5 : 1, transition: "opacity 150ms" }}>
<div className={mergeClasses(styles.tableWrapper, loading && styles.tableWrapperLoading)}>
<MapBansTable
pageBans={pageBans}
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 type { Jail } from "../../types/jail";
import { CodeList } from "./CodeList";
@@ -7,8 +7,15 @@ interface PatternsSectionProps {
jail: Jail;
}
const useStyles = makeStyles({
spacedHeading: {
marginTop: tokens.spacingVerticalS,
},
});
export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Element {
const sectionStyles = useCommonSectionStyles();
const styles = useStyles();
return (
<div className={sectionStyles.section}>
@@ -23,19 +30,19 @@ export function PatternsSection({ jail }: PatternsSectionProps): React.JSX.Eleme
</Text>
<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
</Text>
<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
</Text>
<CodeList items={jail.ignore_regex} empty="No ignore-regex patterns." />
{jail.actions.length > 0 && (
<>
<Text size={300} weight="semibold" style={{ marginTop: "var(--spacingVerticalS)" }}>
<Text size={300} weight="semibold" className={styles.spacedHeading}>
Actions
</Text>
<CodeList items={jail.actions} empty="" />

View File

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

View File

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