From 3833aa58a5f88cd00d0915b3af62dc451c9d2b4c Mon Sep 17 00:00:00 2001 From: Bill Leoutsakos Date: Sun, 20 Sep 2026 15:48:38 -0700 Subject: [PATCH 1/2] improvement(ui): share expandable home sections --- .../components/get-started/get-started.tsx | 88 ++++++------------ .../suggested-actions/suggested-actions.tsx | 92 +++++++------------ apps/sim/components/home/home-section.tsx | 52 +++++++++++ 3 files changed, 111 insertions(+), 121 deletions(-) create mode 100644 apps/sim/components/home/home-section.tsx diff --git a/apps/sim/app/o/[organizationId]/home/components/get-started/get-started.tsx b/apps/sim/app/o/[organizationId]/home/components/get-started/get-started.tsx index 5d343df275e..90d272b5883 100644 --- a/apps/sim/app/o/[organizationId]/home/components/get-started/get-started.tsx +++ b/apps/sim/app/o/[organizationId]/home/components/get-started/get-started.tsx @@ -1,9 +1,10 @@ 'use client' import { useEffect, useState } from 'react' -import { cn, Expandable, ExpandableContent } from '@sim/emcn' -import { ArrowRight, ChevronDown } from '@sim/emcn/icons' +import { cn } from '@sim/emcn' +import { ArrowRight } from '@sim/emcn/icons' import Link from 'next/link' +import { HomeSection } from '@/components/home/home-section' import { OAUTH_SEARCH_READ_SCOPE, oauthScopeSatisfies } from '@/lib/auth/oauth-provider' import type { ResourceScope } from '@/lib/core/resource-scope' import { organizationRoutes } from '@/lib/navigation/paths' @@ -132,64 +133,29 @@ export function GetStarted() { } return ( -
- {/* Full width so the whole line toggles, not just the label and chevron. */} - - - - {/* 6px, matching a sidebar section header to its first item — both headers - are an 18px box around 12px text, so equal padding reads as equal - distance. Padding an inner wrapper rather than the animated element: - `collapsible-up`/`-down` interpolate height alone, so a margin here - would hold its full value through the close and then vanish on unmount, - snapping the content below up. */} -
- {steps.map((step, i) => { - const complete = completed[step.id] - return ( - 0 && 'border-t')} - > - - - {step.label} - - - - ) - })} -
-
-
-
+ + {steps.map((step, i) => { + const complete = completed[step.id] + return ( + 0 && 'border-t')}> + + + {step.label} + + + + ) + })} + ) } diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx index 973bf4587fa..c794699b94d 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/suggested-actions/suggested-actions.tsx @@ -2,11 +2,12 @@ import { useMemo, useState } from 'react' import { INTEGRATION_METADATA } from '@sim/deployment-config/integration-metadata' -import { ArrowRight, ChevronDown, cn, Expandable, ExpandableContent, OverflowText } from '@sim/emcn' +import { ArrowRight, cn, OverflowText } from '@sim/emcn' import { Table } from '@sim/emcn/icons' import { stripVersionSuffix } from '@sim/utils/string' import { useParams } from 'next/navigation' import { usePostHog } from 'posthog-js/react' +import { HomeSection } from '@/components/home/home-section' import { GmailIcon, SlackIcon } from '@/components/icons' import { resolveOAuthServiceForIntegration, @@ -317,65 +318,36 @@ export function SuggestedActions({ onSelectPrompt }: SuggestedActionsProps) { } return ( -
- {/* Full width so the whole line toggles, not just the label and chevron. */} - - - - {/* 6px, matching a sidebar section header to its first item — both headers - are an 18px box around 12px text, so equal padding reads as equal - distance. Padding an inner wrapper rather than the animated element: - `collapsible-up`/`-down` interpolate height alone, so a margin here - would hold its full value through the close and then vanish on unmount, - snapping the content below up. */} -
- {actions.map((action, i) => { - const Icon = action.icon - return ( - - ) - })} -
-
-
+ {actions.map((action, i) => { + const Icon = action.icon + return ( + + ) + })} + {oauthTarget && workspaceId && ( )} -
+ ) } diff --git a/apps/sim/components/home/home-section.tsx b/apps/sim/components/home/home-section.tsx new file mode 100644 index 00000000000..f5a03415344 --- /dev/null +++ b/apps/sim/components/home/home-section.tsx @@ -0,0 +1,52 @@ +'use client' + +import type { ReactNode } from 'react' +import { cn, Expandable, ExpandableContent } from '@sim/emcn' +import { ChevronDown } from '@sim/emcn/icons' + +interface HomeSectionProps { + title: string + expanded: boolean + animationsEnabled: boolean + onToggle: () => void + children: ReactNode +} + +/** + * Home-page section with caller-owned expansion and animation timing. + * Inner padding collapses with the content; margin would disappear on unmount and cause a jump. + * Section hover or toggle focus reveals the chevron, preserving keyboard feedback when global + * styles clear outlines. A shared transition keeps its fade and rotation synchronized. + */ +export function HomeSection({ + title, + expanded, + animationsEnabled, + onToggle, + children, +}: HomeSectionProps) { + return ( +
+ + + +
{children}
+
+
+
+ ) +} From 560470e74ec0c1c6bafffa4a94505396d493ebab Mon Sep 17 00:00:00 2001 From: Bill Leoutsakos Date: Sun, 20 Sep 2026 15:57:29 -0700 Subject: [PATCH 2/2] fix(ui): inherit home section client boundary from callers --- apps/sim/components/home/home-section.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/sim/components/home/home-section.tsx b/apps/sim/components/home/home-section.tsx index f5a03415344..0b6c8da9b30 100644 --- a/apps/sim/components/home/home-section.tsx +++ b/apps/sim/components/home/home-section.tsx @@ -1,5 +1,3 @@ -'use client' - import type { ReactNode } from 'react' import { cn, Expandable, ExpandableContent } from '@sim/emcn' import { ChevronDown } from '@sim/emcn/icons'