diff --git a/apps/sim/app/(interfaces)/chat/components/message/components/file-download.tsx b/apps/sim/app/(interfaces)/chat/components/message/components/file-download.tsx index 938ea3f2b3c..0e3c40e1f15 100644 --- a/apps/sim/app/(interfaces)/chat/components/message/components/file-download.tsx +++ b/apps/sim/app/(interfaces)/chat/components/message/components/file-download.tsx @@ -254,7 +254,7 @@ export function ChatFileDownloadAll({ files }: ChatFileDownloadAllProps) { variant='ghost-secondary' onClick={handleDownloadAll} disabled={isDownloading} - className='p-0' + size='icon' > {isDownloading ? ( diff --git a/apps/sim/app/(interfaces)/chat/components/message/message.tsx b/apps/sim/app/(interfaces)/chat/components/message/message.tsx index 9458ed16be7..1b99ccf96cc 100644 --- a/apps/sim/app/(interfaces)/chat/components/message/message.tsx +++ b/apps/sim/app/(interfaces)/chat/components/message/message.tsx @@ -274,7 +274,7 @@ export const ClientChatMessage = memo(function ClientChatMessage({ - + +
{/* `disabled` on the fieldset reaches every native control inside, diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichment-config.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichment-config.tsx index f411281d21e..e158e4ab159 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichment-config.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichment-config.tsx @@ -21,6 +21,10 @@ import type { ColumnDefinition, WorkflowGroup, WorkflowGroupOutput } from '@/lib import { columnMatchesRef, getColumnId } from '@/lib/table/column-keys' import { deriveOutputColumnName } from '@/lib/table/column-naming' import { FieldError } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/sidebar-fields' +import { + TableSidebarHeader, + TableSidebarHeaderAction, +} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-header/table-sidebar-header' import type { EnrichmentConfig as EnrichmentDef } from '@/enrichments/types' import { useAddWorkflowGroup, @@ -232,31 +236,21 @@ export function EnrichmentConfig({ return (
-
+
- +
- -
+ +
diff --git a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichments-sidebar.tsx b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichments-sidebar.tsx index 0aebd34cb4c..421055477fc 100644 --- a/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichments-sidebar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/enrichments-sidebar/enrichments-sidebar.tsx @@ -1,9 +1,13 @@ 'use client' import { useState } from 'react' -import { Button, ChipInput, cn } from '@sim/emcn' +import { ChipInput, cn } from '@sim/emcn' import { Search, X } from '@sim/emcn/icons' import type { ColumnDefinition, WorkflowGroup } from '@/lib/table' +import { + TableSidebarHeader, + TableSidebarHeaderAction, +} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-header/table-sidebar-header' import { ALL_ENRICHMENTS } from '@/enrichments' import { getEnrichment } from '@/enrichments/registry' import type { EnrichmentConfig as EnrichmentDef } from '@/enrichments/types' @@ -71,19 +75,12 @@ function EnrichmentsSidebarBody({ if (editGroup && !editEnrichment) { return (
-
+

Enrichment

- -
+ +

This enrichment ("{editGroup.enrichmentId}") is no longer available. Delete the column @@ -118,19 +115,12 @@ function EnrichmentsSidebarBody({ return (

-
+

Enrichments

- -
+ +
+ {children} +
+ ) +} + +interface TableSidebarHeaderActionProps extends ButtonHTMLAttributes { + 'aria-label': string +} + +export const TableSidebarHeaderAction = forwardRef< + HTMLButtonElement, + TableSidebarHeaderActionProps +>(({ className, ...props }, ref) => ( + + )}

- -
+ +
{/* Single-output mode renames this column directly. */} @@ -730,7 +724,8 @@ export function WorkflowSidebarBody({ 'noopener,noreferrer' ) } - className='absolute right-[6px] bottom-1.5 z-10 size-[24px] cursor-pointer border border-[var(--border)] bg-[var(--surface-2)] p-0 hover-hover:bg-[var(--surface-4)]' + iconSize='compact-fixed' + className='absolute right-[6px] bottom-1.5 z-10 cursor-pointer border border-[var(--border)] bg-[var(--surface-2)] hover-hover:bg-[var(--surface-4)]' > @@ -837,23 +832,9 @@ export function WorkflowSidebarBody({ )} {selectedWorkflowId && ( <> -
- - - -
+ setShowAdvanced((v) => !v)}> + {showAdvanced ? 'Hide additional fields' : 'Show additional fields'} + {showAdvanced && ( <> @@ -517,6 +518,7 @@ export const ActionBar = memo( collaborativeBatchToggleBlockEnabled([blockId]) } }} + iconSize='compact-fixed' className={getActionButtonStyles('enabled')} disabled={ isWorkflowRunning || @@ -553,6 +555,7 @@ export const ActionBar = memo( ) : (
@@ -499,7 +505,7 @@ export function Editor() { @@ -742,22 +749,14 @@ export function Editor() { })} {hasAdditionalFields && canEditBlock && ( -
- - - -
+ + {displayAdvancedOptions + ? 'Hide additional fields' + : 'Show additional fields'} + )} {hasAdditionalFields && !canEditBlock && displayAdvancedOptions && (
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx index 09ede00b538..27f4ee1ed93 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/toolbar/toolbar.tsx @@ -875,12 +875,7 @@ export const Toolbar = memo(

Toolbar

{!isSearchActive ? ( - ) : ( diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx index 5f894cfc5f3..5337e108a8d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/panel.tsx @@ -915,7 +915,7 @@ export const Panel = memo(function Panel() { diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx index 6a1ce331611..a583115eaa6 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx @@ -1398,7 +1398,8 @@ function PreviewEditorContent({ type='button' variant='ghost' onClick={handleExpandChildWorkflow} - className='absolute right-[6px] bottom-1.5 z-10 size-[24px] cursor-pointer border border-[var(--border)] bg-[var(--surface-2)] p-0 hover-hover:bg-[var(--surface-4)]' + iconSize='compact-fixed' + className='absolute right-[6px] bottom-1.5 z-10 cursor-pointer border border-[var(--border)] bg-[var(--surface-2)] hover-hover:bg-[var(--surface-4)]' > {isExecutionMode && onDrillDown ? ( diff --git a/packages/emcn/src/components/bulk-action-button/bulk-action-button.tsx b/packages/emcn/src/components/bulk-action-button/bulk-action-button.tsx index b24e402e274..8088e98f093 100644 --- a/packages/emcn/src/components/bulk-action-button/bulk-action-button.tsx +++ b/packages/emcn/src/components/bulk-action-button/bulk-action-button.tsx @@ -18,7 +18,8 @@ export const bulkActionButtonVariants = cva( } ) -export interface BulkActionButtonProps extends Omit { +export interface BulkActionButtonProps + extends Omit { /** Accessible name for the icon action; tooltip content is supplied separately. */ 'aria-label': string /** diff --git a/packages/emcn/src/components/button/button.test.tsx b/packages/emcn/src/components/button/button.test.tsx new file mode 100644 index 00000000000..c0b4fc35df3 --- /dev/null +++ b/packages/emcn/src/components/button/button.test.tsx @@ -0,0 +1,67 @@ +/** @vitest-environment node */ +/** biome-ignore assist/source/organizeImports: Preserve the documented core/external/UI import order. */ +import { renderToStaticMarkup } from 'react-dom/server' +import { describe, expect, it } from 'vitest' +import { Button } from '@sim/emcn' + +function normalizeClasses(markup: string) { + return markup.replace( + /class="([^"]+)"/g, + (_, classes: string) => `class="${classes.split(/\s+/).sort().join(' ')}"` + ) +} + +/** The three existing Button treatments used by compact product actions. */ +const TREATMENTS = [ + { size: undefined, variant: 'ghost' }, + { size: 'sm', variant: 'ghost-secondary' }, + { size: 'icon', variant: 'ghost' }, +] as const + +describe('Button iconSize', () => { + for (const [iconSize, previousClass] of [ + ['compact', 'size-6 p-0'], + ['compact-fixed', 'size-[24px] p-0'], + ] as const) { + it.each(TREATMENTS)( + `preserves the ${iconSize} treatment with size=$size and variant=$variant`, + (treatment) => { + const icon = + const before = renderToStaticMarkup( + + ) + const after = renderToStaticMarkup( + + ) + expect(normalizeClasses(after)).toBe(normalizeClasses(before)) + } + ) + } + + it('allows explicit padding and consumer width to take precedence', () => { + const markup = renderToStaticMarkup( + + */ + iconSize?: VariantProps['iconSize'] /** * Symmetric padding for icon actions whose content or layout determines their size. * Preserves the selected size's typography, corner radius and icon stroke. @@ -85,11 +98,11 @@ export interface ButtonProps } const Button = forwardRef( - ({ className, variant, size, iconPadding, ...props }, ref) => { + ({ className, variant, size, iconSize, iconPadding, ...props }, ref) => { return ( + +
+ ) +} + +export { DashedDividerLine, FieldDisclosure, FieldDivider } diff --git a/packages/emcn/src/components/index.ts b/packages/emcn/src/components/index.ts index 6628b0a2d1b..29607eea0a6 100644 --- a/packages/emcn/src/components/index.ts +++ b/packages/emcn/src/components/index.ts @@ -153,7 +153,12 @@ export { dropdownMenuRowClass, } from './dropdown-menu/dropdown-menu' export { Expandable, ExpandableContent } from './expandable/expandable' -export { DashedDividerLine, FieldDivider } from './field-divider/field-divider' +export { + DashedDividerLine, + FieldDisclosure, + type FieldDisclosureProps, + FieldDivider, +} from './field-divider/field-divider' export { Info } from './info/info' export { InfoCard, diff --git a/packages/workflow-renderer/src/note/note-block-view.tsx b/packages/workflow-renderer/src/note/note-block-view.tsx index d47a556d391..6b71def6fb5 100644 --- a/packages/workflow-renderer/src/note/note-block-view.tsx +++ b/packages/workflow-renderer/src/note/note-block-view.tsx @@ -1058,7 +1058,8 @@ export function NoteBlockView({ event.stopPropagation() onExpandedChange(!isExpanded) }} - className='nodrag nopan nowheel pointer-events-none ml-1 size-[24px] shrink-0 rounded-md border-none bg-transparent p-0 text-current opacity-0 transition-[background-color,color,opacity,transform] duration-150 hover-hover:bg-current/10 hover-hover:opacity-100 active:scale-[0.96] group-hover:pointer-events-auto group-hover:opacity-70 group-data-[node-selected]:pointer-events-auto group-data-[node-selected]:opacity-70' + iconSize='compact-fixed' + className='nodrag nopan nowheel pointer-events-none ml-1 shrink-0 rounded-md border-none bg-transparent text-current opacity-0 transition-[background-color,color,opacity,transform] duration-150 hover-hover:bg-current/10 hover-hover:opacity-100 active:scale-[0.96] group-hover:pointer-events-auto group-hover:opacity-70 group-data-[node-selected]:pointer-events-auto group-data-[node-selected]:opacity-70' >