From b9fa37cef87e7ff632d3b9d280716d33890ba7d6 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Thu, 20 Mar 2025 09:36:10 +0530 Subject: [PATCH] visualization functions seperated --- app/src/assets/orgTemp.png | Bin 0 -> 25838 bytes .../components/icons/ExportCommonIcons.tsx | 14 +- .../components/icons/ExportModuleIcons.tsx | 4 +- app/src/components/icons/ExportToolsIcons.tsx | 4 +- .../icons/RealTimeVisulationIcons.tsx | 92 +-- app/src/components/icons/SimulationIcons.tsx | 8 +- .../components/layout/sidebarRight/Header.tsx | 3 +- app/src/components/ui/Tools.tsx | 13 +- .../components/ui/componets/AddButtons.tsx | 77 +- .../ui/componets/RealTimeVisulization.tsx | 122 +-- app/src/functions/generateUniqueId.ts | 2 + app/src/hooks/temp.md | 0 app/src/modules/builder/temp.md | 0 app/src/modules/simulation/temp.md | 0 .../visualization/captureVisualization.ts | 55 ++ .../visualization/handleSaveTemplate.ts | 36 + app/src/pages/Project.tsx | 2 + app/src/services/temp.md | 0 app/src/store/useTemplateStore.ts | 12 +- app/src/styles/layout/sidebar.scss | 57 +- app/src/styles/pages/realTimeViz.scss | 764 ++++++++---------- 21 files changed, 564 insertions(+), 701 deletions(-) create mode 100644 app/src/assets/orgTemp.png create mode 100644 app/src/functions/generateUniqueId.ts create mode 100644 app/src/hooks/temp.md create mode 100644 app/src/modules/builder/temp.md create mode 100644 app/src/modules/simulation/temp.md create mode 100644 app/src/modules/visualization/captureVisualization.ts create mode 100644 app/src/modules/visualization/handleSaveTemplate.ts create mode 100644 app/src/services/temp.md diff --git a/app/src/assets/orgTemp.png b/app/src/assets/orgTemp.png new file mode 100644 index 0000000000000000000000000000000000000000..e3865d6ad2d2fb5d4439f26ce4d20199e5e9ba69 GIT binary patch literal 25838 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 literal 0 HcmV?d00001 diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 53c5b9a..e64af49 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -378,8 +378,8 @@ export function UndoIcon() { xmlns="http://www.w3.org/2000/svg" > @@ -397,8 +397,8 @@ export function RedoIcon() { xmlns="http://www.w3.org/2000/svg" > @@ -436,7 +436,7 @@ export function RemoveIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); } @@ -458,8 +458,8 @@ export function InfoIcon() { d="M6.00006 10.3175C8.45219 10.3175 10.4401 8.32963 10.4401 5.8775C10.4401 3.42536 8.45219 1.4375 6.00006 1.4375C3.54792 1.4375 1.56006 3.42536 1.56006 5.8775C1.56006 8.32963 3.54792 10.3175 6.00006 10.3175Z" stroke="var(--text-color)" stroke-width="0.72" - stroke-linecap="round" - stroke-linejoin="round" + strokeLinecap="round" + strokeLinejoin="round" /> ); diff --git a/app/src/components/icons/ExportModuleIcons.tsx b/app/src/components/icons/ExportModuleIcons.tsx index ffa64c4..fb2f566 100644 --- a/app/src/components/icons/ExportModuleIcons.tsx +++ b/app/src/components/icons/ExportModuleIcons.tsx @@ -113,7 +113,7 @@ export function CartIcon({ isActive }: { isActive: boolean }) { ); diff --git a/app/src/components/icons/ExportToolsIcons.tsx b/app/src/components/icons/ExportToolsIcons.tsx index 2b7134a..d463c0a 100644 --- a/app/src/components/icons/ExportToolsIcons.tsx +++ b/app/src/components/icons/ExportToolsIcons.tsx @@ -605,7 +605,7 @@ export function PenIcon({ isActive }: { isActive: boolean }) { stroke={ isActive ? "var(--highlight-accent-color)" : "var(--text-color)" } - stroke-linecap="round" + strokeLinecap="round" /> ); @@ -631,7 +631,7 @@ export function SaveTemplateIcon({ isActive }: { isActive: boolean }) { stroke={ isActive ? "var(--highlight-accent-color)" : "var(--text-color)" } - stroke-linecap="round" + strokeLinecap="round" /> ); diff --git a/app/src/components/icons/RealTimeVisulationIcons.tsx b/app/src/components/icons/RealTimeVisulationIcons.tsx index 0174eda..7c1a8d0 100644 --- a/app/src/components/icons/RealTimeVisulationIcons.tsx +++ b/app/src/components/icons/RealTimeVisulationIcons.tsx @@ -7,40 +7,40 @@ export function CleanPannel() { fill="none" xmlns="http://www.w3.org/2000/svg" > - - + + - + @@ -98,65 +98,3 @@ export function LockIcon() { ); } - -export function PlayIcon() { - return ( - - - - ); -} - -export function CommentIcon() { - return ( - - - - - - ); -} - -export function SaveTeemplateIcon() { - return ( - - - - - ); -} diff --git a/app/src/components/icons/SimulationIcons.tsx b/app/src/components/icons/SimulationIcons.tsx index 1dc82a7..3ce3ebe 100644 --- a/app/src/components/icons/SimulationIcons.tsx +++ b/app/src/components/icons/SimulationIcons.tsx @@ -10,14 +10,14 @@ export function AnalysisIcon({ isActive }: { isActive: boolean }) { ); diff --git a/app/src/components/layout/sidebarRight/Header.tsx b/app/src/components/layout/sidebarRight/Header.tsx index e9ebaa8..b80fd53 100644 --- a/app/src/components/layout/sidebarRight/Header.tsx +++ b/app/src/components/layout/sidebarRight/Header.tsx @@ -1,5 +1,6 @@ import React from "react"; import { AppDockIcon } from "../../icons/HeaderIcons"; +import orgImg from "../../../assets/orgTemp.png" const Header: React.FC = () => { const guestUsers = [ @@ -38,7 +39,7 @@ const Header: React.FC = () => { V
- +
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx index 291a8f2..a182e1d 100644 --- a/app/src/components/ui/Tools.tsx +++ b/app/src/components/ui/Tools.tsx @@ -13,6 +13,10 @@ import { } from "../icons/ExportToolsIcons"; import { ArrowIcon, TickIcon } from "../icons/ExportCommonIcons"; import useModuleStore from "../../store/useModuleStore"; +import { handleSaveTemplate } from "../../modules/visualization/handleSaveTemplate"; +import { usePlayButtonStore } from "../../store/usePlayButtonStore"; +import useTemplateStore from "../../store/useTemplateStore"; +import { useSelectedZoneStore } from "../../store/useZoneStore"; const Tools: React.FC = () => { const [activeTool, setActiveTool] = useState("cursor"); @@ -23,6 +27,9 @@ const Tools: React.FC = () => { const [openDrop, setOpenDrop] = useState(false); const { activeModule } = useModuleStore(); + const { isPlaying, setIsPlaying } = usePlayButtonStore(); + const { addTemplate } = useTemplateStore(); + const { selectedZone } = useSelectedZoneStore(); // Reset activeTool whenever activeModule changes useEffect(() => { @@ -187,7 +194,10 @@ const Tools: React.FC = () => { <>
-
+
handleSaveTemplate({ addTemplate, selectedZone })} + >
@@ -207,6 +217,7 @@ const Tools: React.FC = () => { className={`tool-button ${activeTool === "play" ? "active" : ""}`} onClick={() => { setActiveTool("play"); + setIsPlaying(!isPlaying); }} > diff --git a/app/src/components/ui/componets/AddButtons.tsx b/app/src/components/ui/componets/AddButtons.tsx index 31110a6..0a810f7 100644 --- a/app/src/components/ui/componets/AddButtons.tsx +++ b/app/src/components/ui/componets/AddButtons.tsx @@ -1,5 +1,9 @@ import React from "react"; -import { CleanPannel, EyeIcon, LockIcon } from "../../icons/RealTimeVisulationIcons"; +import { + CleanPannel, + EyeIcon, + LockIcon, +} from "../../icons/RealTimeVisulationIcons"; // Define the type for `Side` type Side = "top" | "bottom" | "left" | "right"; @@ -137,47 +141,42 @@ const AddButtons: React.FC = ({ {/* Extra Buttons */} -
- {/* Hide Panel */} -
toggleVisibility(side)} - > - -
+ {selectedZone.activeSides.includes(side) && ( +
+ {/* Hide Panel */} +
toggleVisibility(side)} + > + +
- {/* Clean Panel */} -
cleanPanel(side)} - > - -
+ {/* Clean Panel */} +
cleanPanel(side)} + > + +
- {/* Lock/Unlock Panel */} -
toggleLockPanel(side)} - > - + {/* Lock/Unlock Panel */} +
toggleLockPanel(side)} + > + +
-
+ )}
))}
diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx index 5bb2687..fb2d653 100644 --- a/app/src/components/ui/componets/RealTimeVisulization.tsx +++ b/app/src/components/ui/componets/RealTimeVisulization.tsx @@ -2,12 +2,6 @@ import React, { useEffect, useState, useRef } from "react"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; import Panel from "./Panel"; import AddButtons from "./AddButtons"; -import { - CommentIcon, - PlayIcon, - SaveTeemplateIcon, -} from "../../icons/RealTimeVisulationIcons"; -import useTemplateStore from "../../../store/useTemplateStore"; import { useSelectedZoneStore } from "../../../store/useZoneStore"; type Side = "top" | "bottom" | "left" | "right"; @@ -62,82 +56,9 @@ const RealTimeVisulization: React.FC = () => { }, }); - const { isPlaying, setIsPlaying } = usePlayButtonStore(); - const { addTemplate } = useTemplateStore(); + const { isPlaying } = usePlayButtonStore(); + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); - - const generateUniqueId = (): string => - `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; - - const captureVisualization = async (): Promise => { - const container = containerRef.current; - if (!container) return null; - - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - if (!ctx) return null; - - const rect = container.getBoundingClientRect(); - canvas.width = rect.width; - canvas.height = rect.height; - - // Draw background - ctx.fillStyle = getComputedStyle(container).backgroundColor; - ctx.fillRect(0, 0, canvas.width, canvas.height); - - // Capture all canvas elements - const canvases = container.querySelectorAll('canvas'); - canvases.forEach(childCanvas => { - const childRect = childCanvas.getBoundingClientRect(); - const x = childRect.left - rect.left; - const y = childRect.top - rect.top; - ctx.drawImage(childCanvas, x, y, childRect.width, childRect.height); - }); - - // Capture SVG elements - const svgs = container.querySelectorAll('svg'); - for (const svg of Array.from(svgs)) { - const svgString = new XMLSerializer().serializeToString(svg); - const svgBlob = new Blob([svgString], { type: 'image/svg+xml' }); - const url = URL.createObjectURL(svgBlob); - - try { - const img = await new Promise((resolve, reject) => { - const image = new Image(); - image.onload = () => resolve(image); - image.onerror = reject; - image.src = url; - }); - - const svgRect = svg.getBoundingClientRect(); - ctx.drawImage( - img, - svgRect.left - rect.left, - svgRect.top - rect.top, - svgRect.width, - svgRect.height - ); - } finally { - URL.revokeObjectURL(url); - } - } - - return canvas.toDataURL('image/png'); - }; - - const handleSaveTemplate = async () => { - const snapshot = await captureVisualization(); - const template = { - id: generateUniqueId(), - name: `Template ${Date.now()}`, - panelOrder: selectedZone.panelOrder, - widgets: selectedZone.widgets, - snapshot, - }; - addTemplate(template); - - }; - useEffect(() => { setZonesData((prev) => ({ ...prev, @@ -148,38 +69,25 @@ const RealTimeVisulization: React.FC = () => { return (
-
-
- -
-
- -
-
setIsPlaying(!isPlaying)} - > - -
-
- -
+
{Object.keys(zonesData).map((zoneName, index) => (
{ setSelectedZone({ zoneName, @@ -204,4 +112,4 @@ const RealTimeVisulization: React.FC = () => { ); }; -export default RealTimeVisulization; \ No newline at end of file +export default RealTimeVisulization; diff --git a/app/src/functions/generateUniqueId.ts b/app/src/functions/generateUniqueId.ts new file mode 100644 index 0000000..a315524 --- /dev/null +++ b/app/src/functions/generateUniqueId.ts @@ -0,0 +1,2 @@ +export const generateUniqueId = (): string => + `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; \ No newline at end of file diff --git a/app/src/hooks/temp.md b/app/src/hooks/temp.md new file mode 100644 index 0000000..e69de29 diff --git a/app/src/modules/builder/temp.md b/app/src/modules/builder/temp.md new file mode 100644 index 0000000..e69de29 diff --git a/app/src/modules/simulation/temp.md b/app/src/modules/simulation/temp.md new file mode 100644 index 0000000..e69de29 diff --git a/app/src/modules/visualization/captureVisualization.ts b/app/src/modules/visualization/captureVisualization.ts new file mode 100644 index 0000000..01d67a0 --- /dev/null +++ b/app/src/modules/visualization/captureVisualization.ts @@ -0,0 +1,55 @@ +export const captureVisualization = async (): Promise => { + const container = document.getElementById("real-time-vis-canvas"); + if (!container) return null; + + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + if (!ctx) return null; + + const rect = container.getBoundingClientRect(); + canvas.width = rect.width; + canvas.height = rect.height; + + // Draw background + ctx.fillStyle = getComputedStyle(container).backgroundColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + // Capture all canvas elements + const canvases = container.querySelectorAll("canvas"); + canvases.forEach((childCanvas) => { + const childRect = childCanvas.getBoundingClientRect(); + const x = childRect.left - rect.left; + const y = childRect.top - rect.top; + ctx.drawImage(childCanvas, x, y, childRect.width, childRect.height); + }); + + // Capture SVG elements + const svgs = container.querySelectorAll("svg"); + for (const svg of Array.from(svgs)) { + const svgString = new XMLSerializer().serializeToString(svg); + const svgBlob = new Blob([svgString], { type: "image/svg+xml" }); + const url = URL.createObjectURL(svgBlob); + + try { + const img = await new Promise((resolve, reject) => { + const image = new Image(); + image.onload = () => resolve(image); + image.onerror = reject; + image.src = url; + }); + + const svgRect = svg.getBoundingClientRect(); + ctx.drawImage( + img, + svgRect.left - rect.left, + svgRect.top - rect.top, + svgRect.width, + svgRect.height + ); + } finally { + URL.revokeObjectURL(url); + } + } + + return canvas.toDataURL("image/png"); +}; diff --git a/app/src/modules/visualization/handleSaveTemplate.ts b/app/src/modules/visualization/handleSaveTemplate.ts new file mode 100644 index 0000000..290395a --- /dev/null +++ b/app/src/modules/visualization/handleSaveTemplate.ts @@ -0,0 +1,36 @@ +import { Template } from "../../store/useTemplateStore"; +import { captureVisualization } from "./captureVisualization"; + +type HandleSaveTemplateProps = { + addTemplate: (template: Template) => void; + selectedZone: { + panelOrder: string[]; // Adjust the type based on actual data structure + widgets: any[]; // Replace `any` with the actual widget type + }; +}; + +// Generate a unique ID (placeholder function) +const generateUniqueId = (): string => { + return Math.random().toString(36).substring(2, 15); +}; + +// Refactored function +export const handleSaveTemplate = async ({ + addTemplate, + selectedZone, +}: HandleSaveTemplateProps): Promise => { + try { + const snapshot = await captureVisualization(); + const template: Template = { + id: generateUniqueId(), + name: `Template ${Date.now()}`, + panelOrder: selectedZone.panelOrder, + widgets: selectedZone.widgets, + snapshot, + }; + console.log('template: ', template); + addTemplate(template); + } catch (error) { + console.error('Failed to save template:', error); + } +}; diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 29f8c6c..16c0461 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -4,6 +4,7 @@ import SideBarLeft from "../components/layout/sidebarLeft/SideBarLeft"; import SideBarRight from "../components/layout/sidebarRight/SideBarRight"; import useModuleStore from "../store/useModuleStore"; import RealTimeVisulization from "../components/ui/componets/RealTimeVisulization"; +import Tools from "../components/ui/Tools"; const Project: React.FC = () => { const { activeModule } = useModuleStore(); @@ -14,6 +15,7 @@ const Project: React.FC = () => { {activeModule === "visualization" && } +
); }; diff --git a/app/src/services/temp.md b/app/src/services/temp.md new file mode 100644 index 0000000..e69de29 diff --git a/app/src/store/useTemplateStore.ts b/app/src/store/useTemplateStore.ts index a91c14a..f8f3711 100644 --- a/app/src/store/useTemplateStore.ts +++ b/app/src/store/useTemplateStore.ts @@ -1,21 +1,21 @@ import { create } from "zustand"; -type Side = "top" | "bottom" | "left" | "right"; +// type Side = "top" | "bottom" | "left" | "right"; -interface Widget { +export interface Widget { id: string; type: string; title: string; - panel: Side; + panel: string; data: any; } -interface Template { +export interface Template { id: string; name: string; - panelOrder: Side[]; + panelOrder: string[]; widgets: Widget[]; - snapshot?: string; // Add an optional image property (base64) + snapshot?: string | null; // Add an optional image property (base64) } interface TemplateStore { diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 622cade..0daeca3 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -84,9 +84,9 @@ .chart { min-height: 170px; - background: var(--background-primary, #FCFDFD); - border: 1.23px solid var(--Grays-Gray-5, #E5E5EA); - box-shadow: 0px 4.91px 4.91px 0px #0000001C; + background: var(--background-primary, #fcfdfd); + border: 1.23px solid var(--Grays-Gray-5, #e5e5ea); + box-shadow: 0px 4.91px 4.91px 0px #0000001c; border-radius: $border-radius-medium; padding: 12px 6px; } @@ -107,7 +107,7 @@ .stock { padding: 13px 5px; - background-color: #E0DFFF80; + background-color: #e0dfff80; border-radius: 6.33px; display: flex; justify-content: space-between; @@ -129,16 +129,11 @@ font-size: 12px; } } - } } - } } } - - - } .outline-container { @@ -230,14 +225,18 @@ .user-profile-container { display: flex; - .user-organnization { + .user-organization { height: 100%; max-width: 52px; + border-radius: 20px; + overflow: hidden; + margin-left: 2px; img { height: 100%; width: 100%; object-fit: cover; + vertical-align: top; } } } @@ -430,9 +429,7 @@ width: 24px; height: 26px; border-radius: 3.2px; - } - } } @@ -441,7 +438,6 @@ } } } - } } } @@ -527,39 +523,6 @@ } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* Base styles */ .multi-level-dropdown { position: relative; @@ -649,4 +612,4 @@ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* Subtle shadow */ z-index: 20; } -} \ No newline at end of file +} diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index 6bf0ae3..828cc7b 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -1,464 +1,412 @@ -@use '../abstracts/variables.scss' as *; +@use "../abstracts/variables.scss" as *; // Main Container .realTime-viz { - background-color: var(--background-color); - border-radius: 20px; - box-shadow: 0px 4px 8px rgba(60, 60, 67, 0.1019607843); - width: 55%; - height: 600px; - position: absolute; - top: 50%; - left: 48%; - transform: translate(-50%, -50%); + background-color: var(--background-color); + border-radius: 20px; + box-shadow: 0px 4px 8px rgba(60, 60, 67, 0.1019607843); + width: calc(100% - (320px + 270px + 80px)); + height: 600px; + position: absolute; + top: 50%; + left: calc(270px + 40px); + transform: translate(0, -50%); + .icon { + display: flex; + align-items: center; + position: relative; + } + + .icons-container { .icon { - display: flex; - align-items: center; - position: relative; - - &:first-child { - &::after { - content: ""; - display: block; - width: 1px; - height: 18px; - background-color: #000; - margin-top: 10px; - position: absolute; - right: -10px; - top: -4px; - } + &:first-child { + &::after { + display: none; } + } + } + } + + .zoon-wrapper { + display: flex; + background-color: #e0dfff80; + position: absolute; + bottom: 10px; + left: 50%; + transform: translate(-50%, 0); + gap: 6px; + padding: 4px; + border-radius: 8px; + max-width: 80%; + overflow: auto; + + &::-webkit-scrollbar { + display: none; } - .icons-container { - .icon { - &:first-child { - &::after { - display: none; - } - } - } - - - + .zone { + width: auto; + background-color: #fcfdfd; + border-radius: 6px; + padding: 4px 8px; + white-space: nowrap; + font-size: $small; } - .realTimeViz-tools { - position: fixed; - bottom: -150px; - left: 50%; - transform: translateX(-50%); - box-shadow: 0px 4px 8px 0px rgba(60, 60, 67, 0.1); - background: $background-color; - display: flex; - gap: 12px; - border-radius: 12px; - z-index: 1000; - transition: bottom 0.3s ease; - padding: 8px; - - .icons-container { - padding-left: 8px; - display: flex; - align-items: center; - gap: 10px; - } + .active { + background-color: var(--accent-color); + color: var(--background-color); + // color: #FCFDFD !important; } + } + .zoon-wrapper.bottom { + bottom: 210px; + } - .zoon-wrapper { - display: flex; - background-color: #E0DFFF80; - position: absolute; - bottom: 10px; - left: 50%; - transform: translate(-50%, 0); - gap: 6px; - padding: 4px; - border-radius: 8px; - max-width: 80%; - overflow: auto; - - &::-webkit-scrollbar { - display: none; - } - - .zone { - width: auto; - background-color: #FCFDFD; - border-radius: 6px; - padding: 4px 8px; - white-space: nowrap; - font-size: $small; - - } - - .active { - background-color: var(--accent-color); - color: var(--background-color); - // color: #FCFDFD !important; - } - } - - .zoon-wrapper.bottom { - bottom: 210px; - } - - @media (max-width: 1024px) { - width: 80%; // Increase width to take more space on smaller screens - height: 500px; // Reduce height to fit smaller screens - left: 50%; // Center horizontally - - .main-container { - margin: 0 15px; // Reduce margin for better spacing - } - - .zoon-wrapper { - bottom: 5px; // Adjust position for smaller screens - - &.bottom { - bottom: 150px; // Adjust for bottom placement - } - } - } - - @media (max-width: 768px) { - width: 90%; // Take even more width on very small screens - height: 400px; // Further reduce height - top: 45%; // Adjust vertical position slightly upward - - .panel { - - &.top-panel, - &.bottom-panel { - .panel-content { - flex-direction: column; // Stack panels vertically on small screens - - .chart-container { - width: 100%; // Make charts full width - height: 150px; // Reduce chart height - } - } - } - } - } - - @media (max-width: 480px) { - width: 95%; // Take almost full width on very small devices - height: 350px; // Further reduce height - top: 40%; // Move slightly higher for better visibility - - .side-button-container { - flex-direction: row !important; // Force buttons into a row - gap: 4px; // Reduce spacing between buttons - - &.top, - &.bottom { - left: 50%; // Center horizontally - transform: translateX(-50%); - } - } - } - - .content-container { - display: flex; - height: 100vh; - transition: all 0.3s ease; - } + @media (max-width: 1024px) { + width: 80%; // Increase width to take more space on smaller screens + height: 500px; // Reduce height to fit smaller screens + left: 50%; // Center horizontally .main-container { - position: relative; - flex: 1; - height: 600px; - background-color: rgb(235, 235, 235); - margin: 0 30px; - transition: height 0.3s ease, margin 0.3s ease; - - - - .zoon-wrapper { - display: flex; - background-color: rgba(224, 223, 255, 0.5); - position: absolute; - bottom: 10px; - left: 50%; - transform: translate(-50%, 0); - gap: 6px; - padding: 4px; - border-radius: 8px; - max-width: 80%; - overflow: auto; - transition: transform 0.3s ease; - - &::-webkit-scrollbar { - display: none; - } - - .zone { - width: auto; - background-color: $background-color; - border-radius: 6px; - padding: 4px 8px; - white-space: nowrap; - cursor: pointer; - transition: background-color 0.3s ease; - - &.active { - background-color: var(--primary-color); - color: var(--accent-color); - } - } - - &.bottom { - bottom: 210px; - } - } + margin: 0 15px; // Reduce margin for better spacing } + .zoon-wrapper { + bottom: 5px; // Adjust position for smaller screens + + &.bottom { + bottom: 150px; // Adjust for bottom placement + } + } + } + + @media (max-width: 768px) { + width: 90%; // Take even more width on very small screens + height: 400px; // Further reduce height + top: 45%; // Adjust vertical position slightly upward + .panel { - position: absolute; - background: white; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - transition: all 0.3s ease; - border-radius: 6px; - overflow: visible !important; - + &.top-panel, + &.bottom-panel { .panel-content { - position: relative; - height: 100%; - padding: 10px; - overflow: auto; - display: flex; - flex-direction: column; - gap: 10px; + flex-direction: column; // Stack panels vertically on small screens - &::-webkit-scrollbar { - display: none; - } - - .chart-container { - width: 100%; - height: 200px; - max-height: 100%; - border: 1px dotted #a9a9a9; - border-radius: 8px; - box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1); - padding: 6px 0; - background-color: white; - } - - .close-btn { - position: absolute; - top: 5px; - right: 5px; - background: none; - border: none; - cursor: pointer; - color: var(--primary-color); - } - } - - &.top-panel, - &.bottom-panel { - left: 0; - right: 0; - - .panel-content { - display: flex; - flex-direction: row; - - .chart-container { - height: 100%; - width: 230px; - } - } - } - - &.top-panel { - top: 0; - } - - &.bottom-panel { - bottom: 0; - } - - &.left-panel { - left: 0; - top: 0; - bottom: 0; - - .chart-container { - width: 100%; - height: 200px; - } - } - - &.right-panel { - right: 0; - top: 0; - bottom: 0; + .chart-container { + width: 100%; // Make charts full width + height: 150px; // Reduce chart height + } } + } } + } + + @media (max-width: 480px) { + width: 95%; // Take almost full width on very small devices + height: 350px; // Further reduce height + top: 40%; // Move slightly higher for better visibility + + .side-button-container { + flex-direction: row !important; // Force buttons into a row + gap: 4px; // Reduce spacing between buttons + + &.top, + &.bottom { + left: 50%; // Center horizontally + transform: translateX(-50%); + } + } + } + + .content-container { + display: flex; + height: 100vh; + transition: all 0.3s ease; + } + + .main-container { + position: relative; + flex: 1; + height: 600px; + background-color: rgb(235, 235, 235); + margin: 0 30px; + transition: height 0.3s ease, margin 0.3s ease; + + .zoon-wrapper { + display: flex; + background-color: rgba(224, 223, 255, 0.5); + position: absolute; + bottom: 10px; + left: 50%; + transform: translate(-50%, 0); + gap: 6px; + padding: 4px; + border-radius: 8px; + max-width: 80%; + overflow: auto; + transition: transform 0.3s ease; + + &::-webkit-scrollbar { + display: none; + } + + .zone { + width: auto; + background-color: $background-color; + border-radius: 6px; + padding: 4px 8px; + white-space: nowrap; + cursor: pointer; + transition: background-color 0.3s ease; + + &.active { + background-color: var(--primary-color); + color: var(--accent-color); + } + } + + &.bottom { + bottom: 210px; + } + } + } + + .panel { + position: absolute; + background: white; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + border-radius: 6px; + overflow: visible !important; + + .panel-content { + position: relative; + height: 100%; + padding: 10px; + overflow: auto; + display: flex; + flex-direction: column; + gap: 10px; + + &::-webkit-scrollbar { + display: none; + } + + .chart-container { + width: 100%; + height: 200px; + max-height: 100%; + border: 1px dotted #a9a9a9; + border-radius: 8px; + box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1); + padding: 6px 0; + background-color: white; + } + + .close-btn { + position: absolute; + top: 5px; + right: 5px; + background: none; + border: none; + cursor: pointer; + color: var(--primary-color); + } + } + + &.top-panel, + &.bottom-panel { + left: 0; + right: 0; + + .panel-content { + display: flex; + flex-direction: row; + + .chart-container { + height: 100%; + width: 230px; + } + } + } + + &.top-panel { + top: 0; + } + + &.bottom-panel { + bottom: 0; + } + + &.left-panel { + left: 0; + top: 0; + bottom: 0; + + .chart-container { + width: 100%; + height: 200px; + } + } + + &.right-panel { + right: 0; + top: 0; + bottom: 0; + } + } } // Side Buttons .side-button-container { - position: absolute; + position: absolute; + display: flex; + background-color: $background-color; + padding: 5px; + border-radius: 8px; + transition: transform 0.3s ease; + + .extra-Bs { display: flex; - background-color: $background-color; - padding: 5px; - border-radius: 8px; - transition: transform 0.3s ease; + align-items: center; + gap: 12px; - .extra-Bs { - display: flex; - align-items: center; - gap: 12px; - - .icon { - display: flex; - } - - &:hover { - cursor: pointer; - } + .icon { + display: flex; } - .side-button { - cursor: pointer; - transition: background-color 0.3s ease; - width: 18px; - height: 18px; - display: flex; - justify-content: center; - // align-items: center; - background-color: var(--accent-color); - border: none; - color: var(--background-color); - border-radius: 4px; - - &:hover { - // background-color: var(--primary-color); - // color: var(--accent-color); - } + &:hover { + cursor: pointer; } + } - &.top { - top: -30px; - left: 50%; - transform: translateX(-50%); - flex-direction: row; - gap: 6px; - } + .side-button { + cursor: pointer; + transition: background-color 0.3s ease; + width: 18px; + height: 18px; + display: flex; + justify-content: center; + // align-items: center; + background-color: var(--accent-color); + border: none; + color: var(--background-color); + border-radius: 4px; + } - &.right { - right: -30px; - top: 50%; - transform: translateY(-50%); - flex-direction: column; - gap: 6px; - } + &.top { + top: -30px; + left: 50%; + transform: translateX(-50%); + flex-direction: row; + gap: 6px; + } - &.bottom { - bottom: -30px; - left: 50%; - transform: translateX(-50%); - flex-direction: row; - gap: 6px; - } + &.right { + right: -30px; + top: 50%; + transform: translateY(-50%); + flex-direction: column; + gap: 6px; + } - &.left { - left: -30px; - top: 50%; - transform: translateY(-50%); - flex-direction: column; - gap: 6px; - } + &.bottom { + bottom: -30px; + left: 50%; + transform: translateX(-50%); + flex-direction: row; + gap: 6px; + } + + &.left { + left: -30px; + top: 50%; + transform: translateY(-50%); + flex-direction: column; + gap: 6px; + } } .right.side-button-container { - - .extra-Bs { - flex-direction: column; - } - + .extra-Bs { + flex-direction: column; + } } .left.side-button-container { - - .extra-Bs { - flex-direction: column; - } + .extra-Bs { + flex-direction: column; + } } // Theme Container .theme-container { - width: 250px; - padding: 12px; - box-shadow: 1px -3px 4px 0px rgba(0, 0, 0, 0.11); - border-radius: 8px; - background-color: white; - position: absolute; - top: 20px; - right: -100%; - transform: translate(-0%, 0); + width: 250px; + padding: 12px; + box-shadow: 1px -3px 4px 0px rgba(0, 0, 0, 0.11); + border-radius: 8px; + background-color: white; + position: absolute; + top: 20px; + right: -100%; + transform: translate(-0%, 0); - h2 { - font-size: 12px; - margin-bottom: 8px; - color: #2B3344; - } + h2 { + font-size: 12px; + margin-bottom: 8px; + color: #2b3344; + } - .theme-preset-wrapper { - display: flex; - gap: 5px; - flex-wrap: wrap; + .theme-preset-wrapper { + display: flex; + gap: 5px; + flex-wrap: wrap; - .theme-preset { - display: flex; - gap: 2px; - margin-bottom: 10px; - border: 1px solid $border-color; - padding: 5px 10px; - border-radius: 4px; - transition: border 0.3s ease; + .theme-preset { + display: flex; + gap: 2px; + margin-bottom: 10px; + border: 1px solid $border-color; + padding: 5px 10px; + border-radius: 4px; + transition: border 0.3s ease; - &.active { - border: 1px solid var(--primary-color); + &.active { + border: 1px solid var(--primary-color); - &::after { - content: ''; - position: absolute; - top: 1px; - left: 1px; - width: 10px; - height: 10px; - background-color: var(--primary-color); - border-radius: 50%; - } - } + &::after { + content: ""; + position: absolute; + top: 1px; + left: 1px; + width: 10px; + height: 10px; + background-color: var(--primary-color); + border-radius: 50%; } + } } + } - .custom-color { - display: flex; - justify-content: space-between; + .custom-color { + display: flex; + justify-content: space-between; - .color-displayer { - display: flex; - gap: 5px; - align-items: center; - border: 1px solid var(--accent-color); - border-radius: 4px; - padding: 0 5px; + .color-displayer { + display: flex; + gap: 5px; + align-items: center; + border: 1px solid var(--accent-color); + border-radius: 4px; + padding: 0 5px; - input { - border: none; - outline: none; - border-radius: 50%; - } - } + input { + border: none; + outline: none; + border-radius: 50%; + } } -} \ No newline at end of file + } +}