WIP expose button type picker

This commit is contained in:
Keavon Chambers
2026-05-13 21:07:21 -07:00
parent 696b625a3e
commit 47f2936ef3
10 changed files with 225 additions and 37 deletions
@@ -37,6 +37,8 @@
export let interactive = false;
export let scrollableY = false;
export let virtualScrolling = false;
// Use `Popover` to draw a tail pointing at the spawner. Defaults to `Dropdown` (no tail), which the menu bar uses. Recursive submenus always use `Dropdown`.
export let type: "Dropdown" | "Popover" = "Dropdown";
// Keep the child references outside of the entries array so as to avoid infinite recursion.
let childReferences: MenuList[][] = [];
@@ -453,7 +455,7 @@
{open}
on:open={({ detail }) => (open = detail)}
on:naturalWidth
type="Dropdown"
{type}
windowEdgeMargin={0}
escapeCloses={false}
{direction}
@@ -611,8 +611,8 @@
}
}
&.top.dropdown .floating-menu-container,
&.bottom.dropdown .floating-menu-container {
&.top.dropdown > .floating-menu-container,
&.bottom.dropdown > .floating-menu-container {
justify-content: left;
}
@@ -709,22 +709,22 @@
}
}
&.top .floating-menu-container {
&.top > .floating-menu-container {
justify-content: center;
margin-bottom: var(--floating-menu-content-offset);
}
&.bottom .floating-menu-container {
&.bottom > .floating-menu-container {
justify-content: center;
margin-top: var(--floating-menu-content-offset);
}
&.left .floating-menu-container {
&.left > .floating-menu-container {
align-items: center;
margin-right: var(--floating-menu-content-offset);
}
&.right .floating-menu-container {
&.right > .floating-menu-container {
align-items: center;
margin-left: var(--floating-menu-content-offset);
}
@@ -167,7 +167,7 @@
component: ParameterExposeButton,
getProps: (props, index) => ({
...props,
action: () => widgetValueCommitAndUpdate(index, undefined, true),
$$events: { selectedEntryValuePath: (e: CustomEvent) => widgetValueCommitAndUpdate(index, e.detail, false) },
}),
},
IconButton: {
@@ -1,27 +1,44 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import MenuList from "/src/components/floating-menus/MenuList.svelte";
import LayoutRow from "/src/components/layout/LayoutRow.svelte";
import type { FrontendGraphDataType, ActionShortcut } from "/wrapper/pkg/graphite_wasm_wrapper";
import type { FrontendGraphDataType, ActionShortcut, MenuListEntry } from "/wrapper/pkg/graphite_wasm_wrapper";
const dispatch = createEventDispatcher<{ selectedEntryValuePath: string[] }>();
let self: MenuList;
// Content
export let exposed: boolean;
export let dataType: FrontendGraphDataType;
// Children
export let menuListChildren: MenuListEntry[][] = [];
export let menuListChildrenHash: bigint = 0n;
// Tooltips
export let tooltipLabel: string | undefined = undefined;
export let tooltipDescription: string | undefined = undefined;
export let tooltipShortcut: ActionShortcut | undefined = undefined;
// Callbacks
export let action: (e?: MouseEvent) => void;
function onClick(e: MouseEvent) {
// Focus the target so that keyboard inputs are sent to the dropdown
if (e.target instanceof HTMLElement) e.target.focus();
// Open the menu list floating menu
if (self) self.open = true;
}
</script>
<LayoutRow class="parameter-expose-button">
<button
class:exposed
class:open={self?.open}
style:--data-type-color={`var(--color-data-${dataType.toLowerCase()})`}
style:--data-type-color-dim={`var(--color-data-${dataType.toLowerCase()}-dim)`}
on:click={action}
on:click={onClick}
data-tooltip-label={tooltipLabel}
data-tooltip-description={tooltipDescription}
data-tooltip-shortcut={tooltipShortcut?.shortcut ? JSON.stringify(tooltipShortcut.shortcut) : undefined}
data-floating-menu-spawner
tabindex="-1"
>
{#if !exposed}
@@ -42,6 +59,16 @@
</svg>
{/if}
</button>
<MenuList
on:selectedEntryValuePath={({ detail }) => dispatch("selectedEntryValuePath", detail)}
open={false}
entries={menuListChildren}
entriesHash={menuListChildrenHash}
direction="Bottom"
type="Popover"
drawIcon={true}
bind:this={self}
/>
</LayoutRow>
<style lang="scss">
@@ -49,6 +76,7 @@
display: flex;
align-items: center;
flex: 0 0 auto;
position: relative;
max-height: 24px;
button {
@@ -70,7 +98,8 @@
fill: var(--data-type-color);
}
&:hover {
&:hover,
&.open {
.outline {
fill: var(--data-type-color);
}
@@ -80,5 +109,12 @@
}
}
}
// Anchor the floating menu's tail to the bottom-center of the small button.
// Scoped to the direct child so nested submenu floating menus aren't affected.
> :global(.floating-menu) {
left: 50%;
bottom: 0;
}
}
</style>
+6 -2
View File
@@ -126,6 +126,9 @@ import Copy from "/../branding/assets/icon-16px-solid/copy.svg";
import Credits from "/../branding/assets/icon-16px-solid/credits.svg";
import CustomColor from "/../branding/assets/icon-16px-solid/custom-color.svg";
import Cut from "/../branding/assets/icon-16px-solid/cut.svg";
import DataSourceGraph from "/../branding/assets/icon-16px-solid/data-source-graph.svg";
import DataSourceTimeline from "/../branding/assets/icon-16px-solid/data-source-timeline.svg";
import DataSourceValue from "/../branding/assets/icon-16px-solid/data-source-value.svg";
import DeselectAll from "/../branding/assets/icon-16px-solid/deselect-all.svg";
import Edit from "/../branding/assets/icon-16px-solid/edit.svg";
import Empty from "/../branding/assets/icon-16px-solid/empty.svg";
@@ -192,7 +195,6 @@ import Save from "/../branding/assets/icon-16px-solid/save.svg";
import SelectAll from "/../branding/assets/icon-16px-solid/select-all.svg";
import SelectParent from "/../branding/assets/icon-16px-solid/select-parent.svg";
import Settings from "/../branding/assets/icon-16px-solid/settings.svg";
import SmallDot from "/../branding/assets/icon-16px-solid/small-dot.svg";
import StackBottom from "/../branding/assets/icon-16px-solid/stack-bottom.svg";
import StackHollow from "/../branding/assets/icon-16px-solid/stack-hollow.svg";
import StackLower from "/../branding/assets/icon-16px-solid/stack-lower.svg";
@@ -265,6 +267,9 @@ const SOLID_16PX = {
Credits: { svg: Credits, size: 16 },
CustomColor: { svg: CustomColor, size: 16 },
Cut: { svg: Cut, size: 16 },
DataSourceGraph: { svg: DataSourceGraph, size: 16 },
DataSourceTimeline: { svg: DataSourceTimeline, size: 16 },
DataSourceValue: { svg: DataSourceValue, size: 16 },
DeselectAll: { svg: DeselectAll, size: 16 },
Edit: { svg: Edit, size: 16 },
Empty: { svg: Empty, size: 16 },
@@ -331,7 +336,6 @@ const SOLID_16PX = {
SelectAll: { svg: SelectAll, size: 16 },
SelectParent: { svg: SelectParent, size: 16 },
Settings: { svg: Settings, size: 16 },
SmallDot: { svg: SmallDot, size: 16 },
Stack: { svg: Stack, size: 16 },
StackBottom: { svg: StackBottom, size: 16 },
StackHollow: { svg: StackHollow, size: 16 },