Skip to content

Commit ecc2e03

Browse files
authored
Merge pull request #3241 from plotly/collapse-devtools
Add collapse button to devtools
2 parents 5dc9a11 + 9276a63 commit ecc2e03

File tree

5 files changed

+139
-89
lines changed

5 files changed

+139
-89
lines changed

Diff for: dash/dash-renderer/src/components/error/CallbackGraph/CallbackGraphContainer.css

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
background: #ffffff;
99
display: inline-block;
1010
/* shadow-1 */
11-
box-shadow:
12-
0px 6px 16px rgba(80, 103, 132, 0.165),
11+
box-shadow: 0px 6px 16px rgba(80, 103, 132, 0.165),
1312
0px 2px 6px rgba(80, 103, 132, 0.12),
1413
0px 0px 1px rgba(80, 103, 132, 0.32);
1514
}

Diff for: dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.css

+2-3
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
}
125125

126126
.dash-be-error__str {
127-
background-color: #F5F6FA;
127+
background-color: #f5f6fa;
128128
min-width: 386px;
129129
width: 100%;
130130
overflow: auto;
@@ -177,8 +177,7 @@
177177
background-color: white;
178178
overflow: auto;
179179
border-radius: 6px;
180-
box-shadow:
181-
0px 0.7px 1.4px 0px rgba(0, 0, 0, 0.07),
180+
box-shadow: 0px 0.7px 1.4px 0px rgba(0, 0, 0, 0.07),
182181
0px 1.9px 4px 0px rgba(0, 0, 0, 0.05),
183182
0px 4.5px 10px 0px rgba(0, 0, 0, 0.05);
184183
}
Loading

Diff for: dash/dash-renderer/src/components/error/menu/DebugMenu.css

+39-20
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@
2525
font-size: 14px;
2626
border-radius: 0px;
2727
letter-spacing: normal;
28+
white-space: nowrap;
2829
gap: 6px;
30+
cursor: pointer;
31+
border: none;
32+
background: none;
33+
outline: none;
34+
display: flex;
35+
align-items: center;
2936
}
3037

