/** * Shared makeStyles definitions for the config page and its components. * * All config tab components import `useConfigStyles` from this module * so that visual changes need updating in only one place. */ import { makeStyles, tokens } from "@fluentui/react-components"; export const useConfigStyles = makeStyles({ page: { padding: tokens.spacingVerticalXXL, maxWidth: "1100px", }, // ------------------------------------------------------------------------- // List/Detail layout (ConfigListDetail component) // ------------------------------------------------------------------------- /** Root flex-row container for the two-pane list/detail layout. */ listDetailRoot: { display: "flex", flexDirection: "row", gap: tokens.spacingHorizontalM, minHeight: "400px", "@media (max-width: 900px)": { flexDirection: "column", }, }, /** Fixed-width left pane with scrollable item list. */ listPane: { width: "280px", flexShrink: "0", overflowY: "auto", borderRight: `1px solid ${tokens.colorNeutralStroke2}`, paddingRight: tokens.spacingHorizontalS, "@media (max-width: 900px)": { width: "100%", borderRight: "none", borderBottom: `1px solid ${tokens.colorNeutralStroke2}`, paddingRight: "0", paddingBottom: tokens.spacingVerticalS, overflowY: "visible", }, }, /** A single clickable item in the left pane. */ listItem: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: `${tokens.spacingVerticalS} ${tokens.spacingHorizontalM}`, borderRadius: tokens.borderRadiusMedium, cursor: "pointer", userSelect: "none", overflow: "hidden", ":hover": { backgroundColor: tokens.colorNeutralBackground2, }, ":focus-visible": { outline: `2px solid ${tokens.colorBrandBackground}`, outlineOffset: "2px", }, }, /** Additional styles applied to the currently selected list item. */ listItemSelected: { backgroundColor: tokens.colorNeutralBackground1Selected, borderLeft: `3px solid ${tokens.colorBrandBackground}`, paddingLeft: `calc(${tokens.spacingHorizontalM} - 3px)`, ":hover": { backgroundColor: tokens.colorNeutralBackground1Selected, }, }, /** Right pane that shows detail content for the selected item. */ detailPane: { flex: "1", overflowY: "auto", paddingLeft: tokens.spacingHorizontalM, "@media (max-width: 900px)": { paddingLeft: "0", }, }, header: { marginBottom: tokens.spacingVerticalL, }, tabContent: { marginTop: tokens.spacingVerticalL, animationName: "fadeInUp", animationDuration: tokens.durationNormal, animationTimingFunction: tokens.curveDecelerateMid, animationFillMode: "both", }, section: { marginBottom: tokens.spacingVerticalXL, }, /** Card container for form sections — adds visual separation and depth. */ sectionCard: { backgroundColor: tokens.colorNeutralBackground2, borderRadius: tokens.borderRadiusMedium, padding: `${tokens.spacingVerticalM} ${tokens.spacingHorizontalL}`, boxShadow: tokens.shadow4, marginBottom: tokens.spacingVerticalS, }, /** Label row at the top of a sectionCard. */ sectionCardHeader: { color: tokens.colorNeutralForeground2, borderBottom: `1px solid ${tokens.colorNeutralStroke2}`, paddingBottom: tokens.spacingVerticalS, marginBottom: tokens.spacingVerticalM, textTransform: "uppercase", letterSpacing: "0.05em", fontSize: tokens.fontSizeBase200, fontWeight: tokens.fontWeightSemibold, }, /** Monospace input with left brand-colour accent bar. */ codeInput: { fontFamily: "monospace", borderLeft: `3px solid ${tokens.colorBrandStroke1}`, }, /** Applied to AccordionItem wrappers to get a hover background on headers. */ accordionItem: { "& button:hover": { backgroundColor: tokens.colorNeutralBackground1Hover, }, }, /** Applied to AccordionItem wrappers that are currently expanded. */ accordionItemOpen: { borderLeft: `3px solid ${tokens.colorBrandBackground}`, }, fieldRow: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: tokens.spacingHorizontalM, marginBottom: tokens.spacingVerticalS, alignItems: "end", "@media (max-width: 900px)": { gridTemplateColumns: "1fr", }, }, fieldRowThree: { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: tokens.spacingHorizontalM, marginBottom: tokens.spacingVerticalS, "@media (max-width: 900px)": { gridTemplateColumns: "1fr 1fr", }, "@media (max-width: 700px)": { gridTemplateColumns: "1fr", }, }, buttonRow: { display: "flex", gap: tokens.spacingHorizontalS, marginTop: tokens.spacingVerticalM, flexWrap: "wrap", }, codeFont: { fontFamily: "monospace", fontSize: "0.85rem", }, regexItem: { display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS, marginBottom: tokens.spacingVerticalXS, }, regexInput: { flexGrow: "1", fontFamily: "monospace", borderLeft: `3px solid ${tokens.colorBrandStroke1}`, }, logLine: { padding: `${tokens.spacingVerticalXS} ${tokens.spacingHorizontalS}`, borderRadius: tokens.borderRadiusSmall, fontFamily: "monospace", fontSize: "0.8rem", marginBottom: tokens.spacingVerticalXXS, wordBreak: "break-all", }, matched: { backgroundColor: tokens.colorPaletteGreenBackground2, }, notMatched: { backgroundColor: tokens.colorNeutralBackground3, }, previewArea: { maxHeight: "400px", overflowY: "auto", padding: tokens.spacingHorizontalS, border: `1px solid ${tokens.colorNeutralStroke1}`, borderRadius: tokens.borderRadiusMedium, marginTop: tokens.spacingVerticalS, }, infoText: { color: tokens.colorNeutralForeground3, fontStyle: "italic", }, /** Empty-state container: centred icon + message. */ emptyState: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: tokens.spacingVerticalM, padding: `${tokens.spacingVerticalXXL} ${tokens.spacingHorizontalL}`, color: tokens.colorNeutralForeground3, textAlign: "center", }, /** Auto-save status chip — for AutoSaveIndicator. */ autoSaveWrapper: { display: "flex", alignItems: "center", gap: tokens.spacingHorizontalXS, fontSize: tokens.fontSizeBase200, color: tokens.colorNeutralForeground2, }, autoSaveSaved: { opacity: "1", transform: "scale(1)", transition: `opacity ${tokens.durationNormal} ${tokens.curveDecelerateMid}, transform ${tokens.durationNormal} ${tokens.curveDecelerateMid}`, }, autoSaveFadingOut: { opacity: "0", transition: `opacity ${tokens.durationNormal} ${tokens.curveDecelerateMid}`, }, }); /** * Global CSS keyframes injected once. * * ``makeStyles`` does not support top-level ``@keyframes``, so we inject them * via a ``