Skip to content

Commit

Permalink
Add configurable control panel width (#123)
Browse files Browse the repository at this point in the history
* Add configurable control panel width

* Tweak comment
  • Loading branch information
brentyi authored Oct 27, 2023
1 parent 82ba676 commit 93e2699
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 9 deletions.
5 changes: 5 additions & 0 deletions examples/13_theming.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@
control_layout = server.add_gui_dropdown(
"Control layout", ("floating", "fixed", "collapsible")
)
control_width = server.add_gui_dropdown(
"Control width", ("small", "medium", "large"), initial_value="medium"
)
synchronize = server.add_gui_button("Apply theme", icon=viser.Icon.CHECK)


def synchronize_theme() -> None:
server.configure_theme(
titlebar_content=titlebar_theme if titlebar.value else None,
control_layout=control_layout.value,
control_width=control_width.value,
dark_mode=dark_mode.value,
show_logo=show_logo.value,
brand_color=brand_color.value,
Expand All @@ -70,6 +74,7 @@ def synchronize_theme() -> None:
server.configure_theme(
titlebar_content={"titlebar_content" if titlebar.value else None},
control_layout="{control_layout.value}",
control_width="{control_width.value}",
dark_mode={dark_mode.value},
show_logo={show_logo.value},
brand_color={brand_color.value},
Expand Down
2 changes: 2 additions & 0 deletions src/viser/_message_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def configure_theme(
*,
titlebar_content: Optional[theme.TitlebarConfig] = None,
control_layout: Literal["floating", "collapsible", "fixed"] = "floating",
control_width: Literal["small", "medium", "large"] = "medium",
dark_mode: bool = False,
show_logo: bool = True,
brand_color: Optional[Tuple[int, int, int]] = None,
Expand Down Expand Up @@ -224,6 +225,7 @@ def configure_theme(
_messages.ThemeConfigurationMessage(
titlebar_content=titlebar_content,
control_layout=control_layout,
control_width=control_width,
dark_mode=dark_mode,
show_logo=show_logo,
colors=colors_cast,
Expand Down
1 change: 1 addition & 0 deletions src/viser/_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ class ThemeConfigurationMessage(Message):

titlebar_content: Optional[theme.TitlebarConfig]
control_layout: Literal["floating", "collapsible", "fixed"]
control_width: Literal["small", "medium", "large"]
show_logo: bool
dark_mode: bool
colors: Optional[Tuple[str, str, str, str, str, str, str, str, str, str]]
Expand Down
20 changes: 18 additions & 2 deletions src/viser/client/src/ControlPanel/ControlPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ export default function ControlPanel(props: {
);
const [showSettings, { toggle }] = useDisclosure(false);

const controlWidthString = viewer.useGui(
(state) => state.theme.control_width,
);
const controlWidth = (
controlWidthString == "small"
? "16em"
: controlWidthString == "medium"
? "20em"
: controlWidthString == "large"
? "24em"
: null
)!;

const generatedServerToggleButton = (
<Box sx={{ display: showGenerated ? undefined : "none" }}>
<ActionIcon
Expand Down Expand Up @@ -88,7 +101,7 @@ export default function ControlPanel(props: {
} else if (props.control_layout === "floating") {
/* Floating layout. */
return (
<FloatingPanel>
<FloatingPanel width={controlWidth}>
<FloatingPanel.Handle>
<ConnectionStatus />
<FloatingPanel.HideWhenCollapsed>
Expand All @@ -101,7 +114,10 @@ export default function ControlPanel(props: {
} else {
/* Sidebar view. */
return (
<SidebarPanel collapsible={props.control_layout === "collapsible"}>
<SidebarPanel
width={controlWidth}
collapsible={props.control_layout === "collapsible"}
>
<SidebarPanel.Handle>
<ConnectionStatus />
{generatedServerToggleButton}
Expand Down
12 changes: 8 additions & 4 deletions src/viser/client/src/ControlPanel/FloatingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDisclosure } from "@mantine/hooks";
const FloatingPanelContext = React.createContext<null | {
wrapperRef: React.RefObject<HTMLDivElement>;
expanded: boolean;
width: string;
maxHeight: number;
toggleExpanded: () => void;
dragHandler: (
Expand All @@ -27,8 +28,10 @@ const FloatingPanelContext = React.createContext<null | {
/** A floating panel for displaying controls. */
export default function FloatingPanel({
children,
width,
}: {
children: string | React.ReactNode;
width: string;
}) {
const panelWrapperRef = React.useRef<HTMLDivElement>(null);
const [expanded, { toggle: toggleExpanded }] = useDisclosure(true);
Expand Down Expand Up @@ -202,6 +205,7 @@ export default function FloatingPanel({
value={{
wrapperRef: panelWrapperRef,
expanded: expanded,
width: width,
maxHeight: maxHeight,
toggleExpanded: toggleExpanded,
dragHandler: dragHandler,
Expand All @@ -213,7 +217,7 @@ export default function FloatingPanel({
shadow="lg"
sx={{
boxSizing: "border-box",
width: "20em",
width: width,
zIndex: 10,
position: "absolute",
top: "1em",
Expand Down Expand Up @@ -286,11 +290,11 @@ FloatingPanel.Contents = function FloatingPanelContents({
const context = React.useContext(FloatingPanelContext)!;
return (
<Collapse in={context.expanded}>
<ScrollArea.Autosize mah={context!.maxHeight}>
<ScrollArea.Autosize mah={context.maxHeight}>
<Box
/* Prevent internals from getting too wide. Hardcoded to match the
/* Prevent internals from getting too wide. Needs to match the
* width of the wrapper element above. */
w="20em"
w={context.width}
>
{children}
</Box>
Expand Down
1 change: 1 addition & 0 deletions src/viser/client/src/ControlPanel/GuiState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const cleanGuiState: GuiState = {
type: "ThemeConfigurationMessage",
titlebar_content: null,
control_layout: "floating",
control_width: "medium",
dark_mode: false,
show_logo: true,
colors: null,
Expand Down
8 changes: 5 additions & 3 deletions src/viser/client/src/ControlPanel/SidebarPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export const SidebarPanelContext = React.createContext<null | {
export default function SidebarPanel({
children,
collapsible,
width,
}: {
children: string | React.ReactNode;
collapsible: boolean;
width: string;
}) {
const [collapsed, { toggle: toggleCollapsed }] = useDisclosure(false);

Expand Down Expand Up @@ -65,16 +67,16 @@ export default function SidebarPanel({
shadow="xl"
component={ScrollArea}
sx={{
width: collapsed ? 0 : "20em",
width: collapsed ? 0 : width,
boxSizing: "content-box",
transition: "width 0.5s 0s",
zIndex: 10,
}}
>
<Box
/* Prevent DOM reflow, as well as internals from getting too wide.
* Hardcoded to match the width of the wrapper element above. */
w="20em"
* Needs to match the width of the wrapper element above. */
w={width}
>
{children}
</Box>
Expand Down
1 change: 1 addition & 0 deletions src/viser/client/src/WebsocketMessages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ export interface ThemeConfigurationMessage {
} | null;
} | null;
control_layout: "floating" | "collapsible" | "fixed";
control_width: "small" | "medium" | "large";
show_logo: boolean;
dark_mode: boolean;
colors:
Expand Down

0 comments on commit 93e2699

Please sign in to comment.