From 41ea9e0aa7f2a3da2201e24be6eb1e218394ef65 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Tue, 14 Jul 2026 15:23:37 +0000 Subject: [PATCH] feat(ui): Make timeline items more compact #500 --- src/client/components/ActivityTimeline.tsx | 36 +++++++++++----------- src/client/components/MSCollapsible.tsx | 12 ++++++-- src/client/components/Provider.tsx | 17 +++++++++- src/client/components/TransformSteps.tsx | 10 +++--- src/client/utils/ComponentUtils.tsx | 6 +++- 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/src/client/components/ActivityTimeline.tsx b/src/client/components/ActivityTimeline.tsx index 6b32a109..fc088564 100644 --- a/src/client/components/ActivityTimeline.tsx +++ b/src/client/components/ActivityTimeline.tsx @@ -1,4 +1,4 @@ -import type { Collapsible} from '@chakra-ui/react'; +import type { Collapsible, IconProps} from '@chakra-ui/react'; import { Card, Icon, SkeletonCircle, SkeletonText, Span, Tabs, Timeline, type HTMLChakraProps } from '@chakra-ui/react'; import type { Dayjs } from "dayjs"; import dayjs from "dayjs"; @@ -12,7 +12,7 @@ import { CLIENT_DEAD_QUEUE, CLIENT_INGRESS_QUEUE, QUEUE_STATUS_COMPLETED, QUEUE_ import { sortByNewestDate } from "../../core/PlayUtils"; import { capitalizeWords } from "../../core/StringUtils"; import { shortTodayAwareFormat } from "../../core/TimeUtils"; -import { activityTransformHasIssue, timelineTextFormatting } from "../utils/ComponentUtils"; +import { activityTransformHasIssue, timelineTextFormatting, timelineIconProps } from "../utils/ComponentUtils"; import { ChakraCodeBlockShort } from "./CodeBlock"; import { ErrorAlert } from "./ErrorAlert"; import { MSErrorBoundary } from "./ErrorBoundary"; @@ -42,7 +42,7 @@ const TimelineLoading = () => ( - + @@ -62,10 +62,10 @@ const QueuedCreatedItem = (props: { dead?: boolean, datetime: string }) => ( - + - + {props.dead ? 'Dead ' : ''}Queued at {shortTodayAwareFormat(dayjs(props.datetime))} @@ -98,7 +98,7 @@ const NewItem = (props: Pick - + @@ -157,12 +157,12 @@ const TransformsItem = (props: Pick - + - + ( - + - + Play was not transformed because no Transform Rules were used/configured. @@ -210,12 +210,12 @@ const ScrobbleMatchItem = (props: Pick & - + - + {error !== undefined ? : ( - + )} - + - + @@ -323,7 +323,7 @@ const QueueTimelineItem = (props: {queueState: QueueStateApi, collapsibleOpen: b - + @@ -356,10 +356,10 @@ const QueueTimelineItem = (props: {queueState: QueueStateApi, collapsibleOpen: b - + - + {titleContent} diff --git a/src/client/components/MSCollapsible.tsx b/src/client/components/MSCollapsible.tsx index 8993cf90..b3c3a49b 100644 --- a/src/client/components/MSCollapsible.tsx +++ b/src/client/components/MSCollapsible.tsx @@ -20,7 +20,15 @@ export interface MSCollapsibleExternalProps { export const timelineCollapsibleProps = { indicatorProps: { paddingBottom: '4px' }, - triggerProps: { paddingBlockStart: "0.3em" } + triggerProps: { paddingBlockStart: "0.3em" }, + triggerPropsClosed: { + //paddingBlockStart: "0.3em", + paddingBlock: 'initial' + }, + triggerPropsOpen: { + paddingBlock: 'initial', + paddingBlockEnd: "var(--chakra-spacing-3)" + } } export type MSCollapsibleProps = PropsWithChildren> & MSCollapsibleInternalProps; @@ -104,7 +112,7 @@ export const MSCollapsible = (props: MSCollapsibleProps) => { iProps.display = 'none'; } - const tProps = { ...(timeline ? timelineCollapsibleProps.triggerProps : {}), ...triggerProps } + const tProps = { ...(timeline ? (open? timelineCollapsibleProps.triggerPropsOpen : timelineCollapsibleProps.triggerPropsClosed) : {}), ...triggerProps } return ( setOpen(val.open)} flexGrow="1" disabled={isDisabled} {...rest}> diff --git a/src/client/components/Provider.tsx b/src/client/components/Provider.tsx index 9d8ed8d6..11b1aa25 100644 --- a/src/client/components/Provider.tsx +++ b/src/client/components/Provider.tsx @@ -1,6 +1,7 @@ "use client" -import { ChakraProvider, createSystem, defaultConfig, defineConfig } from "@chakra-ui/react" +import { ChakraProvider, createSystem, defaultConfig, defineConfig, defineSlotRecipe } from "@chakra-ui/react" +import { timelineAnatomy } from "@chakra-ui/react/anatomy"; import { QueryClient, QueryClientProvider @@ -11,6 +12,15 @@ import { type ColorModeProviderProps, } from "./Color-Mode" +const timelineSlotRecipe = defineSlotRecipe({ + slots: timelineAnatomy.keys(), + base: { + item: { + "--timeline-content-gap": "spacing.5" // was spacing.6 + } + } +}); + const queryClient = new QueryClient() const customConfig = defineConfig({ @@ -37,6 +47,11 @@ const customConfig = defineConfig({ color: "gray.500" } }, + theme: { + slotRecipes: { + timeline: timelineSlotRecipe + } + } }) export const system = createSystem(defaultConfig, customConfig) diff --git a/src/client/components/TransformSteps.tsx b/src/client/components/TransformSteps.tsx index 3c6c010f..377a0aca 100644 --- a/src/client/components/TransformSteps.tsx +++ b/src/client/components/TransformSteps.tsx @@ -1,10 +1,10 @@ -import { Heading, Icon, Span, Stack, Text, Timeline } from '@chakra-ui/react'; +import { Heading, Icon, Span, Stack, Text, Timeline} from '@chakra-ui/react'; import React, { Fragment, useMemo } from "react"; import { BsExclamationTriangle, BsSkipForward, BsStoplights } from "react-icons/bs"; import { MdMusicNote } from "react-icons/md"; import type {JsonPlayObject, LifecycleStep} from "../../core/Atomic"; import { patchObject } from "../../core/DataUtils"; -import { timelineTextFormatting } from "../utils/ComponentUtils"; +import { timelineIconProps, timelineTextFormatting } from "../utils/ComponentUtils"; import { ChakraCodeBlockShort } from "./CodeBlock"; import { ErrorAlert } from "./ErrorAlert"; import { MSCollapsible, type MSCollapsibleExternalProps } from "./MSCollapsible"; @@ -84,7 +84,7 @@ export const TransformSteps = (props: LifeycleStepsTimelineProps) => { const [diffs, finalPlay] = useMemo(() => diffElements(original, steps), [steps, original]); return ( - + {steps.map((x, index) => { const { patch, @@ -137,7 +137,7 @@ export const TransformSteps = (props: LifeycleStepsTimelineProps) => { - + {timelineIcon} @@ -175,7 +175,7 @@ export const TransformSteps = (props: LifeycleStepsTimelineProps) => { - + diff --git a/src/client/utils/ComponentUtils.tsx b/src/client/utils/ComponentUtils.tsx index 1aa726e0..615eaab6 100644 --- a/src/client/utils/ComponentUtils.tsx +++ b/src/client/utils/ComponentUtils.tsx @@ -1,4 +1,4 @@ -import type { Card} from '@chakra-ui/react'; +import type { Card, IconProps} from '@chakra-ui/react'; import type {HTMLChakraProps} from '@chakra-ui/react'; import type {PlayApiCommonDetailed} from '../../core/Api'; import { type LifecycleStep, QUEUE_STATUS_COMPLETED, QUEUE_STATUS_FAILED } from '../../core/Atomic'; @@ -13,6 +13,10 @@ export const timelineTextFormatting: HTMLChakraProps<"span"> = { textWrap: "balance" } +export const timelineIconProps: IconProps = { + fontSize: 'md' +} + export const activityTransformHasIssue = (steps: LifecycleStep[]): 'warn' | 'error' | undefined => { for(const step of steps) { if(step.flowKnownState === 'prereq') {