Polish up the Layers panel design

This commit is contained in:
Keavon Chambers
2024-04-01 02:09:01 -07:00
parent 5bab38e173
commit 938a688fa0
17 changed files with 217 additions and 28 deletions
+11
View File
@@ -69,6 +69,7 @@
:root {
// Replace usage of `-rgb` variants with CSS color() function to calculate alpha when browsers support it
// See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color() and https://caniuse.com/css-color-function
// Specifically, support for the relative syntax is needed: `color(from var(--color-0-black) srgb r g b / 0.5)` to convert black to 50% alpha
--color-0-black: #000;
--color-0-black-rgb: 0, 0, 0;
--color-1-nearblack: #111;
@@ -138,6 +139,16 @@
--color-transparent-checkered-background-size: 16px 16px;
--color-transparent-checkered-background-position: 0 0, 8px 8px;
--background-inactive-stripes: repeating-linear-gradient(
-45deg,
transparent 0px,
transparent calc((3px * sqrt(2) / 2) - 0.5px),
var(--color-5-dullgray) calc((3px * sqrt(2) / 2) - 0.5px),
var(--color-5-dullgray) calc((3px * sqrt(2) / 2) + 0.5px),
transparent calc((3px * sqrt(2) / 2) + 0.5px),
transparent calc(6px * sqrt(2) / 2)
);
// Arrow triangle (#eee fill)
--icon-expand-collapse-arrow: url('data:image/svg+xml;utf8,\
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8"><polygon fill="%23eee" points="3,0 1,0 5,4 1,8 3,8 7,4" /></svg>\
@@ -6,6 +6,7 @@
export { styleName as style };
export let styles: Record<string, string | number | undefined> = {};
export let tooltip: string | undefined = undefined;
// TODO: Add middle-click drag scrolling
export let scrollableX = false;
export let scrollableY = false;
@@ -6,6 +6,7 @@
export { styleName as style };
export let styles: Record<string, string | number | undefined> = {};
export let tooltip: string | undefined = undefined;
// TODO: Add middle-click drag scrolling
export let scrollableX = false;
export let scrollableY = false;
+66 -22
View File
@@ -377,6 +377,7 @@
classes={{
selected: fakeHighlight !== undefined ? fakeHighlight === listing.entry.id : $nodeGraph.selected.includes(listing.entry.id),
"insert-folder": (draggingData?.highlightFolder || false) && draggingData?.insertParentId === listing.entry.id,
"nesting-layer": isNestingLayer(listing.entry.layerClassification),
}}
styles={{ "--layer-indent-levels": `${listing.entry.depth - 1}` }}
data-layer
@@ -387,7 +388,13 @@
on:click={(e) => selectLayerWithModifiers(e, listing)}
>
{#if isNestingLayer(listing.entry.layerClassification)}
<button class="expand-arrow" class:expanded={listing.entry.expanded} on:click|stopPropagation={() => handleExpandArrowClick(listing.entry.id)} tabindex="0" />
<button
class="expand-arrow"
class:expanded={listing.entry.expanded}
disabled={!listing.entry.hasChildren}
on:click|stopPropagation={() => handleExpandArrowClick(listing.entry.id)}
tabindex="0"
/>
{#if listing.entry.layerClassification === "Artboard"}
<IconLabel icon="Artboard" class={"layer-type-icon"} />
{:else if listing.entry.layerClassification === "Folder"}
@@ -413,12 +420,25 @@
on:change={(e) => onEditLayerNameChange(listing, e)}
/>
</LayoutRow>
{#if !listing.entry.unlocked || !listing.entry.parentsUnlocked}
<IconButton
class={"status-toggle"}
classes={{ inactive: !listing.entry.parentsUnlocked }}
action={(e) => (toggleLayerVisibility(listing.entry.id), e?.stopPropagation())}
size={24}
icon={listing.entry.parentsUnlocked ? "PadlockLocked" : "PadlockUnlocked"}
hoverIcon={listing.entry.parentsUnlocked ? "PadlockUnlocked" : "PadlockLocked"}
tooltip={listing.entry.parentsUnlocked ? "Unlock" : "Lock"}
/>
{/if}
<IconButton
class={"visibility"}
class={"status-toggle"}
classes={{ inactive: !listing.entry.parentsVisible }}
action={(e) => (toggleLayerVisibility(listing.entry.id), e?.stopPropagation())}
size={24}
icon={listing.entry.visible ? "EyeVisible" : "EyeHidden"}
tooltip={listing.entry.visible ? "Visible" : "Hidden"}
hoverIcon={listing.entry.visible ? "EyeHide" : "EyeShow"}
tooltip={listing.entry.visible ? "Hide" : "Show"}
/>
</LayoutRow>
{/each}
@@ -443,16 +463,27 @@
min-width: 300px;
}
// Blend mode selector
.dropdown-input {
max-width: 120px;
}
// Blend mode selector and opacity slider
.dropdown-input,
.number-input {
flex: 1 1 auto;
}
// Blend mode selector
.dropdown-input {
max-width: 120px;
flex-basis: 120px;
}
// Opacity slider
.number-input {
max-width: 180px;
flex-basis: 180px;
+ .separator ~ .separator {
flex-grow: 1;
}
}
}
// Layer hierarchy
@@ -464,11 +495,15 @@
flex: 0 0 auto;
align-items: center;
position: relative;
border-bottom: 1px solid var(--color-2-mildblack);
border-radius: 2px;
height: 32px;
margin: 0 4px;
padding-left: calc(4px + var(--layer-indent-levels) * 16px);
border-bottom: 1px solid var(--color-2-mildblack);
border-radius: 2px;
&.nesting-layer {
padding-left: calc(var(--layer-indent-levels) * 16px);
}
&.selected {
background: var(--color-4-dimgray);
@@ -493,23 +528,28 @@
justify-content: center;
border-radius: 2px;
&:hover {
background: var(--color-5-dullgray);
}
&::after {
content: "";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 3px 0 3px 6px;
border-color: transparent transparent transparent var(--color-e-nearwhite);
width: 8px;
height: 8px;
background: var(--icon-expand-collapse-arrow);
}
&[disabled]::after {
background: var(--icon-expand-collapse-arrow-disabled);
}
&:hover:not([disabled]) {
background: var(--color-5-dullgray);
&::after {
background: var(--icon-expand-collapse-arrow-hover);
}
}
&.expanded::after {
border-width: 6px 3px 0 3px;
border-color: var(--color-e-nearwhite) transparent transparent transparent;
transform: rotate(90deg);
}
}
@@ -573,11 +613,15 @@
}
}
.visibility {
.status-toggle {
flex: 0 0 auto;
align-items: center;
height: 100%;
&.inactive {
background-image: var(--background-inactive-stripes);
}
.icon-button {
height: 100%;
width: calc(24px + 2 * 4px);
@@ -4,6 +4,7 @@
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
export let icon: IconName;
export let hoverIcon: IconName | undefined = undefined;
export let size: IconSize;
export let disabled = false;
export let active = false;
@@ -20,8 +21,21 @@
.join(" ");
</script>
<button class={`icon-button size-${size} ${className} ${extraClasses}`.trim()} class:disabled class:active on:click={action} {disabled} title={tooltip} tabindex={active ? -1 : 0} {...$$restProps}>
<button
class={`icon-button size-${size} ${className} ${extraClasses}`.trim()}
class:hover-icon={hoverIcon && !disabled}
class:disabled
class:active
on:click={action}
{disabled}
title={tooltip}
tabindex={active ? -1 : 0}
{...$$restProps}
>
<IconLabel {icon} />
{#if hoverIcon && !disabled}
<IconLabel icon={hoverIcon} />
{/if}
</button>
<style lang="scss" global>
@@ -49,6 +63,16 @@
background: var(--color-5-dullgray);
}
&.hover-icon {
&:not(:hover) .icon-label:nth-of-type(2) {
display: none;
}
&:hover .icon-label:nth-of-type(1) {
display: none;
}
}
&.disabled {
background: none;
@@ -14,6 +14,7 @@
// However, if multiple TextButton widgets are used in a group with only some having no label, this component is able to accommodate that.
export let label: string;
export let icon: IconName | undefined = undefined;
export let hoverIcon: IconName | undefined = undefined;
export let emphasized = false;
export let flush = false;
export let minWidth = 0;
@@ -54,6 +55,7 @@
<button
class="text-button"
class:open={self?.open}
class:hover-icon={hoverIcon && !disabled}
class:emphasized
class:disabled
class:flush
@@ -68,6 +70,9 @@
>
{#if icon}
<IconLabel {icon} />
{#if hoverIcon && !disabled}
<IconLabel icon={hoverIcon} />
{/if}
{/if}
{#if icon && label}
<Separator type={flush ? "Unrelated" : "Related"} />
@@ -118,6 +123,16 @@
--button-text-color: var(--color-f-white);
}
&.hover-icon {
&:not(:hover) .icon-label:nth-of-type(2) {
display: none;
}
&:hover .icon-label:nth-of-type(1) {
display: none;
}
}
&.disabled {
--button-background-color: var(--color-4-dimgray);
--button-text-color: var(--color-8-uppergray);