3138
.dash-debug-menu__popup {
@@ -52,8 +59,7 @@
5259
align-self: flex-end;
5360
position: relative;
5461
/* Shadow/Small */
55-
box-shadow:
56-
0px 0.7px 1.4px 0px rgba(0, 0, 0, 0.07),
62+
box-shadow: 0px 0.7px 1.4px 0px rgba(0, 0, 0, 0.07),
5763
0px 1.9px 4px 0px rgba(0, 0, 0, 0.05),
5864
0px 4.5px 10px 0px rgba(0, 0, 0, 0.05);
5965
}
@@ -113,30 +119,28 @@
113119
transition: 0.3s;
114120
box-sizing: border-box;
115121
position: fixed;
116-
bottom: 8px;
117-
right: 8px;
122+
bottom: -1px;
123+
right: -1px;
118124
display: flex;
119125
color: black;
120-
flex-direction: column;
126+
flex-direction: row;
121127
font-family: Verdana, sans-serif !important;
122128
font-size: 14px;
123-
justify-content: center;
129+
justify-content: flex-end;
124130
align-items: center;
125131
z-index: 10000;
126-
border-radius: 5px;
127-
padding: 5px;
132+
border-radius: 5px 0 0 0;
133+
padding: 15px 0;
128134
background-color: #f5f6fa;
129-
box-shadow:
130-
0px 0.8px 0.8px 0px rgba(0, 0, 0, 0.04),
135+
box-shadow: 0px 0.8px 0.8px 0px rgba(0, 0, 0, 0.04),
131136
0px 2.3px 2px 0px rgba(0, 0, 0, 0.03);
132137
border: 1px solid rgba(0, 24, 102, 0.1);
133138
}
134-
.dash-debug-menu__outer--closed {
135-
height: 60px;
136-
width: 60px;
137-
bottom: 37px;
138-
right: 37px;
139-
padding: 0;
139+
.dash-debug-menu__outer.dash-debug-menu__outer--collapsed {
140+
max-width: 50px;
141+
}
142+
.dash-debug-menu__outer.dash-debug-menu__outer--expanded {
143+
max-width: 682px;
140144
}
141145

142146
.dash-debug-menu__upgrade-tooltip {
@@ -153,6 +157,22 @@
153157
z-index: 1200;
154158
}
155159

160+
.dash-debug-menu__toggle {
161+
color: #7f4bc4;
162+
transition: 0.3s;
163+
}
164+
.dash-debug-menu__toggle--expanded {
165+
transform: rotate(180deg);
166+
}
167+
.dash-debug-menu__error-indicator {
168+
width: 8px;
169+
height: 8px;
170+
background-color: #DC3E42;
171+
border-radius: 100%;
172+
position: absolute;
173+
right: 3px;
174+
top: 13px;
175+
}
156176
.dash-debug-menu__status {
157177
display: flex;
158178
align-items: center;
@@ -162,7 +182,8 @@
162182
.dash-debug-menu__content {
163183
display: flex;
164184
align-items: stretch;
165-
margin: 10px;
185+
margin-left: 15px;
186+
transition: all 0.5s ease;
166187
}
167188

168189
.dash-debug-menu__version {
@@ -186,7 +207,6 @@
186207
justify-content: center;
187208
align-items: center;
188209
transition: background-color 0.2s;
189-
cursor: pointer;
190210
font-family: Verdana, sans-serif !important;
191211
font-weight: bold;
192212
color: black;
@@ -213,8 +233,7 @@
213233
right: 29px;
214234
z-index: 10002;
215235
cursor: pointer;
216-
box-shadow:
217-
0px 0px 1px rgba(0, 0, 0, 0.25),
236+
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.25),
218237
0px 1px 3px rgba(162, 177, 198, 0.32);
219238
border-radius: 32px;
220239
background-color: white;

Diff for: dash/dash-renderer/src/components/error/menu/DebugMenu.react.js

+96-64
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {Component} from 'react';
1+
import React, {useEffect, useState} from 'react';
22
import PropTypes from 'prop-types';
33
import {concat} from 'ramda';
44

@@ -9,13 +9,23 @@ import ClockIcon from '../icons/ClockIcon.svg';
99
import ErrorIcon from '../icons/ErrorIcon.svg';
1010
import GraphIcon from '../icons/GraphIcon.svg';
1111
import OffIcon from '../icons/OffIcon.svg';
12+
import Expand from '../icons/Expand.svg';
1213
import {VersionInfo} from './VersionInfo.react';
1314
import {CallbackGraphContainer} from '../CallbackGraph/CallbackGraphContainer.react';
1415
import {FrontEndErrorContainer} from '../FrontEnd/FrontEndErrorContainer.react';
1516

1617
const classes = (base, variant, variant2) =>
1718
`${base} ${base}--${variant}` + (variant2 ? ` ${base}--${variant2}` : '');
1819

20+
const isCollapsed = () => {
21+
try {
22+
return localStorage.getItem('dash_debug_menu_collapsed') === 'true';
23+
} catch (e) {
24+
// If localStorage is not available, default to false
25+
return false;
26+
}
27+
};
28+
1929
const MenuContent = ({
2030
hotReload,
2131
connected,
@@ -77,76 +87,98 @@ const MenuContent = ({
7787
Server
7888
<_StatusIcon className='dash-debug-menu__icon' />
7989
</div>
90+
<div
91+
className='dash-debug-menu__divider'
92+
style={{marginRight: 0}}
93+
/>
8094
</div>
8195
);
8296
};
8397

84-
class DebugMenu extends Component {
85-
constructor(props) {
86-
super(props);
98+
const DebugMenu = ({error, hotReload, config, children}) => {
99+
const [popup, setPopup] = useState('errors');
100+
const [collapsed, setCollapsed] = useState(isCollapsed);
101+
102+
const errCount = error.frontEnd.length + error.backEnd.length;
103+
const connected = error.backEndConnected;
104+
105+
useEffect(() => {
106+
if (errCount > 0 && popup == null) {
107+
setPopup('errors');
108+
}
109+
}, [errCount]);
110+
111+
const toggleErrors = () => {
112+
setPopup(popup == 'errors' ? null : 'errors');
113+
};
114+
115+
const toggleCallbackGraph = () => {
116+
setPopup(popup == 'callbackGraph' ? null : 'callbackGraph');
117+
};
118+
119+
const toggleCollapsed = () => {
120+
setCollapsed(!collapsed);
121+
try {
122+
localStorage.setItem('dash_debug_menu_collapsed', !collapsed);
123+
} catch (e) {
124+
// If localStorage is not available, do nothing
125+
}
126+
};
127+
128+
const errors = concat(error.frontEnd, error.backEnd);
129+
130+
const popupContent = (
131+
<div className='dash-debug-menu__popup'>
132+
{popup == 'callbackGraph' ? <CallbackGraphContainer /> : undefined}
133+
{popup == 'errors' && errCount > 0 ? (
134+
<FrontEndErrorContainer
135+
clickHandler={toggleErrors}
136+
errors={errors}
137+
connected={error.backEndConnected}
138+
/>
139+
) : undefined}
140+
</div>
141+
);
87142

88-
this.state = {
89-
opened: false,
90-
popup: 'errors'
91-
};
92-
}
143+
const menuContent = collapsed ? undefined : (
144+
<MenuContent
145+
popup={popup}
146+
errCount={errCount}
147+
toggleErrors={toggleErrors}
148+
toggleCallbackGraph={toggleCallbackGraph}
149+
config={config}
150+
hotReload={hotReload}
151+
connected={connected}
152+
/>
153+
);
93154

94-
render() {
95-
const {popup} = this.state;
96-
const {error, hotReload, config} = this.props;
97-
const errCount = error.frontEnd.length + error.backEnd.length;
98-
const connected = error.backEndConnected;
99-
100-
const toggleErrors = () => {
101-
this.setState({popup: popup == 'errors' ? null : 'errors'});
102-
};
103-
104-
const toggleCallbackGraph = () => {
105-
this.setState({
106-
popup: popup == 'callbackGraph' ? null : 'callbackGraph'
107-
});
108-
};
109-
110-
const errors = concat(error.frontEnd, error.backEnd);
111-
112-
const popupContent = (
113-
<div className='dash-debug-menu__popup'>
114-
{popup == 'callbackGraph' ? (
115-
<CallbackGraphContainer />
116-
) : undefined}
117-
{popup == 'errors' && errCount > 0 ? (
118-
<FrontEndErrorContainer
119-
clickHandler={toggleErrors}
120-
errors={errors}
121-
connected={error.backEndConnected}
122-
/>
123-
) : undefined}
124-
</div>
125-
);
126-
127-
const menuContent = (
128-
<MenuContent
129-
popup={popup}
130-
errCount={errCount}
131-
toggleErrors={toggleErrors}
132-
toggleCallbackGraph={toggleCallbackGraph}
133-
config={config}
134-
hotReload={hotReload}
135-
connected={connected}
136-
/>
137-
);
138-
139-
return (
140-
<div>
141-
<div className={classes('dash-debug-menu__outer')}>
142-
{popupContent}
143-
{menuContent}
144-
</div>
145-
{this.props.children}
155+
return (
156+
<div>
157+
<div
158+
className={classes(
159+
'dash-debug-menu__outer',
160+
collapsed ? 'collapsed' : 'expanded'
161+
)}
162+
>
163+
{popupContent}
164+
{menuContent}
165+
<button
166+
onClick={toggleCollapsed}
167+
className={classes(
168+
'dash-debug-menu__toggle',
169+
collapsed ? 'collapsed' : 'expanded'
170+
)}
171+
>
172+
<Expand />
173+
{errCount > 0 && collapsed ? (
174+
<div className='dash-debug-menu__error-indicator' />
175+
) : null}
176+
</button>
146177
</div>
147-
);
148-
}
149-
}
178+
{children}
179+
</div>
180+
);
181+
};
150182

151183
DebugMenu.propTypes = {
152184
children: PropTypes.object,

0 commit comments

Comments
 (0)