@samitouri / QOS-React-2 / commits / 4f254c0a05

Refactored KeyValue toggle so columns with toggles align better below those without

Brian Vaughn committed Apr 10, 2019 at 11:44 UTC 4f254c0a05cc6eba1aa8828736ef3617fc54017a
2 files changed +51 -44
src/devtools/views/Components/KeyValue.css
+2 -1
@@ -5,6 +5,7 @@
5 .Name {
6 color: var(--color-dim);
7 flex: 0 0 auto;
8 + user-select: none;
9 }
10 .EditableName {
11 color: var(--color-attribute-name);
@@ -27,7 +28,7 @@
28 font-style: italic;
29 }
30
30 -.Opener {
31 +.ExpandCollapseToggle {
32 display: inline-flex;
33 width: 1rem;
34 height: 1rem;
src/devtools/views/Components/KeyValue.js
+49 -43
@@ -1,6 +1,6 @@
1 // @flow
2
3 -import React, { useState } from 'react';
3 +import React, { useCallback, useState } from 'react';
4 import type { Element } from 'react';
5 import EditableValue from './EditableValue';
6 import Button from '../Button';
@@ -26,11 +26,7 @@ export default function KeyValue({
26 path = [],
27 value,
28 }: KeyValueProps) {
29 - const [open, setOpen] = useState(false);
30 -
31 - const handleToggle = () => {
32 - setOpen(prevOpen => !prevOpen);
33 - };
29 + const [isOpen, setIsOpen] = useState<boolean>(true);
30
31 const dataType = typeof value;
32 const isSimpleType =
@@ -39,7 +35,9 @@ export default function KeyValue({
35 dataType === 'boolean' ||
36 value == null;
37
42 - const paddingLeft = `${depth * 0.75}rem`;
38 + const style = {
39 + paddingLeft: `${(depth - 1) * 0.75}rem`,
40 + };
41
42 let children = null;
43 if (isSimpleType) {
@@ -58,7 +56,8 @@ export default function KeyValue({
56 typeof overrideValueFn === 'function' ? styles.EditableName : styles.Name;
57
58 children = (
61 - <div key="root" className={styles.Item} style={{ paddingLeft }}>
59 + <div key="root" className={styles.Item} style={style}>
60 + <div className={styles.ExpandCollapseToggle} />
61 <span className={nameClassName}>{name}</span>
62 {typeof overrideValueFn === 'function' ? (
63 <EditableValue
@@ -75,26 +74,17 @@ export default function KeyValue({
74 } else if (value.hasOwnProperty(meta.type)) {
75 // TODO Is this type even necessary? Can we just drop it?
76 children = (
78 - <div key="root" className={styles.Item} style={{ paddingLeft }}>
77 + <div key="root" className={styles.Item} style={style}>
78 + <div className={styles.ExpandCollapseToggle} />
79 <span className={styles.Name}>{name}</span>
80 <span className={styles.Value}>{getMetaValueLabel(value)}</span>
81 </div>
82 );
83 } else {
84 - const opener = (
85 - <Button
86 - className={styles.Opener}
87 - onClick={handleToggle}
88 - title={`${open ? 'Collapse' : 'Expand'} prop value`}
89 - >
90 - <ButtonIcon type={open ? 'expanded' : 'collapsed'} />
91 - </Button>
92 - );
93 -
84 if (Array.isArray(value)) {
95 - const showOpener = value.length > 0;
85 + const hasChildren = value.length > 0;
86
97 - children = open
87 + children = isOpen
88 ? value.map((innerValue, index) => (
89 <KeyValue
90 key={index}
@@ -107,24 +97,20 @@ export default function KeyValue({
97 ))
98 : [];
99 children.unshift(
110 - <div
111 - key={`${depth}-root`}
112 - className={styles.Item}
113 - style={{
114 - paddingLeft: showOpener
115 - ? `calc(${paddingLeft} - 1rem)`
116 - : paddingLeft,
117 - }}
118 - >
119 - {showOpener && opener}
100 + <div key={`${depth}-root`} className={styles.Item} style={style}>
101 + {hasChildren ? (
102 + <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />
103 + ) : (
104 + <div className={styles.ExpandCollapseToggle} />
105 + )}
106 <span className={styles.Name}>{name}</span>
107 <span>Array</span>
108 </div>
109 );
110 } else {
125 - const showOpener = Object.entries(value).length > 0;
111 + const hasChildren = Object.entries(value).length > 0;
112
127 - children = open
113 + children = isOpen
114 ? Object.entries(value).map<Element<any>>(([name, value]) => (
115 <KeyValue
116 key={name}
@@ -137,16 +123,12 @@ export default function KeyValue({
123 ))
124 : [];
125 children.unshift(
140 - <div
141 - key={`${depth}-root`}
142 - className={styles.Item}
143 - style={{
144 - paddingLeft: showOpener
145 - ? `calc(${paddingLeft} - 1rem)`
146 - : paddingLeft,
147 - }}
148 - >
149 - {showOpener && opener}
126 + <div key={`${depth}-root`} className={styles.Item} style={style}>
127 + {hasChildren ? (
128 + <ExpandCollapseToggle isOpen={isOpen} setIsOpen={setIsOpen} />
129 + ) : (
130 + <div className={styles.ExpandCollapseToggle} />
131 + )}
132 <span className={styles.Name}>{name}</span>
133 <span>Object</span>
134 </div>
@@ -156,3 +138,27 @@ export default function KeyValue({
138
139 return children;
140 }
141 +
142 +type ExpandCollapseToggleProps = {|
143 + isOpen: boolean,
144 + setIsOpen: Function,
145 +|};
146 +
147 +function ExpandCollapseToggle({
148 + isOpen,
149 + setIsOpen,
150 +}: ExpandCollapseToggleProps) {
151 + const handleClick = useCallback(() => {
152 + setIsOpen(prevIsOpen => !prevIsOpen);
153 + }, [setIsOpen]);
154 +
155 + return (
156 + <Button
157 + className={styles.ExpandCollapseToggle}
158 + onClick={handleClick}
159 + title={`${isOpen ? 'Collapse' : 'Expand'} prop value`}
160 + >
161 + <ButtonIcon type={isOpen ? 'expanded' : 'collapsed'} />
162 + </Button>
163 + );
164 +}