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
4 changes: 4 additions & 0 deletions .claude/rules/emcn-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@ geometry only; colour, radius and SVG stroke continue to come from the selected
Use `shape='round'` for circular actions, or omit it to retain the current radius.
`size='inline'` is a 20px-high action with caption typography and compact horizontal
padding. Prefer these supported props to size, padding and radius overrides.

### Chip sizing and centered actions

`Chip`, `ChipLink`, and `ChipInput` retain their default 30px height. Use `size="lg"` for the existing auth-scale 36px controls; the larger size follows the root font size. `Chip` and `ChipLink` accept `align="center"` to center their icon/label group, including full-width form actions. Long labels still shrink and retain their overflow treatment. Avoid descendant flex overrides to center chip labels. The default geometry exports remain unchanged for static consumers.
4 changes: 4 additions & 0 deletions .cursor/rules/emcn-components.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@ geometry only; colour, radius and SVG stroke continue to come from the selected
Use `shape='round'` for circular actions, or omit it to retain the current radius.
`size='inline'` is a 20px-high action with caption typography and compact horizontal
padding. Prefer these supported props to size, padding and radius overrides.

### Chip sizing and centered actions

`Chip`, `ChipLink`, and `ChipInput` retain their default 30px height. Use `size="lg"` for the existing auth-scale 36px controls; the larger size follows the root font size. `Chip` and `ChipLink` accept `align="center"` to center their icon/label group, including full-width form actions. Long labels still shrink and retain their overflow treatment. Avoid descendant flex overrides to center chip labels. The default geometry exports remain unchanged for static consumers.
17 changes: 4 additions & 13 deletions apps/sim/app/(auth)/components/auth-input.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
'use client'

import * as React from 'react'
import { ChipInput, type ChipInputProps, cn } from '@sim/emcn'
import { AUTH_CONTROL_HEIGHT } from '@/app/(auth)/components/constants'
import { ChipInput, type ChipInputProps } from '@sim/emcn'

