Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@ function DetailCodeSection({
<Code.Viewer
code={jsonString}
language='json'
className='max-w-full rounded-md border-0 bg-[var(--surface-4)]! [word-break:break-all] dark:bg-[var(--surface-3)]!'
appearance='inspection'
className='max-w-full [word-break:break-all]'
wrapText
searchQuery={isSearchActive ? searchQuery : undefined}
currentMatchIndex={currentMatchIndex}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ export const WorkflowOutputSection = memo(
<Code.Viewer
code={jsonString}
language='json'
className='max-h-[300px] min-h-0 max-w-full rounded-md border-0 bg-[var(--surface-4)]! [word-break:break-all] dark:bg-[var(--surface-3)]!'
appearance='inspection'
className='max-h-[300px] min-h-0 max-w-full [word-break:break-all]'
wrapText
searchQuery={isSearchActive ? searchQuery : undefined}
currentMatchIndex={currentMatchIndex}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ function ServerDetailView({
: 'json'
}
wrapText
className='min-h-0! rounded-sm border border-[var(--border-1)]'
className='min-h-0!'
/>
{activeConfigTab === 'cursor' && (
<a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Button,
ChipCombobox,
ChipInput,
cn,
FieldDivider,
Label,
Switch,
Expand All @@ -29,6 +28,10 @@ import {
TableSidebarHeader,
TableSidebarHeaderAction,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-header/table-sidebar-header'
import {
TableSidebarScrollBody,
TableSidebarShell,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout'
import { useAddTableColumn, useUpdateColumn } from '@/hooks/queries/tables'
import { SelectOptionsEditor } from '../select-field'
import { columnTypeOptionsForTable } from './column-types'
Expand Down Expand Up @@ -100,18 +103,11 @@ export function ColumnConfigSidebar(props: ColumnConfigSidebarProps) {
// different column / mode remounts and re-seeds state from props.
const open = props.config !== null
return (
<aside
role='dialog'
aria-label='Configure column'
className={cn(
'absolute top-0 right-0 bottom-0 z-[var(--z-modal)] flex w-[400px] flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--bg)] transition-transform duration-200 ease-out',
open ? 'translate-x-0 shadow-overlay' : 'translate-x-full'
)}
>
<TableSidebarShell open={open} aria-label='Configure column'>
{props.config && (
<ColumnConfigBody key={configKey(props.config)} {...props} config={props.config} />
)}
</aside>
</TableSidebarShell>
)
}

Expand Down Expand Up @@ -274,7 +270,7 @@ function ColumnConfigBody({
</TableSidebarHeaderAction>
</TableSidebarHeader>

<div className='flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]'>
<TableSidebarScrollBody>
{/* `disabled` on the fieldset reaches every native control inside,
including the comboboxes' trigger buttons; `contents` keeps the
existing layout. Values stay readable and selectable. */}
Expand Down Expand Up @@ -383,7 +379,7 @@ function ColumnConfigBody({
</>
)}
</fieldset>
</div>
</TableSidebarScrollBody>

<div className='flex items-center justify-end gap-2 border-[var(--border)] border-t px-2 py-3'>
<Button variant='default' size='sm' onClick={onClose}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
TableSidebarHeader,
TableSidebarHeaderAction,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-header/table-sidebar-header'
import { TableSidebarScrollBody } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout'
import type { EnrichmentConfig as EnrichmentDef } from '@/enrichments/types'
import {
useAddWorkflowGroup,
Expand Down Expand Up @@ -252,7 +253,7 @@ export function EnrichmentConfig({
</TableSidebarHeaderAction>
</TableSidebarHeader>

<div className='flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]'>
<TableSidebarScrollBody>
<div className='flex flex-col gap-[9.5px]'>
<Label className='flex items-baseline gap-1.5 whitespace-nowrap pl-0.5'>Inputs</Label>
{enrichment.inputs.length === 0 ? (
Expand Down Expand Up @@ -362,7 +363,7 @@ export function EnrichmentConfig({
/>
</>
)}
</div>
</TableSidebarScrollBody>

<div className='flex items-center justify-end gap-2 border-[var(--border)] border-t px-2 py-3'>
<Button variant='default' size='sm' onClick={onClose}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
'use client'

import { useState } from 'react'
import { ChipInput, cn } from '@sim/emcn'
import { ChipInput } 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 { TableSidebarShell } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout'
import { ALL_ENRICHMENTS } from '@/enrichments'
import { getEnrichment } from '@/enrichments/registry'
import type { EnrichmentConfig as EnrichmentDef } from '@/enrichments/types'
Expand All @@ -31,16 +32,9 @@ interface EnrichmentsSidebarProps {
*/
export function EnrichmentsSidebar({ open, ...rest }: EnrichmentsSidebarProps) {
return (
<aside
role='dialog'
aria-label='Enrichments'
className={cn(
'absolute top-0 right-0 bottom-0 z-[var(--z-modal)] flex w-[400px] flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--bg)] transition-transform duration-200 ease-out',
open ? 'translate-x-0 shadow-overlay' : 'translate-x-full'
)}
>
<TableSidebarShell open={open} aria-label='Enrichments'>
{open && <EnrichmentsSidebarBody {...rest} />}
</aside>
</TableSidebarShell>
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @vitest-environment jsdom
*/
import { act } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import {
TableSidebarScrollBody,
TableSidebarShell,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout'

let container: HTMLDivElement
let root: Root

beforeEach(() => {
globalThis.IS_REACT_ACT_ENVIRONMENT = true
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
})

afterEach(() => {
act(() => root.unmount())
container.remove()
})

describe('table sidebar layout', () => {
it('keeps the labeled dialog and its form mounted while the sidebar slides closed', () => {
function render(open: boolean) {
act(() => {
root.render(
<TableSidebarShell open={open} aria-label='Configure workflow'>
<TableSidebarScrollBody>
<input aria-label='Workflow name' defaultValue='Existing workflow' />
</TableSidebarScrollBody>
</TableSidebarShell>
)
})
}

render(true)
const dialog = container.querySelector<HTMLElement>('[role="dialog"]')!
const input = container.querySelector<HTMLInputElement>('input')!
const scrollBody = input.parentElement!
expect(dialog.getAttribute('aria-label')).toBe('Configure workflow')
expect(dialog.classList.contains('translate-x-0')).toBe(true)
expect(dialog.classList.contains('shadow-overlay')).toBe(true)

input.value = 'Edited workflow'
scrollBody.scrollTop = 64
render(false)
expect(container.querySelector('[role="dialog"]')).toBe(dialog)
expect(container.querySelector('input')).toBe(input)
expect(input.value).toBe('Edited workflow')
expect(input.parentElement).toBe(scrollBody)
expect(scrollBody.scrollTop).toBe(64)
expect(dialog.classList.contains('translate-x-full')).toBe(true)
expect(dialog.classList.contains('shadow-overlay')).toBe(false)

render(true)
expect(dialog.classList.contains('translate-x-0')).toBe(true)
expect(input.value).toBe('Edited workflow')
expect(scrollBody.scrollTop).toBe(64)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ReactNode } from 'react'
import { cn } from '@sim/emcn'

interface TableSidebarShellProps {
open: boolean
'aria-label': string
children: ReactNode
}

/** The shared sliding shell for table configuration sidebars. */
export function TableSidebarShell({
open,
children,
'aria-label': ariaLabel,
}: TableSidebarShellProps) {
return (
<aside
role='dialog'
aria-label={ariaLabel}
className={cn(
'absolute top-0 right-0 bottom-0 z-[var(--z-modal)] flex w-[400px] flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--bg)] transition-transform duration-200 ease-out',
open ? 'translate-x-0 shadow-overlay' : 'translate-x-full'
)}
>
{children}
</aside>
)
}

interface TableSidebarScrollBodyProps {
children: ReactNode
}

/** The scrolling form area shared by column, workflow, and enrichment settings. */
export function TableSidebarScrollBody({ children }: TableSidebarScrollBodyProps) {
return (
<div className='flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]'>
{children}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ import {
ChipCombobox,
ChipInput,
type ComboboxOptionGroup,
cn,
FieldDisclosure,
FieldDivider,
Label,
Loader,
OverflowText,
Switch,
Tooltip,
toast,
} from '@sim/emcn'
import { ArrowLeft, SquareArrowUpRight, X } from '@sim/emcn/icons'
import { toError } from '@sim/utils/errors'
import { generateId } from '@sim/utils/id'
import { WorkflowPreviewAction } from '@/components/workflow/workflow-preview-action'
import { findValidationIssue, isValidationError } from '@/lib/api/client/errors'
import type {
AddWorkflowGroupBodyInput,
Expand Down Expand Up @@ -50,6 +49,10 @@ import {
TableSidebarHeader,
TableSidebarHeaderAction,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-header/table-sidebar-header'
import {
TableSidebarScrollBody,
TableSidebarShell,
} from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-sidebar-layout'
import { PreviewWorkflow } from '@/app/workspace/[workspaceId]/w/components/preview'
import { BlockTile } from '@/blocks/block-tile'
import { useDeployedWorkflowState } from '@/hooks/queries/deployments'
Expand Down Expand Up @@ -150,18 +153,11 @@ interface BlockOutputGroup {
export function WorkflowSidebar(props: WorkflowSidebarProps) {
const open = props.config !== null
return (
<aside
role='dialog'
aria-label='Configure workflow'
className={cn(
'absolute top-0 right-0 bottom-0 z-[var(--z-modal)] flex w-[400px] flex-col overflow-hidden border-[var(--border)] border-l bg-[var(--bg)] transition-transform duration-200 ease-out',
open ? 'translate-x-0 shadow-overlay' : 'translate-x-full'
)}
>
<TableSidebarShell open={open} aria-label='Configure workflow'>
{props.config && (
<WorkflowSidebarBody key={configKey(props.config)} {...props} config={props.config} />
)}
</aside>
</TableSidebarShell>
)
}

Expand Down Expand Up @@ -654,7 +650,7 @@ export function WorkflowSidebarBody({
</TableSidebarHeaderAction>
</TableSidebarHeader>

<div className='flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]'>
<TableSidebarScrollBody>
{/* Single-output mode renames this column directly. */}
{isEditOutputMode && (
<>
Expand Down Expand Up @@ -711,27 +707,18 @@ export function WorkflowSidebarBody({
/>
</div>
{!isEnrichment && (
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
aria-label='Open workflow'
type='button'
variant='ghost'
onClick={() =>
window.open(
`/workspace/${workspaceId}/w/${selectedWorkflowId}`,
'_blank',
'noopener,noreferrer'
)
}
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)]'
>
<SquareArrowUpRight className='size-[12px]' />
</Button>
</Tooltip.Trigger>
<Tooltip.Content side='top'>Open workflow</Tooltip.Content>
</Tooltip.Root>
<WorkflowPreviewAction
aria-label='Open workflow'
onClick={() =>
window.open(
`/workspace/${workspaceId}/w/${selectedWorkflowId}`,
'_blank',
'noopener,noreferrer'
)
}
>
<SquareArrowUpRight className='size-[12px]' />
</WorkflowPreviewAction>
)}
</>
) : (
Expand Down Expand Up @@ -849,7 +836,7 @@ export function WorkflowSidebarBody({
)}
</>
)}
</div>
</TableSidebarScrollBody>

<div className='flex items-center justify-end gap-2 border-[var(--border)] border-t px-2 py-3'>
<Button variant='default' size='sm' onClick={onClose}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ console.log(limits);`
code={getSyncCommand()}
language={LANGUAGE_SYNTAX[language]}
wrapText
className='min-h-0! rounded-sm border border-[var(--border-1)]'
className='min-h-0!'
/>
</div>

Expand Down Expand Up @@ -533,7 +533,7 @@ console.log(limits);`
code={getStreamCommand()}
language={LANGUAGE_SYNTAX[language]}
wrapText
className='min-h-0! rounded-sm border border-[var(--border-1)]'
className='min-h-0!'
/>
</div>

Expand Down Expand Up @@ -579,7 +579,7 @@ console.log(limits);`
code={getAsyncCommand()}
language={LANGUAGE_SYNTAX[language]}
wrapText
className='min-h-0! rounded-sm border border-[var(--border-1)]'
className='min-h-0!'
/>
</div>
)}
Expand Down
Loading
Loading