mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 17:30:46 +00:00
feat: implement zoom level hook and update components for responsive design.
This commit is contained in:
@@ -32,6 +32,7 @@ import { userContext } from "UserContext";
|
|||||||
import { getCollectionName, getDatabaseName } from "Utils/APITypeUtils";
|
import { getCollectionName, getDatabaseName } from "Utils/APITypeUtils";
|
||||||
import { Allotment, AllotmentHandle } from "allotment";
|
import { Allotment, AllotmentHandle } from "allotment";
|
||||||
import { useSidePanel } from "hooks/useSidePanel";
|
import { useSidePanel } from "hooks/useSidePanel";
|
||||||
|
import useZoomLevel from "hooks/useZoomLevel";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
||||||
@@ -109,11 +110,18 @@ const useSidebarStyles = makeStyles({
|
|||||||
overflow: "scroll",
|
overflow: "scroll",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
minHeight: {
|
minHeightResponsive: {
|
||||||
"@media (max-width: 420px)": {
|
"@media (max-width: 420px)": {
|
||||||
minHeight: "300px",
|
minHeight: "400px",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
accessibleContentZoom: {
|
||||||
|
overflow: "scroll",
|
||||||
|
},
|
||||||
|
|
||||||
|
minHeightZoom:{
|
||||||
|
minHeight: "400px",
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface GlobalCommandsProps {
|
interface GlobalCommandsProps {
|
||||||
@@ -285,6 +293,7 @@ export const SidebarContainer: React.FC<SidebarProps> = ({ explorer }) => {
|
|||||||
const [expandedSize, setExpandedSize] = React.useState(300);
|
const [expandedSize, setExpandedSize] = React.useState(300);
|
||||||
const hasSidebar = userContext.apiType !== "Postgres" && userContext.apiType !== "VCoreMongo";
|
const hasSidebar = userContext.apiType !== "Postgres" && userContext.apiType !== "VCoreMongo";
|
||||||
const allotment = useRef<AllotmentHandle>(null);
|
const allotment = useRef<AllotmentHandle>(null);
|
||||||
|
const isZoomed = useZoomLevel();
|
||||||
|
|
||||||
const expand = useCallback(() => {
|
const expand = useCallback(() => {
|
||||||
if (!expanded) {
|
if (!expanded) {
|
||||||
@@ -338,12 +347,12 @@ export const SidebarContainer: React.FC<SidebarProps> = ({ explorer }) => {
|
|||||||
ref={allotment}
|
ref={allotment}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onDragEnd={onDragEnd}
|
onDragEnd={onDragEnd}
|
||||||
className={`resourceTreeAndTabs ${styles.accessibleContent}`}
|
className={`resourceTreeAndTabs ${styles.accessibleContent} ${isZoomed ? styles.accessibleContentZoom : ''}`}
|
||||||
>
|
>
|
||||||
{/* Collections Tree - Start */}
|
{/* Collections Tree - Start */}
|
||||||
{hasSidebar && (
|
{hasSidebar && (
|
||||||
// When collapsed, we force the pane to 24 pixels wide and make it non-resizable.
|
// When collapsed, we force the pane to 24 pixels wide and make it non-resizable.
|
||||||
<Allotment.Pane className={styles.minHeight} minSize={24} preferredSize={250}>
|
<Allotment.Pane className={`${styles.minHeightResponsive} ${isZoomed ? styles.minHeightZoom : ''}`} minSize={24} preferredSize={250}>
|
||||||
<CosmosFluentProvider className={mergeClasses(styles.sidebar)}>
|
<CosmosFluentProvider className={mergeClasses(styles.sidebar)}>
|
||||||
<div className={styles.sidebarContainer}>
|
<div className={styles.sidebarContainer}>
|
||||||
{loading && (
|
{loading && (
|
||||||
@@ -399,7 +408,7 @@ export const SidebarContainer: React.FC<SidebarProps> = ({ explorer }) => {
|
|||||||
</CosmosFluentProvider>
|
</CosmosFluentProvider>
|
||||||
</Allotment.Pane>
|
</Allotment.Pane>
|
||||||
)}
|
)}
|
||||||
<Allotment.Pane className={styles.minHeight} minSize={200}>
|
<Allotment.Pane className={`${styles.minHeightResponsive} ${isZoomed ? styles.minHeightZoom : ''}`} minSize={200}>
|
||||||
<Tabs explorer={explorer} />
|
<Tabs explorer={explorer} />
|
||||||
</Allotment.Pane>
|
</Allotment.Pane>
|
||||||
</Allotment>
|
</Allotment>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ exports[`Documents tab (noSql API) when rendered should render the page 1`] = `
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="___11ktxfv_0000000 f1o614cb fy9rknc f22iagw fsnqrgy f1f5gg8d fjodcmx f122n59 f1f09k3d fg706s2 frpde29"
|
className="___11ktxfv_0000000 f1o614cb fy9rknc f22iagw fsnqrgy f1f5gg8d fjodcmx f122n59 f1f09k3d fg706s2 frpde29 ___1ngl8o6_0000000 fz7mnu6 fl3egqs flhmrkm"
|
||||||
data-test="DocumentsTab/Filter"
|
data-test="DocumentsTab/Filter"
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import RunQuery from "../../../../images/RunQuery.png";
|
|||||||
import { QueryResults } from "../../../Contracts/ViewModels";
|
import { QueryResults } from "../../../Contracts/ViewModels";
|
||||||
import { ErrorList } from "./ErrorList";
|
import { ErrorList } from "./ErrorList";
|
||||||
import { ResultsView } from "./ResultsView";
|
import { ResultsView } from "./ResultsView";
|
||||||
|
import useZoomLevel from "hooks/useZoomLevel";
|
||||||
|
|
||||||
export interface ResultsViewProps {
|
export interface ResultsViewProps {
|
||||||
isMongoDB: boolean;
|
isMongoDB: boolean;
|
||||||
@@ -23,11 +24,12 @@ interface QueryResultProps extends ResultsViewProps {
|
|||||||
|
|
||||||
const ExecuteQueryCallToAction: React.FC = () => {
|
const ExecuteQueryCallToAction: React.FC = () => {
|
||||||
const styles = useQueryTabStyles();
|
const styles = useQueryTabStyles();
|
||||||
|
const isZoomed = useZoomLevel();
|
||||||
return (
|
return (
|
||||||
<div data-test="QueryTab/ResultsPane/ExecuteCTA" className={styles.executeCallToAction}>
|
<div data-test="QueryTab/ResultsPane/ExecuteCTA" className={styles.executeCallToAction}>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<img src={RunQuery} aria-hidden="true" />
|
<img className={`${styles.responsiveImg} ${isZoomed ? styles.zoomedImageSize : ''}`} src={RunQuery} aria-hidden="true" />
|
||||||
</p>
|
</p>
|
||||||
<p>Execute a query to see the results</p>
|
<p>Execute a query to see the results</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export const useQueryTabStyles = makeStyles({
|
|||||||
height: "100%",
|
height: "100%",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
|
"@media (max-width: 420px)": {
|
||||||
|
overflow: "scroll",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
queryResultsMessage: {
|
queryResultsMessage: {
|
||||||
...shorthands.margin("5px"),
|
...shorthands.margin("5px"),
|
||||||
@@ -38,6 +41,9 @@ export const useQueryTabStyles = makeStyles({
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
rowGap: "12px",
|
rowGap: "12px",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
|
"@media (max-width: 420px)": {
|
||||||
|
height: "auto",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
queryResultsTabContentContainer: {
|
queryResultsTabContentContainer: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@@ -93,4 +99,13 @@ export const useQueryTabStyles = makeStyles({
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
},
|
},
|
||||||
|
responsiveImg:{
|
||||||
|
"@media (max-width: 420px)": {
|
||||||
|
width: "50px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
zoomedImageSize: {
|
||||||
|
width: "60px",
|
||||||
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
20
src/hooks/useZoomLevel.ts
Normal file
20
src/hooks/useZoomLevel.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
const useZoomLevel = (threshold: number = 2): boolean => {
|
||||||
|
const [isZoomed, setIsZoomed] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkZoom = () => {
|
||||||
|
const zoomLevel = window.devicePixelRatio;
|
||||||
|
setIsZoomed(zoomLevel >= threshold);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkZoom();
|
||||||
|
window.addEventListener("resize", checkZoom);
|
||||||
|
return () => window.removeEventListener("resize", checkZoom);
|
||||||
|
}, [threshold]);
|
||||||
|
|
||||||
|
return isZoomed;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useZoomLevel;
|
||||||
Reference in New Issue
Block a user