/**
* The auth text field — a {@link ChipInput} raised to the auth control height
* ({@link AUTH_CONTROL_HEIGHT}) so every labeled field on the auth and invite
* surfaces shares one slightly-taller geometry. All chip props pass through
* (`error`, `endAdornment`, `icon`, …); only the height is owned here, and a
* caller's `className` (layout only) still composes on top.
*/
export const AuthInput = React.forwardRef<HTMLInputElement, ChipInputProps>(
({ className, ...props }, ref) => (
<ChipInput ref={ref} className={cn(AUTH_CONTROL_HEIGHT, className)} {...props} />
)
/** Auth fields use the larger shared chip size while retaining native input props and refs. */
export const AuthInput = React.forwardRef<HTMLInputElement, Omit<ChipInputProps, 'size'>>(
(props, ref) => <ChipInput {...props} ref={ref} size='lg' />
)

AuthInput.displayName = 'AuthInput'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { Button, StatusPageContent } from '@sim/emcn'
import { Chip, StatusPageContent } from '@sim/emcn'
import { useRouter } from 'next/navigation'
import { APP_ENTRY_PATH } from '@/lib/navigation/paths'

Expand All @@ -14,14 +14,15 @@ export function ChatErrorState({ error }: ChatErrorStateProps) {
return (
<div className='flex flex-1 items-center justify-center px-4 py-16 text-center'>
<StatusPageContent title='Chat Unavailable' description={error}>
<Button
type='button'
<Chip
variant='primary'
className='h-[32px] w-full gap-2 px-2.5 text-sm'
onClick={() => router.push(APP_ENTRY_PATH)}
fullWidth
type='button'
align='center'
>
Open Sim
</Button>
</Chip>
</StatusPageContent>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,17 +781,18 @@ export default function ResumeExecutionPage({
</div>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
<Chip
variant='outline'
size='sm'
type='button'
onClick={handleRefreshExecution}
disabled={refreshingExecution}
className='gap-1.5 px-2.5'
leftAdornment={
<RefreshCw className={cn('size-[14px]', refreshingExecution && 'animate-spin')} />
}
aria-label='Refresh execution details'
>
<RefreshCw className={cn('size-[14px]', refreshingExecution && 'animate-spin')} />
Refresh
</Button>
</Chip>
</Tooltip.Trigger>
<Tooltip.Content>Refresh</Tooltip.Content>
</Tooltip.Root>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type LandingCtaSize = 'compact' | 'default' | 'display'

export type LandingCtaSection = PostHogEventMap['landing_cta_clicked']['section']

interface LandingCtaLinkProps extends Omit<ChipLinkProps, 'variant'> {
interface LandingCtaLinkProps extends Omit<ChipLinkProps, 'variant' | 'size'> {
size?: LandingCtaSize
variant?: 'primary' | 'outline'
/** Adds the animated chevron used by demo actions. */
Expand Down
10 changes: 3 additions & 7 deletions apps/sim/app/workspace/[workspaceId]/files/files.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import {
Button,
Chip,
ChipCombobox,
ChipConfirmModal,
Columns2,
Expand Down Expand Up @@ -2057,13 +2057,9 @@ function FilesContent() {
</div>
)}
{hasActiveFilters && (
<Button
variant='ghost'
onClick={clearFileFilters}
className='h-[32px] w-full text-caption hover-hover:bg-[var(--surface-active)]'
>
<Chip fullWidth onClick={clearFileFilters} align='center'>
Clear all filters
</Button>
</Chip>
)}
</div>
)
Expand Down
9 changes: 3 additions & 6 deletions apps/sim/app/workspace/[workspaceId]/logs/logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import {
Button,
Calendar,
Chip,
ChipCombobox,
type ComboboxOption,
cn,
Expand Down Expand Up @@ -1584,13 +1585,9 @@ function LogsFilterPanel({ searchQuery, onSearchQueryChange }: LogsFilterPanelPr
</div>

{filtersActive && (
<Button
variant='active'
onClick={handleClearFilters}
className='h-[32px] w-full rounded-md'
>
<Chip variant='border-shadow' fullWidth onClick={handleClearFilters} align='center'>
Clear All Filters
</Button>
</Chip>
)}
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,8 @@ export function Admin() {
Page {currentPage} of {totalPages} ({usersData.total} users)
</span>
<div className='flex gap-1'>
<Button
variant='active'
className='h-[28px] text-caption'
<Chip
variant='border-shadow'
onClick={() =>
setAdminParams((prev) => ({
offset: Math.max(0, prev.offset - PAGE_SIZE),
Expand All @@ -454,17 +453,16 @@ export function Admin() {
disabled={usersOffset === 0 || usersLoading}
>
Previous
</Button>
<Button
variant='active'
className='h-[28px] text-caption'
</Chip>
<Chip
variant='border-shadow'
onClick={() =>
setAdminParams((prev) => ({ offset: prev.offset + PAGE_SIZE }))
}
disabled={usersOffset + PAGE_SIZE >= (usersData?.total ?? 0) || usersLoading}
>
Next
</Button>
</Chip>
</div>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { useCallback, useMemo, useState } from 'react'
import {
Badge,
Button,
Chip,
ChipCopyInput,
ChipInput,
ChipModalTabs,
Expand Down Expand Up @@ -434,14 +434,13 @@ function LicensesTab({ environment }: { environment: MothershipEnv }) {
className='w-[160px]'
/>
</div>
<Button
<Chip
variant='primary'
className='h-[32px]'
onClick={handleGenerate}
disabled={generateLicense.isPending || !newName.trim()}
>
{generateLicense.isPending ? 'Generating...' : 'Generate'}
</Button>
</Chip>
</div>

{generatedKey && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const VIEWER_MASK_LENGTH = 10

type SecretValueFieldProps = Omit<
ComponentProps<'input'>,
'type' | 'value' | 'onChange' | 'readOnly' | 'style'
'type' | 'value' | 'onChange' | 'readOnly' | 'style' | 'size'
> & {
/** The chip owns field styling; callers use className for layout. */
style?: never
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { Button, Combobox, Input } from '@sim/emcn'
import { Chip, ChipCombobox, ChipInput } from '@sim/emcn'
import type { WorkflowSearchReplacementOption } from '@/lib/workflows/search-replace/types'

interface ReplacementControlsProps {
Expand Down Expand Up @@ -33,7 +33,7 @@ export function ReplacementControls({
return (
<div className='space-y-2'>
{usesResourceReplacement ? (
<Combobox
<ChipCombobox
options={compatibleResourceOptions.map((option) => ({
label: option.label,
value: option.value,
Expand All @@ -47,7 +47,7 @@ export function ReplacementControls({
disabled={disabled || compatibleResourceOptions.length === 0}
/>
) : (
<Input
<ChipInput
value={replacement}
placeholder='Replace'
disabled={disabled}
Expand All @@ -60,22 +60,22 @@ export function ReplacementControls({
{eligibleCount} replaceable match{eligibleCount === 1 ? '' : 'es'}
</span>
<div className='flex gap-1.5'>
<Button
className='h-8 text-xs'
variant='default'
<Chip
type='button'
variant='outline'
disabled={disabled || isApplying || !canReplaceActive}
onClick={onReplaceActive}
>
Replace
</Button>
<Button
className='h-8 text-xs'
variant='active'
</Chip>
<Chip
type='button'
active
disabled={disabled || isApplying || !canReplaceAll}
onClick={onReplaceAll}
>
{isApplying ? 'Replacing...' : 'Replace All'}
</Button>
</Chip>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { type RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Button, cn, Input, toast } from '@sim/emcn'
import { Button, ChipInput, cn, toast } from '@sim/emcn'
import { ChevronDown, ChevronRight, ChevronUp, X } from '@sim/emcn/icons'
import { useParams } from 'next/navigation'
import { useShallow } from 'zustand/react/shallow'
Expand Down Expand Up @@ -575,12 +575,7 @@ function WorkflowSearchReplacePanel({ focusRef }: WorkflowSearchReplacePanelProp
onMouseDown={(event) => event.stopPropagation()}
>
<span className='text-[var(--text-muted)] text-xs'>{matchCountLabel}</span>
<Button
aria-label='Close search'
variant='ghost'
className='size-[26px] p-0'
onClick={close}
>
<Button aria-label='Close search' variant='ghost' iconSize='regular' onClick={close}>
<X className='size-[14px]' />
</Button>
</div>
Expand All @@ -589,7 +584,7 @@ function WorkflowSearchReplacePanel({ focusRef }: WorkflowSearchReplacePanelProp
<div className='grid grid-cols-[2rem_minmax(0,1fr)_2rem_2rem] items-start gap-1.5'>
<Button
variant='ghost'
className='size-8 p-0'
iconSize='roomy'
aria-label={isReplaceExpanded ? 'Hide replace controls' : 'Show replace controls'}
onClick={() => setIsReplaceExpanded((expanded) => !expanded)}
>
Expand All @@ -600,7 +595,7 @@ function WorkflowSearchReplacePanel({ focusRef }: WorkflowSearchReplacePanelProp
)}
/>
</Button>
<Input
<ChipInput
ref={searchInputRef}
value={query}
placeholder='Search'
Expand All @@ -614,7 +609,7 @@ function WorkflowSearchReplacePanel({ focusRef }: WorkflowSearchReplacePanelProp
<Button
aria-label='Previous match'
variant='ghost'
className='size-8 p-0'
iconSize='roomy'
disabled={hydratedMatches.length === 0}
onClick={() => handleMoveActiveMatch(-1)}
>
Expand All @@ -623,7 +618,7 @@ function WorkflowSearchReplacePanel({ focusRef }: WorkflowSearchReplacePanelProp
<Button
aria-label='Next match'
variant='ghost'
className='size-8 p-0'
iconSize='roomy'
disabled={hydratedMatches.length === 0}
onClick={() => handleMoveActiveMatch(1)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@

import type React from 'react'
import { useEffect, useMemo, useRef, useState } from 'react'
import { Button, cn, OverflowText, Tooltip } from '@sim/emcn'
import {
Chip,
chipBorderShadowRing,
chipContentLabelClass,
chipGeometryClass,
cn,
OverflowText,
Tooltip,
} from '@sim/emcn'
import { ArrowLeft } from '@sim/emcn/icons'
import { redactApiKeys } from '@/lib/core/security/redaction'
import { PreviewEditor } from '@/app/workspace/[workspaceId]/w/components/preview/components/preview-editor'
Expand Down Expand Up @@ -295,23 +303,21 @@ export function Preview({
<div className='absolute top-3 left-[12px] z-20 flex items-center gap-1.5'>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<Button
variant='ghost'
onClick={handleGoBack}
className='flex h-[28px] gap-[5px] rounded-md border border-[var(--border)] bg-[var(--surface-2)] px-2.5 shadow-xs hover-hover:bg-[var(--surface-4)]'
>
<ArrowLeft className='size-[12px]' />
<span className='text-caption'>Back</span>
</Button>
<Chip variant='border-shadow' leftIcon={ArrowLeft} onClick={handleGoBack}>
Back
</Chip>
</Tooltip.Trigger>
<Tooltip.Content side='bottom'>Go back to parent workflow</Tooltip.Content>
</Tooltip.Root>
{currentWorkflowName && (
<div className='flex h-[28px] max-w-[200px] items-center rounded-md border border-[var(--border)] bg-[var(--surface-2)] px-2.5 shadow-xs'>
<OverflowText
label={currentWorkflowName}
className='text-[var(--text-secondary)] text-caption'
/>
<div
className={cn(
chipGeometryClass,
chipBorderShadowRing,
'inline-flex max-w-[200px] bg-[var(--surface-2)]'
)}
>
<OverflowText label={currentWorkflowName} className={chipContentLabelClass} />
</div>
)}
</div>
Expand Down
Loading
Loading