mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-26 19:38:13 +08:00
WIP expose button type picker
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user