Skip to content

Commit 6bb11f9

Browse files
authored
feat: Adjustable grid density (#2151)
Fixes #885 This adds a user setting for grid density in the theme section which applies to all grids without an explicit density prop. A separate dh.ui PR will allow setting the density per table and is not influenced by the global density setting.
1 parent 7875d03 commit 6bb11f9

25 files changed

Lines changed: 278 additions & 123 deletions

packages/app-utils/src/components/AppBootstrap.tsx

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React, { useCallback, useMemo, useState } from 'react';
2+
import { Provider } from 'react-redux';
3+
import { store } from '@deephaven/redux';
24
import '@deephaven/components/scss/BaseStyleSheet.scss';
35
import { ClientBootstrap } from '@deephaven/jsapi-bootstrap';
46
import {
@@ -56,29 +58,34 @@ export function AppBootstrap({
5658
}, []);
5759
useBroadcastLoginListener(onLogin, onLogout);
5860
return (
59-
<FontBootstrap fontClassNames={fontClassNames}>
60-
<PluginsBootstrap getCorePlugins={getCorePlugins} pluginsUrl={pluginsUrl}>
61-
<ThemeBootstrap>
62-
<ClientBootstrap
63-
serverUrl={serverUrl}
64-
options={clientOptions}
65-
key={logoutCount}
66-
>
67-
<RefreshTokenBootstrap>
68-
<AuthBootstrap>
69-
<ServerConfigBootstrap>
70-
<UserBootstrap>
71-
<ConnectionBootstrap>
72-
<FontsLoaded>{children}</FontsLoaded>
73-
</ConnectionBootstrap>
74-
</UserBootstrap>
75-
</ServerConfigBootstrap>
76-
</AuthBootstrap>
77-
</RefreshTokenBootstrap>
78-
</ClientBootstrap>
79-
</ThemeBootstrap>
80-
</PluginsBootstrap>
81-
</FontBootstrap>
61+
<Provider store={store}>
62+
<FontBootstrap fontClassNames={fontClassNames}>
63+
<PluginsBootstrap
64+
getCorePlugins={getCorePlugins}
65+
pluginsUrl={pluginsUrl}
66+
>
67+
<ThemeBootstrap>
68+
<ClientBootstrap
69+
serverUrl={serverUrl}
70+
options={clientOptions}
71+
key={logoutCount}
72+
>
73+
<RefreshTokenBootstrap>
74+
<AuthBootstrap>
75+
<ServerConfigBootstrap>
76+
<UserBootstrap>
77+
<ConnectionBootstrap>
78+
<FontsLoaded>{children}</FontsLoaded>
79+
</ConnectionBootstrap>
80+
</UserBootstrap>
81+
</ServerConfigBootstrap>
82+
</AuthBootstrap>
83+
</RefreshTokenBootstrap>
84+
</ClientBootstrap>
85+
</ThemeBootstrap>
86+
</PluginsBootstrap>
87+
</FontBootstrap>
88+
</Provider>
8289
);
8390
}
8491

packages/app-utils/src/components/ThemeBootstrap.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { MonacoThemeProvider } from '@deephaven/console';
44
import { ThemeProvider } from '@deephaven/components';
55
import { IrisGridThemeProvider } from '@deephaven/iris-grid';
66
import { getThemeDataFromPlugins, PluginsContext } from '@deephaven/plugin';
7+
import { getSettings } from '@deephaven/redux';
8+
import { useAppSelector } from '@deephaven/dashboard';
79

810
export interface ThemeBootstrapProps {
911
children: React.ReactNode;
@@ -21,11 +23,15 @@ export function ThemeBootstrap({ children }: ThemeBootstrapProps): JSX.Element {
2123
[pluginModules]
2224
);
2325

26+
const settings = useAppSelector(getSettings);
27+
2428
return (
2529
<ThemeProvider themes={themes}>
2630
<ChartThemeProvider>
2731
<MonacoThemeProvider>
28-
<IrisGridThemeProvider>{children}</IrisGridThemeProvider>
32+
<IrisGridThemeProvider density={settings.gridDensity}>
33+
{children}
34+
</IrisGridThemeProvider>
2935
</MonacoThemeProvider>
3036
</ChartThemeProvider>
3137
</ThemeProvider>

packages/app-utils/src/storage/LocalWorkspaceStorage.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
6161
},
6262
webgl: true,
6363
webglEditable: true,
64+
gridDensity: 'regular' as const,
6465
};
6566
const serverSettings = {
6667
defaultDateTimeFormat: serverConfigValues?.get('dateTimeFormat'),
@@ -121,7 +122,9 @@ export class LocalWorkspaceStorage implements WorkspaceStorage {
121122
),
122123
};
123124

124-
const keys = Object.keys(serverSettings) as Array<keyof typeof settings>;
125+
const keys = Object.keys(serverSettings) as Array<
126+
keyof typeof serverSettings
127+
>;
125128
for (let i = 0; i < keys.length; i += 1) {
126129
const key = keys[i];
127130
if (serverSettings[key] !== undefined) {

packages/code-studio/src/AppRoot.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import React from 'react';
2-
import { Provider } from 'react-redux';
32
import { MonacoUtils } from '@deephaven/console';
4-
import { store } from '@deephaven/redux';
53
import { DownloadServiceWorkerUtils } from '@deephaven/iris-grid';
64
import MonacoWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
75
import AppRouter from './main/AppRouter';
@@ -25,11 +23,7 @@ export function AppRoot(): JSX.Element {
2523
// @ts-ignore
2624
window['__react-beautiful-dnd-disable-dev-warnings'] = true;
2725

28-
return (
29-
<Provider store={store}>
30-
<AppRouter />
31-
</Provider>
32-
);
26+
return <AppRouter />;
3327
}
3428

3529
export default AppRoot;

packages/code-studio/src/index.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React, { Suspense } from 'react';
22
import ReactDOM from 'react-dom';
3-
import '@deephaven/components/scss/BaseStyleSheet.scss';
3+
import '@deephaven/components/scss/BaseStyleSheet.scss'; // Do NOT move any lower. This needs to be imported before any other styles
4+
import { Provider } from 'react-redux';
45
import { LoadingOverlay, preloadTheme } from '@deephaven/components';
56
import { ApiBootstrap } from '@deephaven/jsapi-bootstrap';
7+
import { store } from '@deephaven/redux';
68
import logInit from './log/LogInit';
79

810
logInit();
@@ -59,13 +61,15 @@ async function getCorePlugins() {
5961
ReactDOM.render(
6062
<ApiBootstrap apiUrl={apiURL.href} setGlobally>
6163
<Suspense fallback={<LoadingOverlay />}>
62-
<AppBootstrap
63-
getCorePlugins={getCorePlugins}
64-
serverUrl={apiURL.origin}
65-
pluginsUrl={pluginsURL.href}
66-
>
67-
<AppRoot />
68-
</AppBootstrap>
64+
<Provider store={store}>
65+
<AppBootstrap
66+
getCorePlugins={getCorePlugins}
67+
serverUrl={apiURL.origin}
68+
pluginsUrl={pluginsURL.href}
69+
>
70+
<AppRoot />
71+
</AppBootstrap>
72+
</Provider>
6973
</Suspense>
7074
</ApiBootstrap>,
7175
document.getElementById('root')

packages/code-studio/src/settings/SettingsMenu.tsx

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import {
1616
CopyButton,
1717
GLOBAL_SHORTCUTS,
1818
Logo,
19-
ThemeContext,
20-
ThemePicker,
2119
Tooltip,
2220
} from '@deephaven/components';
2321
import { ServerConfigValues, User } from '@deephaven/redux';
@@ -26,7 +24,6 @@ import {
2624
BROADCAST_LOGOUT_MESSAGE,
2725
makeMessage,
2826
} from '@deephaven/jsapi-utils';
29-
import { assertNotNull } from '@deephaven/utils';
3027
import { PluginModuleMap } from '@deephaven/plugin';
3128
import FormattingSectionContent from './FormattingSectionContent';
3229
import LegalNotice from './LegalNotice';
@@ -40,6 +37,7 @@ import {
4037
getFormattedVersionInfo,
4138
} from './SettingsUtils';
4239
import AdvancedSectionContent from './AdvancedSectionContent';
40+
import ThemeSectionContent from './ThemeSectionContent';
4341

4442
interface SettingsMenuProps {
4543
serverConfigValues: ServerConfigValues;
@@ -258,33 +256,23 @@ export class SettingsMenu extends Component<
258256
<ColumnSpecificSectionContent scrollTo={this.handleScrollTo} />
259257
</SettingsMenuSection>
260258

261-
<ThemeContext.Consumer>
262-
{contextValue => {
263-
assertNotNull(contextValue, 'ThemeContext value is null');
264-
265-
return contextValue.themes.length > 1 ? (
266-
<SettingsMenuSection
267-
sectionKey={SettingsMenu.THEME_SECTION_KEY}
268-
isExpanded={this.isSectionExpanded(
269-
SettingsMenu.THEME_SECTION_KEY
270-
)}
271-
onToggle={this.handleSectionToggle}
272-
title={
273-
<>
274-
<FontAwesomeIcon
275-
icon={vsPaintcan}
276-
transform="grow-4"
277-
className="mr-2"
278-
/>
279-
Theme
280-
</>
281-
}
282-
>
283-
<ThemePicker />
284-
</SettingsMenuSection>
285-
) : null;
286-
}}
287-
</ThemeContext.Consumer>
259+
<SettingsMenuSection
260+
sectionKey={SettingsMenu.THEME_SECTION_KEY}
261+
isExpanded={this.isSectionExpanded(SettingsMenu.THEME_SECTION_KEY)}
262+
onToggle={this.handleSectionToggle}
263+
title={
264+
<>
265+
<FontAwesomeIcon
266+
icon={vsPaintcan}
267+
transform="grow-4"
268+
className="mr-2"
269+
/>
270+
Theme
271+
</>
272+
}
273+
>
274+
<ThemeSectionContent />
275+
</SettingsMenuSection>
288276

289277
<SettingsMenuSection
290278
sectionKey={SettingsMenu.SHORTCUT_SECTION_KEY}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React, { useCallback } from 'react';
2+
import {
3+
Item,
4+
ItemKey,
5+
Picker,
6+
ThemePicker,
7+
useTheme,
8+
} from '@deephaven/components';
9+
import { assertNotNull } from '@deephaven/utils';
10+
import { useDispatch } from 'react-redux';
11+
import { getSettings, updateSettings } from '@deephaven/redux';
12+
import { useAppSelector } from '@deephaven/dashboard';
13+
14+
export function ThemeSectionContent(): JSX.Element {
15+
const theme = useTheme();
16+
const settings = useAppSelector(getSettings);
17+
const dispatch = useDispatch();
18+
19+
const updateDensity = useCallback(
20+
(density: ItemKey | null) => {
21+
if (
22+
density !== 'regular' &&
23+
density !== 'compact' &&
24+
density !== 'spacious'
25+
) {
26+
throw new Error(`Invalid grid density value: ${density}`);
27+
}
28+
dispatch(updateSettings({ gridDensity: density }));
29+
},
30+
[dispatch]
31+
);
32+
33+
const density = settings.gridDensity;
34+
35+
assertNotNull(theme, 'ThemeContext value is null');
36+
37+
return (
38+
<>
39+
<ThemePicker />
40+
<Picker
41+
label="Default table density"
42+
selectedKey={density}
43+
onChange={updateDensity}
44+
>
45+
<Item key="regular">Regular</Item>
46+
<Item key="compact">Compact</Item>
47+
<Item key="spacious">Spacious</Item>
48+
</Picker>
49+
</>
50+
);
51+
}
52+
53+
export default ThemeSectionContent;

packages/code-studio/src/styleguide/Grids.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ function Grids(): ReactElement {
2222
const [irisGridModel] = useState(
2323
new MockIrisGridTreeModel(dh, new MockTreeGridModel())
2424
);
25+
const [irisGridCompactModel] = useState(
26+
new MockIrisGridTreeModel(dh, new MockTreeGridModel())
27+
);
28+
const [irisGridSpaciousModel] = useState(
29+
new MockIrisGridTreeModel(dh, new MockTreeGridModel())
30+
);
2531
const [model] = useState(new MockGridModel());
2632
const [theme] = useState<Partial<GridThemeType>>({
2733
autoSelectRow: true,
@@ -68,7 +74,15 @@ function Grids(): ReactElement {
6874
</SampleSection>
6975
<h2 className="ui-title">Iris Grid</h2>
7076
<SampleSection name="grids-iris" component={Flex} height={500}>
71-
<IrisGrid model={irisGridModel} />
77+
<IrisGrid model={irisGridModel} density="regular" />
78+
</SampleSection>
79+
<h2 className="ui-title">Iris Grid Compact</h2>
80+
<SampleSection name="grids-iris-compact" component={Flex} height={500}>
81+
<IrisGrid model={irisGridCompactModel} density="compact" />
82+
</SampleSection>
83+
<h2 className="ui-title">Iris Grid Spacious</h2>
84+
<SampleSection name="grids-iris-spacious" component={Flex} height={500}>
85+
<IrisGrid model={irisGridSpaciousModel} density="spacious" />
7286
</SampleSection>
7387
</ThemeContext.Provider>
7488
</div>

packages/code-studio/src/styleguide/StyleGuide.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ function StyleGuide(): React.ReactElement {
7575
>
7676
<h1 style={{ paddingTop: '2rem' }}>Deephaven UI Components</h1>
7777
</Flex>
78-
79-
{/* {isIsolatedSection ? null : ( */}
8078
<Flex
8179
{...stickyProps}
8280
UNSAFE_className={
@@ -90,8 +88,6 @@ function StyleGuide(): React.ReactElement {
9088
{hasMultipleThemes ? <ThemePicker /> : null}
9189
<SamplesMenu />
9290
</Flex>
93-
{/* )} */}
94-
{/* {isIsolatedSection ? null : ( */}
9591
<Flex
9692
{...stickyProps}
9793
UNSAFE_className={
@@ -103,7 +99,6 @@ function StyleGuide(): React.ReactElement {
10399
>
104100
<GotoTopButton />
105101
</Flex>
106-
{/* )} */}
107102

108103
<Typograpy />
109104

packages/embed-widget/src/index.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import React, { Suspense } from 'react';
22
import ReactDOM from 'react-dom';
3-
import { Provider } from 'react-redux';
4-
import { store } from '@deephaven/redux';
5-
import '@deephaven/components/scss/BaseStyleSheet.scss';
3+
import '@deephaven/components/scss/BaseStyleSheet.scss'; // Do NOT move any lower. This needs to be imported before any other styles
64
import { LoadingOverlay, preloadTheme } from '@deephaven/components';
75
import { ApiBootstrap } from '@deephaven/jsapi-bootstrap';
86
import './index.scss';
@@ -56,9 +54,7 @@ ReactDOM.render(
5654
serverUrl={apiURL.origin}
5755
pluginsUrl={pluginsURL.href}
5856
>
59-
<Provider store={store}>
60-
<App />
61-
</Provider>
57+
<App />
6258
</AppBootstrap>
6359
</Suspense>
6460
</ApiBootstrap>,

0 commit comments

Comments
 (0)