Skip to content

Commit d147983

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
refactor(ui): use CSS-variable sizing for details panels
1 parent a3bd9d4 commit d147983

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

‎packages/emcn/src/components/details-panel/details-panel.test.tsx‎

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @vitest-environment jsdom */
22
import { act, createRef } from 'react'
3-
import { DetailsPanel } from '@sim/emcn'
3+
import { DetailsPanel, type DetailsPanelProps } from '@sim/emcn'
44
import { createRoot } from 'react-dom/client'
55
import { expect, it, vi } from 'vitest'
66

@@ -11,11 +11,12 @@ it('forwards resize events and retains content and refs while closed', () => {
1111
const root = createRoot(container)
1212
const ref = createRef<HTMLDivElement>()
1313
const resize = vi.fn()
14-
const render = (open: boolean) => (
14+
const render = (open: boolean, width: DetailsPanelProps['width'] = 520) => (
1515
<DetailsPanel
1616
ref={ref}
1717
open={open}
18-
width={520}
18+
width={width}
19+
style={{ width: 1, opacity: 0.9 }}
1920
onResizeStart={resize}
2021
resizeLabel='Resize details'
2122
aria-label='Details'
@@ -27,9 +28,13 @@ it('forwards resize events and retains content and refs while closed', () => {
2728
try {
2829
act(() => root.render(render(true)))
2930
const panel = ref.current!
31+
expect(panel.style.getPropertyValue('--details-panel-width')).toBe('520px')
32+
expect(panel.style.width).toBe('')
33+
expect(panel.style.opacity).toBe('0.9')
3034
expect(panel.hasAttribute('inert')).toBe(false)
3135
const input = panel.querySelector('input')!
32-
const handle = container.querySelector('[role="separator"]')!
36+
const handle = container.querySelector<HTMLDivElement>('[role="separator"]')!
37+
expect(handle.style.getPropertyValue('--details-panel-width')).toBe('520px')
3338
expect(handle.getAttribute('aria-label')).toBe('Resize details')
3439
expect(panel.contains(handle)).toBe(false)
3540
act(() => handle.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: 240 })))
@@ -42,7 +47,9 @@ it('forwards resize events and retains content and refs while closed', () => {
4247
expect(panel.querySelector('input')).toBe(input)
4348
expect(input.value).toBe('Retained query')
4449
expect(container.querySelector('[role="separator"]')).toBeNull()
45-
act(() => root.render(render(true)))
50+
const responsiveWidth = 'clamp(min(320px, 60vw), 520px, 60vw)'
51+
act(() => root.render(render(true, responsiveWidth)))
52+
expect(panel.style.getPropertyValue('--details-panel-width')).toBe(responsiveWidth)
4653
expect(panel.hasAttribute('inert')).toBe(false)
4754
expect(panel.querySelector('input')).toBe(input)
4855
expect(container.querySelector('[role="separator"]')).not.toBeNull()

‎packages/emcn/src/components/details-panel/details-panel.tsx‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@ export interface DetailsPanelProps extends HTMLAttributes<HTMLDivElement> {
2626
export const DetailsPanel = forwardRef<HTMLDivElement, DetailsPanelProps>(
2727
({ open, width, onResizeStart, resizeLabel, className, style, children, ...props }, ref) => {
2828
const cssWidth = typeof width === 'number' ? `${width}px` : width
29+
const widthStyle = { '--details-panel-width': cssWidth } as CSSProperties
30+
const { width: _styleWidth, ...panelStyle } = style ?? {}
2931

3032
return (
3133
<>
3234
{open && (
3335
<div
34-
className='absolute top-0 bottom-0 z-[var(--z-dropdown)] w-[8px] cursor-ew-resize'
35-
style={{ right: `calc(${cssWidth} - 4px)` }}
36+
className='absolute top-0 right-[calc(var(--details-panel-width)-4px)] bottom-0 z-[var(--z-dropdown)] w-[8px] cursor-ew-resize'
37+
style={widthStyle}
3638
onMouseDown={onResizeStart}
3739
role='separator'
3840
aria-label={resizeLabel}
@@ -44,11 +46,11 @@ export const DetailsPanel = forwardRef<HTMLDivElement, DetailsPanelProps>(
4446
ref={ref}
4547
inert={!open || props.inert}
4648
className={cn(
47-
'absolute top-0 right-0 bottom-0 z-[var(--z-dropdown)] overflow-hidden border-l bg-[var(--bg)] shadow-md transition-transform duration-200 ease-out',
49+
'absolute top-0 right-0 bottom-0 z-[var(--z-dropdown)] w-[var(--details-panel-width)] overflow-hidden border-l bg-[var(--bg)] shadow-md transition-transform duration-200 ease-out',
4850
open ? 'translate-x-0' : 'translate-x-full',
4951
className
5052
)}
51-
style={{ ...style, width }}
53+
style={{ ...panelStyle, ...widthStyle }}
5254
>
5355
{children}
5456
</div>

0 commit comments

Comments
 (0)