Skip to content
Open
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 @@ -72,7 +72,8 @@ export function ChatMessageContainer({
<Button
onClick={scrollToBottom}
size='sm'
className='gap-1 rounded-full px-3 shadow-medium'
shape='round'
className='gap-1 px-3 shadow-medium'
>
<ArrowDown className='size-3.5' />
<span className='sr-only'>Scroll to bottom</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function ChatFileDownload({ file }: ChatFileDownloadProps) {
variant='default'
onClick={handleDownload}
disabled={isDownloading}
className='group flex h-auto w-[200px] gap-2 rounded-lg px-3 py-2'
className='group flex w-[200px] gap-2 rounded-lg px-3 py-2'
>
<div className='flex size-8 shrink-0 items-center justify-center'>{renderIcon()}</div>
<div className='min-w-0 flex-1 text-left'>
Expand Down
4 changes: 2 additions & 2 deletions apps/sim/app/workspace/[workspaceId]/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -775,11 +775,11 @@ function HomeContent({ chatId, userName, userId }: HomeProps) {
className={cn('z-30', RESOURCE_HEADER_CLASSES.overlay, RESOURCE_HEADER_CLASSES.endPosition)}
>
<Button
variant='ghost'
variant='quiet'
size={null}
type='button'
onClick={isResourceCollapsed ? expandResource : collapseResource}
className="after:-translate-x-1/2 after:-translate-y-1/2 relative size-[var(--resource-header-toggle-size)] rounded-[8px] after:absolute after:top-1/2 after:left-1/2 after:size-[var(--resource-header-toggle-hit-size)] after:content-[''] hover-hover:bg-[var(--surface-active)]"
className="after:-translate-x-1/2 after:-translate-y-1/2 relative size-[var(--resource-header-toggle-size)] rounded-[8px] after:absolute after:top-1/2 after:left-1/2 after:size-[var(--resource-header-toggle-hit-size)] after:content-['']"
aria-label={resourceToggleLabel}
>
<span className='relative'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type ButtonHTMLAttributes, forwardRef, type ReactNode } from 'react'
import { Button, cn } from '@sim/emcn'
import { Button } from '@sim/emcn'

interface TableSidebarHeaderProps {
children: ReactNode
Expand Down Expand Up @@ -28,10 +28,8 @@ export const TableSidebarHeaderAction = forwardRef<
size='sm'
iconSize='regular'
iconPadding='sm'
className={cn(
'focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]',
className
)}
focusRing='muted'
className={className}
/>
))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type ButtonHTMLAttributes, forwardRef, type ReactNode } from 'react'
import { cn } from '@sim/emcn'
import { cn, mutedFocusRingClass } from '@sim/emcn'

interface SidebarRowActionsProps {
children: ReactNode
Expand Down Expand Up @@ -62,7 +62,7 @@ export const SidebarRowAction = forwardRef<HTMLButtonElement, SidebarRowActionPr
{...props}
ref={ref}
type='button'
className='flex size-[18px] items-center justify-center rounded-sm focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]'
className={cn('flex size-[18px] items-center justify-center rounded-sm', mutedFocusRingClass)}
/>
)
)
Expand Down
20 changes: 20 additions & 0 deletions packages/emcn/src/components/button/button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@ describe('Button shared action geometry', () => {
expect(baseOnly).not.toContain('sm:size')
})

it('offers the existing muted keyboard ring without changing the default', () => {
const before = renderToStaticMarkup(
<Button
variant='ghost'
size='sm'
className='focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]'
>
Open
</Button>
)
const after = renderToStaticMarkup(
<Button variant='ghost' size='sm' focusRing='muted'>
Open
</Button>
)
expect(normalizeClasses(after)).toBe(normalizeClasses(before))
expect(after).not.toContain('focusRing=')
expect(renderToStaticMarkup(<Button>Open</Button>)).not.toContain('focus-visible:ring-2')
})

