Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ToolbeltButton with tool switching capability #819

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
.toolbelt-button-container {
display: flex;
align-items: center;
max-height: 36px;
height: 36px;
}

.toolbelt-button-main-button {
cursor: pointer;
height: 28px;
display: flex;
align-items: center;
padding: 5px 0px;
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-dropdown-trigger {
cursor: default;
height: 100%;
background: none;
border: 0px solid transparent;
border-radius: 0px 10px 10px 0px;
}
.toolbelt-button-dropdown-trigger:hover {
background-color: var(--swm-button-hover);
}
.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-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-dropdown-item-wraper {
display: flex;
width: 100%;
align-items: center;
gap: 8px;
}

.toolbelt-button-dropdown-item-wraper:hover {
background-color: var(--swm-dropdown-item-highlighted);
outline: none;
}

.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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import React, { useState } from "react";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import "./ToolbeltButton.css";

export interface ToolbeltOption {
label: string;
component: React.ReactElement;
dropdownIcon: React.ReactNode;
keybinding?: React.ReactNode;
}

interface ToolbeltButtonProps {
options: ToolbeltOption[];
defaultOptionIndex?: number;
disabled?: boolean;
}

function ToolbeltButton({
options,
defaultOptionIndex = 0,
disabled = false,
}: ToolbeltButtonProps) {
const [selectedOptionIndex, setSelectedOptionIndex] = useState(defaultOptionIndex);

const handleSelect = (option: ToolbeltOption) => {
const index = options.findIndex((o) => o.label === option.label);
setSelectedOptionIndex(index);
};

return (
<div className="toolbelt-button-container">
{React.cloneElement(options[selectedOptionIndex].component, {
className: `toolbelt-button-main-button ${options[selectedOptionIndex].component.props.className}`,
})}

<DropdownMenu.Root>
<DropdownMenu.Trigger disabled={disabled} className="toolbelt-button-dropdown-trigger">
<span className="codicon codicon-chevron-down" />
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content
className="dropdown-menu-content toolbelt-button-dropdown-content"
side="bottom"
align="end">
{options.map((option) => (
<DropdownMenu.Item
key={option.label}
onClick={() => handleSelect(option)}
className="toolbelt-button-select-item">
<span className="toolbelt-button-dropdown-item-wraper">
{option.dropdownIcon && <span className="icon">{option.dropdownIcon}</span>}
<div className="toolbelt-button-dropdown-item-content">
<span>{option.label}</span>
{options[selectedOptionIndex].keybinding}
</div>
</span>
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
</div>
);
}

export default ToolbeltButton;

// EXAMPLE USAGE (WITH RECORDING AND SCREENSHOTS TOOLS):
/*
{
<ToolbeltButton
options={[
{
label: "Record",
component: (
<IconButton
className={isRecording ? "button-recording-on" : ""}
tooltip={{
label: isRecording ? "Stop screen recording" : "Start screen recording",
}}
onClick={toggleRecording}>
{isRecording ? (
<div className="recording-rec-indicator">
<div className="recording-rec-dot" />
<span>{recordingTimeFormat}</span>
</div>
) : (
<RecordingIcon />
)}
</IconButton>
),
dropdownIcon: <RecordingIcon />,
keybinding: <KeybindingInfo commandName="RNIDE.openDevMenu" />, // TODO add shortcuts
},
{
label: "Screenshot",
component: (
<IconButton
tooltip={{
label: "Take screenshot",
}}
onClick={() => {}}>
<span slot="start" className="codicon codicon-device-camera" />
</IconButton>
),
dropdownIcon: <span slot="start" className="codicon codicon-device-camera" />,
keybinding: <KeybindingInfo commandName="RNIDE.openDevMenu" />, // TODO add shortcuts
},
]}
disabled={devicesNotFound || isStarting}
/>;
}
*/
Loading