@samitouri / QOS-React / commits / 8e3db095aa

[DevTools] Make a non-editable name of KeyValue clickable (#34095)

This has been bothering me. You can click the arrow and the value to expand/collapse a KeyValue row but not the name. When the name is not editable it should be clickable. Such as when inspecting a Promise value.

Sebastian Markbåge committed Aug 4, 2025 at 09:27 UTC 8e3db095aa99ffdf8ae2bc3944d1dffcebefbbee
1 file changed +32 -19
packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js
+32 -19
@@ -210,6 +210,13 @@ export default function KeyValue({
210 canRenameTheCurrentPath = canRenamePathsAtDepth(depth);
211 }
212
213 + const hasChildren =
214 + typeof value === 'object' &&
215 + value !== null &&
216 + (canEditValues ||
217 + (isArray(value) && value.length > 0) ||
218 + Object.entries(value).length > 0);
219 +
220 let renderedName;
221 if (isDirectChildOfAnArray) {
222 if (canDeletePaths) {
@@ -218,27 +225,37 @@ export default function KeyValue({
225 );
226 } else {
227 renderedName = (
221 - <span className={styles.Name}>
228 + <span
229 + className={styles.Name}
230 + onClick={isInspectable || hasChildren ? toggleIsOpen : null}>
231 {name}
232 {!!hookName && <span className={styles.HookName}>({hookName})</span>}
233 + <span className={styles.AfterName}>:</span>
234 </span>
235 );
236 }
237 } else if (canRenameTheCurrentPath) {
238 renderedName = (
229 - <EditableName
230 - allowEmpty={canDeletePaths}
231 - className={styles.EditableName}
232 - initialValue={name}
233 - overrideName={renamePath}
234 - path={path}
235 - />
239 + <>
240 + <EditableName
241 + allowEmpty={canDeletePaths}
242 + className={styles.EditableName}
243 + initialValue={name}
244 + overrideName={renamePath}
245 + path={path}
246 + />
247 + <span className={styles.AfterName}>:</span>
248 + </>
249 );
250 } else {
251 renderedName = (
239 - <span className={styles.Name} data-testname="NonEditableName">
252 + <span
253 + className={styles.Name}
254 + data-testname="NonEditableName"
255 + onClick={isInspectable || hasChildren ? toggleIsOpen : null}>
256 {name}
257 {!!hookName && <span className={styles.HookName}>({hookName})</span>}
258 + <span className={styles.AfterName}>:</span>
259 </span>
260 );
261 }
@@ -286,7 +303,6 @@ export default function KeyValue({
303 style={style}>
304 <div className={styles.ExpandCollapseToggleSpacer} />
305 {renderedName}
289 - <div className={styles.AfterName}>:</div>
306 {canEditValues ? (
307 <EditableValue
308 overrideValue={overrideValue}
@@ -328,7 +344,6 @@ export default function KeyValue({
344 style={style}>
345 <div className={styles.ExpandCollapseToggleSpacer} />
346 {renderedName}
331 - <div className={styles.AfterName}>:</div>
347 <span
348 className={styles.Link}
349 onClick={() => {
@@ -365,7 +380,6 @@ export default function KeyValue({
380 <div className={styles.ExpandCollapseToggleSpacer} />
381 )}
382 {renderedName}
368 - <div className={styles.AfterName}>:</div>
383 <span
384 className={styles.Value}
385 onClick={isInspectable ? toggleIsOpen : undefined}>
@@ -388,7 +402,6 @@ export default function KeyValue({
402 }
403 } else {
404 if (isArray(value)) {
391 - const hasChildren = value.length > 0 || canEditValues;
405 const displayName = getMetaValueLabel(value);
406
407 children = value.map((innerValue, index) => (
@@ -449,12 +462,11 @@ export default function KeyValue({
462 ref={contextMenuTriggerRef}
463 style={style}>
464 {hasChildren ? (
452 - <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />
465 + <ExpandCollapseToggle isOpen={isOpen} setIsOpen={toggleIsOpen} />
466 ) : (
467 <div className={styles.ExpandCollapseToggleSpacer} />
468 )}
469 {renderedName}
457 - <div className={styles.AfterName}>:</div>
470 <span
471 className={styles.Value}
472 onClick={hasChildren ? toggleIsOpen : undefined}>
@@ -472,7 +484,6 @@ export default function KeyValue({
484 entries.sort(alphaSortEntries);
485 }
486
475 - const hasChildren = entries.length > 0 || canEditValues;
487 const displayName = getMetaValueLabel(value);
488
489 children = entries.map(([key, keyValue]): ReactElement<any> => (
@@ -531,12 +542,11 @@ export default function KeyValue({
542 ref={contextMenuTriggerRef}
543 style={style}>
544 {hasChildren ? (
534 - <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />
545 + <ExpandCollapseToggle isOpen={isOpen} setIsOpen={toggleIsOpen} />
546 ) : (
547 <div className={styles.ExpandCollapseToggleSpacer} />
548 )}
549 {renderedName}
539 - <div className={styles.AfterName}>:</div>
550 <span
551 className={styles.Value}
552 onClick={hasChildren ? toggleIsOpen : undefined}>
@@ -567,7 +577,10 @@ function DeleteToggle({deletePath, name, path}) {
577 title="Delete entry">
578 <ButtonIcon type="delete" />
579 </Button>
570 - <span className={styles.Name}>{name}</span>
580 + <span className={styles.Name}>
581 + {name}
582 + <span className={styles.AfterName}>:</span>
583 + </span>
584 </>
585 );
586 }