Skip to content

Commit 8839be4

Browse files
authored
Dynamic Json component sizing (#312)
1 parent 4fce5a3 commit 8839be4

File tree

3 files changed

+106
-8
lines changed

3 files changed

+106
-8
lines changed

src/components/Json/Json.stories.tsx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,67 @@ export const Objects: Story = {
7171
},
7272
render,
7373
}
74+
75+
export const OpenAICompletions: Story = {
76+
args: {
77+
json: {
78+
model: 'gpt-4',
79+
messages: [
80+
{
81+
role: 'system',
82+
content: 'You are a helpful assistant that explains complex concepts clearly.',
83+
},
84+
{
85+
role: 'user',
86+
content: 'Can you explain how machine learning works?',
87+
},
88+
{
89+
role: 'assistant',
90+
content: 'Machine learning is a method of data analysis that automates analytical model building. It uses algorithms that iteratively learn from data, allowing computers to find hidden insights without being explicitly programmed where to look.',
91+
},
92+
{
93+
role: 'user',
94+
content: 'What are the main types of machine learning?',
95+
},
96+
],
97+
temperature: 0.7,
98+
max_tokens: 2048,
99+
top_p: 1.0,
100+
frequency_penalty: 0.0,
101+
presence_penalty: 0.0,
102+
},
103+
},
104+
render,
105+
}
106+
107+
export const MessagesList: Story = {
108+
args: {
109+
json: [
110+
{
111+
role: 'user',
112+
content: 'Hello, how are you today?',
113+
},
114+
{
115+
role: 'assistant',
116+
content: 'I\'m doing well, thank you for asking! How can I help you today?',
117+
},
118+
{
119+
role: 'user',
120+
content: 'I need help with debugging a JavaScript function that\'s not working correctly.',
121+
},
122+
{
123+
role: 'assistant',
124+
content: 'I\'d be happy to help you debug your JavaScript function. Could you please share the code that\'s causing issues?',
125+
},
126+
{
127+
role: 'user',
128+
content: 'Sure, here it is: function calculate(a, b) { return a + b * c; }',
129+
},
130+
{
131+
role: 'assistant',
132+
content: 'I can see the issue! The variable `c` is not defined in your function. You\'re using `c` but it\'s not a parameter or declared variable. You probably want either `function calculate(a, b, c)` or just `return a + b` depending on your intended calculation.',
133+
},
134+
],
135+
},
136+
render,
137+
}

src/components/Json/Json.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ReactNode, useState } from 'react'
22
import styles from './Json.module.css'
33
import { isPrimitive, shouldObjectCollapse } from './helpers.js'
44
import { cn } from '../../lib'
5+
import { useWidth } from './useWidth.js'
56

67
interface JsonProps {
78
json: unknown
@@ -45,9 +46,8 @@ function JsonContent({ json, label }: JsonProps): ReactNode {
4546
}
4647

4748
function CollapsedArray({ array }: {array: unknown[]}): ReactNode {
48-
// the character count is approximate, but it should be enough
49-
// to avoid showing too many entries
50-
const maxCharacterCount = 40
49+
const { elementRef, width } = useWidth<HTMLSpanElement>()
50+
const maxCharacterCount = Math.max(20, Math.floor(width / 8))
5151
const separator = ', '
5252

5353
const children: ReactNode[] = []
@@ -78,7 +78,7 @@ function CollapsedArray({ array }: {array: unknown[]}): ReactNode {
7878
return (
7979
<>
8080
<span className={styles.array}>{'['}</span>
81-
<span className={styles.array}>{children}</span>
81+
<span ref={elementRef} className={styles.array}>{children}</span>
8282
<span className={styles.array}>{']'}</span>
8383
{suffix && <span className={styles.comment}>{suffix}</span>}
8484
</>
@@ -109,9 +109,8 @@ function JsonArray({ array, label }: { array: unknown[], label?: string }): Reac
109109
}
110110

111111
function CollapsedObject({ obj }: {obj: object}): ReactNode {
112-
// the character count is approximate, but it should be enough
113-
// to avoid showing too many entries
114-
const maxCharacterCount = 40
112+
const { elementRef, width } = useWidth<HTMLSpanElement>()
113+
const maxCharacterCount = Math.max(20, Math.floor(width / 8))
115114
const separator = ', '
116115
const kvSeparator = ': '
117116

@@ -144,7 +143,7 @@ function CollapsedObject({ obj }: {obj: object}): ReactNode {
144143
return (
145144
<>
146145
<span className={styles.object}>{'{'}</span>
147-
<span className={styles.object}>{children}</span>
146+
<span ref={elementRef} className={styles.object}>{children}</span>
148147
<span className={styles.object}>{'}'}</span>
149148
{suffix && <span className={styles.comment}>{suffix}</span>}
150149
</>

src/components/Json/useWidth.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { useLayoutEffect, useRef, useState } from 'react'
2+
3+
const defaultWidth = 320
4+
5+
export function useWidth<T extends HTMLElement = HTMLElement>() {
6+
const [width, setWidth] = useState(defaultWidth)
7+
const elementRef = useRef<T>(null)
8+
9+
useLayoutEffect(() => {
10+
function updateWidth() {
11+
if (elementRef.current) {
12+
// Get the parent container width instead of the span itself
13+
const container = elementRef.current.parentElement
14+
const containerWidth = container ? container.clientWidth : elementRef.current.clientWidth
15+
setWidth(containerWidth || defaultWidth)
16+
}
17+
}
18+
19+
updateWidth()
20+
21+
// Only use ResizeObserver if it's available
22+
if (typeof ResizeObserver !== 'undefined') {
23+
const resizeObserver = new ResizeObserver(updateWidth)
24+
if (elementRef.current?.parentElement) {
25+
resizeObserver.observe(elementRef.current.parentElement)
26+
}
27+
28+
return () => {
29+
resizeObserver.disconnect()
30+
}
31+
}
32+
}, [])
33+
34+
return { elementRef, width }
35+
}

0 commit comments

Comments
 (0)