it('forwards refs and native focus, submission and disabled behavior with responsive sizing', () => {
const container = document.createElement('div')
document.body.appendChild(container)
Expand Down
7 changes: 6 additions & 1 deletion packages/emcn/src/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type ButtonHTMLAttributes, forwardRef } from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '../../lib/cn'
import { mutedFocusRingClass } from '../../lib/focus-ring'

/**
* `size='icon'` is the square 20px icon-only button — a chip field's trailing
Expand Down Expand Up @@ -61,6 +62,9 @@ const buttonVariants = cva(
shape: {
round: 'rounded-full',
},
focusRing: {
muted: mutedFocusRingClass,
},
iconPadding: {
sm: 'p-1',
md: 'p-1.5',
Expand Down Expand Up @@ -118,7 +122,7 @@ export interface ButtonProps
}

const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, iconSize, iconPadding, shape, ...props }, ref) => {
({ className, variant, size, iconSize, iconPadding, shape, focusRing, ...props }, ref) => {
const baseIconSize = typeof iconSize === 'object' ? iconSize?.base : iconSize
const smIconSize = typeof iconSize === 'object' ? iconSize?.sm : undefined
return (
Expand All @@ -131,6 +135,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
iconSize: baseIconSize,
iconPadding,
shape,
focusRing,
}),
smIconSize && responsiveIconSizes[smIconSize],
className
Expand Down
3 changes: 2 additions & 1 deletion packages/emcn/src/components/field-divider/field-divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ function FieldDisclosure({ expanded, children, ...props }: FieldDisclosureProps)
type='button'
variant='ghost'
size={null}
focusRing='muted'
aria-expanded={expanded}
className='gap-1.5 whitespace-nowrap p-0 text-small focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]'
className='gap-1.5 whitespace-nowrap p-0 text-small'
>
{children}
<ChevronDown
Expand Down
8 changes: 7 additions & 1 deletion packages/emcn/src/components/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from 'react'
import * as SliderPrimitive from '@radix-ui/react-slider'
import { cn } from '../../lib/cn'
import { mutedFocusRingClass } from '../../lib/focus-ring'

interface SliderProps extends React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root> {}

Expand Down Expand Up @@ -30,7 +31,12 @@ const Slider = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, S
<SliderPrimitive.Track className='relative h-[6px] w-full grow overflow-hidden rounded-[20px] bg-[var(--border-1)] transition-colors'>
<SliderPrimitive.Range className='absolute h-full bg-[var(--text-primary)]' />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className='relative block size-[14px] cursor-pointer rounded-full bg-[var(--text-primary)] shadow-xs transition-colors before:absolute before:inset-[-15px] before:content-[""] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]' />
<SliderPrimitive.Thumb
className={cn(
'relative block size-[14px] cursor-pointer rounded-full bg-[var(--text-primary)] shadow-xs transition-colors before:absolute before:inset-[-15px] before:content-[""]',
mutedFocusRingClass
)}
/>
</SliderPrimitive.Root>
)
)
Expand Down
4 changes: 3 additions & 1 deletion packages/emcn/src/components/switch/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as React from 'react'
import * as SwitchPrimitives from '@radix-ui/react-switch'
import { cn } from '../../lib/cn'
import { mutedFocusRingClass } from '../../lib/focus-ring'

/**
* Switch component styled to match Sim's design system.
Expand All @@ -16,7 +17,8 @@ const Switch = React.memo(
<SwitchPrimitives.Root
disabled={disabled}
className={cn(
'peer relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full bg-[var(--border-1)] transition-colors before:absolute before:inset-[-12px] before:content-[""] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)] data-[disabled]:cursor-not-allowed data-[state=checked]:bg-[var(--text-primary)] data-[disabled]:opacity-50',
'peer relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full bg-[var(--border-1)] transition-colors before:absolute before:inset-[-12px] before:content-[""] data-[disabled]:cursor-not-allowed data-[state=checked]:bg-[var(--text-primary)] data-[disabled]:opacity-50',
mutedFocusRingClass,
className
)}
{...props}
Expand Down
1 change: 1 addition & 0 deletions packages/emcn/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ export { usePrefersReducedMotion } from './hooks/use-prefers-reduced-motion'
export { useScrollEdges } from './hooks/use-scroll-edges'
export * from './icons'
export { cn } from './lib/cn'
export { mutedFocusRingClass } from './lib/focus-ring'
export { handleKeyboardActivation, isKeyboardActivation } from './lib/keyboard'
export { bindPreviewHorizontalWheel, bindPreviewWheelZoom } from './lib/preview-wheel-zoom'
3 changes: 3 additions & 0 deletions packages/emcn/src/lib/focus-ring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/** Opt-in ring for controls on `--surface-2`; ordinary Button focus remains unchanged. */
export const mutedFocusRingClass =
Comment thread
BillLeoutsakosvl346 marked this conversation as resolved.
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[color-mix(in_srgb,var(--text-muted)_30%,transparent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-2)]'
Loading