From d60382bf3d1763a1730fdce9a5c5f1e2e54a4485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Ma=C5=82ecki?=
<92953623+p-malecki@users.noreply.github.com>
Date: Mon, 2 Dec 2024 12:51:36 +0100
Subject: [PATCH 1/4] Toolbelt WIP
---
.../components/shared/ToolbeltButton.css | 104 ++++++++++++++++++
.../components/shared/ToolbeltButton.tsx | 65 +++++++++++
.../src/webview/views/PreviewView.tsx | 7 ++
3 files changed, 176 insertions(+)
create mode 100644 packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
create mode 100644 packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
new file mode 100644
index 000000000..e1c8b7dc7
--- /dev/null
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
@@ -0,0 +1,104 @@
+.toolbelt-button-container {
+ display: flex;
+ align-items: center;
+ max-height: 36px;
+ height: 36px;
+}
+
+.toolbelt-button-main-button {
+ cursor: pointer;
+ height: 80%;
+ display: flex;
+ align-items: center;
+ padding: 5px;
+ background: none;
+ border: 0px solid transparent;
+ border-radius: 10px 0px 0px 10px;
+}
+
+.toolbelt-button-main-button:hover {
+ background-color: var(--swm-button-hover);
+}
+.toolbelt-button-main-button:active {
+ color: var(--swm-button-active);
+ background-color: var(--swm-button-active-background);
+ transform: scale(0.9);
+}
+
+.toolbelt-button-select-trigger {
+ cursor: default;
+ height: 100%;
+ background: none;
+ border: 0px solid transparent;
+ border-radius: 0px 10px 10px 0px;
+}
+.toolbelt-button-select-trigger:hover {
+ background-color: var(--swm-button-hover);
+}
+
+.toolbelt-button-select-trigger[data-state="open"] {
+ /* border-radius: 0 0 18px 18px; */
+}
+
+.toolbelt-button-select-trigger[data-disabled] {
+ background-color: var(--swm-device-select-trigger-disabled);
+ color: var(--swm-secondary-text);
+ pointer-events: none;
+}
+
+.toolbelt-button-select-content {
+ background-color: var(--swm-popover-background);
+ border-radius: 6px;
+ padding: 4px;
+ animation-duration: 400ms;
+ animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
+ will-change: transform, opacity;
+ box-shadow: var(--swm-backdrop-shadow);
+ max-height: calc(var(--radix-dropdown-menu-content-available-height) - 40px);
+ overflow-y: auto;
+}
+
+.toolbelt-button-select-content[data-side="bottom"] {
+ animation-name: slideUpAndFade;
+}
+
+.toolbelt-button-select-content[data-side="top"] {
+ animation-name: slideDownAndFade;
+}
+
+.toolbelt-button-select-item {
+ padding: 10px;
+ cursor: pointer;
+}
+
+.toolbelt-button-select-item:hover {
+ background-color: var(--swm-button-hover);
+}
+
+.toolbelt-button-icon {
+ margin-right: 8px;
+}
+
+@keyframes slideUpAndFade {
+ from {
+ opacity: 0;
+ transform: translateY(3px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes slideDownAndFade {
+ from {
+ opacity: 0;
+ transform: translateY(-3px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
new file mode 100644
index 000000000..4b4cabdff
--- /dev/null
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
@@ -0,0 +1,65 @@
+import React, { useState } from "react";
+import * as Select from "@radix-ui/react-select";
+import "./ToolbeltButton.css";
+
+
+export interface ToolbeltOption {
+ value: string;
+ label: string;
+ icon?: React.ReactNode;
+}
+
+interface ToolbeltButtonProps {
+ options: ToolbeltOption[],
+ defaultOptionIndex?: number,
+ onSelect: (value: string) => void,
+}
+
+function ToolbeltButton({
+ options,
+ defaultOptionIndex = 0,
+ onSelect,
+}: ToolbeltButtonProps) {
+
+ const [selectedOption, setSelectedOption] = useState(options[defaultOptionIndex]);
+
+ const handleSelect = (value: string) => {
+ const selected = options.find(option => option.value === value);
+ setSelectedOption(selected || options[defaultOptionIndex]);
+ onSelect(value);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {options.map((option) => (
+
+
+ {option.icon && {option.icon}}
+ {option.label}
+
+
+ ))}
+
+
+
+
+
+ );
+}
+
+export default ToolbeltButton;
diff --git a/packages/vscode-extension/src/webview/views/PreviewView.tsx b/packages/vscode-extension/src/webview/views/PreviewView.tsx
index dec91306f..e88b0d5f2 100644
--- a/packages/vscode-extension/src/webview/views/PreviewView.tsx
+++ b/packages/vscode-extension/src/webview/views/PreviewView.tsx
@@ -14,6 +14,7 @@ import { useProject } from "../providers/ProjectProvider";
import DeviceSelect from "../components/DeviceSelect";
import { InspectDataMenu } from "../components/InspectDataMenu";
import Button from "../components/shared/Button";
+import ToolbeltButton, { ToolbeltOption } from "../components/shared/ToolbeltButton";
import {
Frame,
InspectDataStackItem,
@@ -205,11 +206,17 @@ function PreviewView() {
.toString()
.padStart(2, "0")}`;
+
+ const toolbeltOptions: ToolbeltOption[] = [
+ { value: "tool1", label: "tool1", icon: },
+ ];
+
return (
+ {
{}} />}
{
Date: Mon, 2 Dec 2024 19:42:25 +0100
Subject: [PATCH 2/4] WIP 2
---
.../components/shared/ToolbeltButton.css | 45 +++----------
.../components/shared/ToolbeltButton.tsx | 65 ++++++++-----------
.../src/webview/views/PreviewView.tsx | 43 +++++++++++-
3 files changed, 78 insertions(+), 75 deletions(-)
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
index e1c8b7dc7..2f5b41ca2 100644
--- a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
@@ -36,8 +36,15 @@
background-color: var(--swm-button-hover);
}
-.toolbelt-button-select-trigger[data-state="open"] {
- /* border-radius: 0 0 18px 18px; */
+.toolbelt-button-select-trigger-value {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
}
.toolbelt-button-select-trigger[data-disabled] {
@@ -50,22 +57,12 @@
background-color: var(--swm-popover-background);
border-radius: 6px;
padding: 4px;
- animation-duration: 400ms;
- animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
will-change: transform, opacity;
box-shadow: var(--swm-backdrop-shadow);
max-height: calc(var(--radix-dropdown-menu-content-available-height) - 40px);
overflow-y: auto;
}
-.toolbelt-button-select-content[data-side="bottom"] {
- animation-name: slideUpAndFade;
-}
-
-.toolbelt-button-select-content[data-side="top"] {
- animation-name: slideDownAndFade;
-}
-
.toolbelt-button-select-item {
padding: 10px;
cursor: pointer;
@@ -78,27 +75,3 @@
.toolbelt-button-icon {
margin-right: 8px;
}
-
-@keyframes slideUpAndFade {
- from {
- opacity: 0;
- transform: translateY(3px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-@keyframes slideDownAndFade {
- from {
- opacity: 0;
- transform: translateY(-3px);
- }
-
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
index 4b4cabdff..b0f225696 100644
--- a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
@@ -1,63 +1,54 @@
import React, { useState } from "react";
-import * as Select from "@radix-ui/react-select";
+import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import "./ToolbeltButton.css";
-
export interface ToolbeltOption {
- value: string;
label: string;
+ button: React.ReactNode;
icon?: React.ReactNode;
}
interface ToolbeltButtonProps {
- options: ToolbeltOption[],
- defaultOptionIndex?: number,
- onSelect: (value: string) => void,
+ options: ToolbeltOption[];
+ defaultOptionIndex?: number;
+ disabled?: boolean;
}
function ToolbeltButton({
options,
defaultOptionIndex = 0,
- onSelect,
+ disabled = false,
}: ToolbeltButtonProps) {
-
const [selectedOption, setSelectedOption] = useState(options[defaultOptionIndex]);
- const handleSelect = (value: string) => {
- const selected = options.find(option => option.value === value);
- setSelectedOption(selected || options[defaultOptionIndex]);
- onSelect(value);
- };
+ const handleSelect = (option: ToolbeltOption) => {
+ setSelectedOption(option);
+ };
return (
-
);
}
diff --git a/packages/vscode-extension/src/webview/views/PreviewView.tsx b/packages/vscode-extension/src/webview/views/PreviewView.tsx
index e88b0d5f2..4cd27be1b 100644
--- a/packages/vscode-extension/src/webview/views/PreviewView.tsx
+++ b/packages/vscode-extension/src/webview/views/PreviewView.tsx
@@ -208,15 +208,54 @@ function PreviewView() {
const toolbeltOptions: ToolbeltOption[] = [
- { value: "tool1", label: "tool1", icon: },
+ {
+ label: "tool1",
+ button: (
+ {
+ }}
+ tooltip={{
+ label: "Open logs panel",
+ }}
+ disabled={devicesNotFound}>
+
+
+ ),
+ icon: ,
+ },
];
+ // const toolbeltOptions: ToolbeltOption[] = [
+ // {
+ // value: "tool1",
+ // label: "tool1",
+ // icon: (
+ //
+ // {isRecording ? (
+ //
+ //
+ //
{recordingTimeFormat}
+ //
+ // ) : (
+ //
+ // )}
+ //
+ // ),
+ // },
+ // ];
+
return (
- {
{}} />}
+ {}
{
Date: Tue, 3 Dec 2024 14:17:32 +0100
Subject: [PATCH 3/4] Finish Toolbelt
---
.../components/shared/ToolbeltButton.css | 63 +++++++------
.../components/shared/ToolbeltButton.tsx | 56 ++++++-----
.../src/webview/views/PreviewView.tsx | 93 ++++++++++---------
3 files changed, 113 insertions(+), 99 deletions(-)
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
index 2f5b41ca2..1f390c5b4 100644
--- a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.css
@@ -7,10 +7,10 @@
.toolbelt-button-main-button {
cursor: pointer;
- height: 80%;
+ height: 28px;
display: flex;
align-items: center;
- padding: 5px;
+ padding: 5px 0px;
background: none;
border: 0px solid transparent;
border-radius: 10px 0px 0px 10px;
@@ -25,53 +25,56 @@
transform: scale(0.9);
}
-.toolbelt-button-select-trigger {
+.toolbelt-button-dropdown-trigger {
cursor: default;
height: 100%;
background: none;
border: 0px solid transparent;
border-radius: 0px 10px 10px 0px;
}
-.toolbelt-button-select-trigger:hover {
+.toolbelt-button-dropdown-trigger:hover {
background-color: var(--swm-button-hover);
}
-
-.toolbelt-button-select-trigger-value {
- position: absolute;
- width: 1px;
- height: 1px;
- margin: -1px;
- padding: 0;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-
-.toolbelt-button-select-trigger[data-disabled] {
- background-color: var(--swm-device-select-trigger-disabled);
+.toolbelt-button-dropdown-trigger[data-disabled] {
color: var(--swm-secondary-text);
pointer-events: none;
}
+.toolbelt-button-dropdown-trigger[data-state="open"] {
+ background: var(--swm-dropdown-item-highlighted);
+ border-radius: 0px 10px 0px 0px;
+}
-.toolbelt-button-select-content {
- background-color: var(--swm-popover-background);
- border-radius: 6px;
- padding: 4px;
- will-change: transform, opacity;
+.toolbelt-button-dropdown-content {
+ background: var(--swm-popover-background);
+ border-radius: 7px 0px 7px 7px;
+ padding: 5px;
box-shadow: var(--swm-backdrop-shadow);
max-height: calc(var(--radix-dropdown-menu-content-available-height) - 40px);
+ min-width: 150px;
overflow-y: auto;
}
-.toolbelt-button-select-item {
- padding: 10px;
- cursor: pointer;
+.toolbelt-button-dropdown-item-wraper {
+ display: flex;
+ width: 100%;
+ align-items: center;
+ gap: 8px;
}
-.toolbelt-button-select-item:hover {
- background-color: var(--swm-button-hover);
+.toolbelt-button-dropdown-item-wraper:hover {
+ background-color: var(--swm-dropdown-item-highlighted);
+ outline: none;
}
-.toolbelt-button-icon {
- margin-right: 8px;
+.toolbelt-button-dropdown-item-content {
+ color: var(--swm-default-text);
+ font-size: 13px;
+ line-height: 1;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ height: 28px;
+ width: 100%;
+ gap: 5px;
}
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
index b0f225696..e80a8dcd9 100644
--- a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
@@ -4,8 +4,9 @@ import "./ToolbeltButton.css";
export interface ToolbeltOption {
label: string;
- button: React.ReactNode;
- icon?: React.ReactNode;
+ component: React.ReactElement;
+ dropdownIcon: React.ReactNode;
+ keybinding?: React.ReactNode;
}
interface ToolbeltButtonProps {
@@ -19,35 +20,44 @@ function ToolbeltButton({
defaultOptionIndex = 0,
disabled = false,
}: ToolbeltButtonProps) {
- const [selectedOption, setSelectedOption] = useState(options[defaultOptionIndex]);
+ const [selectedOptionIndex, setSelectedOptionIndex] = useState(defaultOptionIndex);
- const handleSelect = (option: ToolbeltOption) => {
- setSelectedOption(option);
- };
+ const handleSelect = (option: ToolbeltOption) => {
+ const index = options.findIndex((o) => o.label === option.label);
+ setSelectedOptionIndex(index);
+ };
return (
-
- {selectedOption.button}
-
+ {React.cloneElement(options[selectedOptionIndex].component, {
+ className: `toolbelt-button-main-button ${options[selectedOptionIndex].component.props.className}`,
+ })}
-
+
-
- {options.map((option) => (
- handleSelect(option)}
- className="toolbelt-button-dropdown-item">
-
- {option.icon && {option.icon}}
- {option.label}
-
-
- ))}
-
+
+
+ {options.map((option) => (
+ handleSelect(option)}
+ className="toolbelt-button-select-item">
+
+ {option.dropdownIcon && {option.dropdownIcon}}
+
+ {option.label}
+ {options[selectedOptionIndex].keybinding}
+
+
+
+ ))}
+
+
);
diff --git a/packages/vscode-extension/src/webview/views/PreviewView.tsx b/packages/vscode-extension/src/webview/views/PreviewView.tsx
index 4cd27be1b..e42d7a361 100644
--- a/packages/vscode-extension/src/webview/views/PreviewView.tsx
+++ b/packages/vscode-extension/src/webview/views/PreviewView.tsx
@@ -14,7 +14,7 @@ import { useProject } from "../providers/ProjectProvider";
import DeviceSelect from "../components/DeviceSelect";
import { InspectDataMenu } from "../components/InspectDataMenu";
import Button from "../components/shared/Button";
-import ToolbeltButton, { ToolbeltOption } from "../components/shared/ToolbeltButton";
+import ToolbeltButton from "../components/shared/ToolbeltButton";
import {
Frame,
InspectDataStackItem,
@@ -29,6 +29,7 @@ import "./PreviewView.css";
import ReplayIcon from "../components/icons/ReplayIcon";
import RecordingIcon from "../components/icons/RecordingIcon";
import { ActivateLicenseView } from "./ActivateLicenseView";
+import { KeybindingInfo } from "../components/shared/KeybindingInfo";
const MAX_RECORDING_TIME_SEC = 10 * 60;
@@ -206,56 +207,56 @@ function PreviewView() {
.toString()
.padStart(2, "0")}`;
-
- const toolbeltOptions: ToolbeltOption[] = [
- {
- label: "tool1",
- button: (
- {
- }}
- tooltip={{
- label: "Open logs panel",
- }}
- disabled={devicesNotFound}>
-
-
- ),
- icon: ,
- },
- ];
-
- // const toolbeltOptions: ToolbeltOption[] = [
- // {
- // value: "tool1",
- // label: "tool1",
- // icon: (
- //
- // {isRecording ? (
- //
- //
- //
{recordingTimeFormat}
- //
- // ) : (
- //
- // )}
- //
- // ),
- // },
- // ];
-
return (
- {
}
+ {
+
+ {isRecording ? (
+
+
+
{recordingTimeFormat}
+
+ ) : (
+
+ )}
+
+ ),
+ dropdownIcon: ,
+ keybinding: ,
+ },
+ {
+ label: "Screenshot",
+ component: (
+ {
+ console.log("FRYTKI screenshot");
+ }}>
+
+
+ ),
+ dropdownIcon: ,
+ keybinding: ,
+ },
+ ]}
+ disabled={devicesNotFound || isStarting}
+ />
+ }
{
Date: Tue, 3 Dec 2024 14:28:27 +0100
Subject: [PATCH 4/4] Move example to ToolbeltButton
---
.../components/shared/ToolbeltButton.tsx | 47 +++++++++++++++++++
.../src/webview/views/PreviewView.tsx | 47 -------------------
2 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
index e80a8dcd9..a0e97d45f 100644
--- a/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
+++ b/packages/vscode-extension/src/webview/components/shared/ToolbeltButton.tsx
@@ -64,3 +64,50 @@ function ToolbeltButton({
}
export default ToolbeltButton;
+
+// EXAMPLE USAGE (WITH RECORDING AND SCREENSHOTS TOOLS):
+/*
+ {
+
+ {isRecording ? (
+
+
+
{recordingTimeFormat}
+
+ ) : (
+
+ )}
+
+ ),
+ dropdownIcon: ,
+ keybinding: , // TODO add shortcuts
+ },
+ {
+ label: "Screenshot",
+ component: (
+ {}}>
+
+
+ ),
+ dropdownIcon: ,
+ keybinding: , // TODO add shortcuts
+ },
+ ]}
+ disabled={devicesNotFound || isStarting}
+ />;
+ }
+ */
diff --git a/packages/vscode-extension/src/webview/views/PreviewView.tsx b/packages/vscode-extension/src/webview/views/PreviewView.tsx
index e42d7a361..dec91306f 100644
--- a/packages/vscode-extension/src/webview/views/PreviewView.tsx
+++ b/packages/vscode-extension/src/webview/views/PreviewView.tsx
@@ -14,7 +14,6 @@ import { useProject } from "../providers/ProjectProvider";
import DeviceSelect from "../components/DeviceSelect";
import { InspectDataMenu } from "../components/InspectDataMenu";
import Button from "../components/shared/Button";
-import ToolbeltButton from "../components/shared/ToolbeltButton";
import {
Frame,
InspectDataStackItem,
@@ -29,7 +28,6 @@ import "./PreviewView.css";
import ReplayIcon from "../components/icons/ReplayIcon";
import RecordingIcon from "../components/icons/RecordingIcon";
import { ActivateLicenseView } from "./ActivateLicenseView";
-import { KeybindingInfo } from "../components/shared/KeybindingInfo";
const MAX_RECORDING_TIME_SEC = 10 * 60;
@@ -212,51 +210,6 @@ function PreviewView() {
- {
-
- {isRecording ? (
-
-
-
{recordingTimeFormat}
-
- ) : (
-
- )}
-
- ),
- dropdownIcon: ,
- keybinding: ,
- },
- {
- label: "Screenshot",
- component: (
- {
- console.log("FRYTKI screenshot");
- }}>
-
-
- ),
- dropdownIcon: ,
- keybinding: ,
- },
- ]}
- disabled={devicesNotFound || isStarting}
- />
- }
{