Skip to content

Commit

Permalink
ux refactor (#11)
Browse files Browse the repository at this point in the history
* uxrefactor

* clean up polish

* .

* albers square

* bugs

* maureen notes

* toggle sections

* .
  • Loading branch information
mcnuttandrew authored Jan 24, 2024
1 parent bafd0a8 commit e780c4b
Show file tree
Hide file tree
Showing 42 changed files with 1,127 additions and 865 deletions.
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ Use: should point to localhost:8888 if all is well

First time you start it up you should also run `yarn prep data`

# Todo bankruptcy

- [ ] Minor: Make keyboard short cut (option+up/down) for the z-direction
- [ ] Chore: Extract some common types into a top level location (like types.ts type thing)
- [ ] Insert color theory options, eg insert opposing, inserting analogous color, etc, mine from the adobe picker
- [ ] Labels, tooltips, etc
- [ ] Nice to have: Rest of basic geometry manipulations: flip (horizontal, vertical), scale, Distribute radially
- [ ] Bug report. If I am comparing a palette with itself and select a color in the main view, the color is not selected in the xy plot of the comparison panel. It is selected in the vertical only plot
- [ ] For the palettes, a couple of ideas. Right now, feels like selecting a palette in the list reorders all the palettes, which is disorienting. I realize what you're doing in removing the palette I clicked on, adding the one I was editing. I think don't do this. Keep a fixed order (which I could change if I wanted to), and simply mark the palette that's being editing, don't remove it from the list. Similarly, if I copy a palette, put it right after the palette I copied, not up at the top. I also think adding a compact view of the palettes will eventually be necessary, so now might be the time to do it. Even as a default, would make the circles a bit smaller and pack them tighter. Or maybe make them tall rectangles that would pack even tighter.
- [ ] For the palettes, there is a copy and delete bug. Try this: Copy Example 2, then immediately click delete (menu is still up). Surpise!
- [ ] Tool tip not staying put
- [ ] Bug: Color channel usage slightly cursed (doesn't update positions correctly)
- [ ] Add clone color (and similar buttons) to the tooltip, mostly for making interacting with the examples simpler
- [ ] Direct manipulation new color add "puttin" mode on the scatterplot
- [ ] Undo / redo stack size. Nice to have: summarize each action
- [ ] XYY is probaably now possible
- [ ] Bug: rotate in polar coordinates doesn't work right
- [ ] Ad hoc lints seem possible, do a spike
- [ ] Directional subtlies for aligns
- [x] Similarly, would like to work through the various options for the examples. Delete, Edit, Hide (not Mute) seem good. If you're going to Hide, then ideally you provide a selective unhide (dropdown of names is the easiest) as well as the unhide all. Your Solo means "hide everything else" which I'm not convinced is worth a button. However, a "full screen" or "fit width" "fit height" options that scales it up and reduces the rest to thumbnails might be cool. And I'm sure there are a few more we'll discover as we work with it.
- [x] Albers color theory games style examples

## Direct manipulation bugs/improvement

The basic UX for editing has the following components
Expand Down Expand Up @@ -52,14 +74,9 @@ To raise the sliders, you need to click on one of the examples that are displaye
## TODOS

- [x] New "blank" button.
- [ ] Too many menu options, refactor so that they have a logical and usable hierarchy
- [ ] Minor: Make keyboard short cut (option+up/down) for the z-direction
- [ ] Chore: Extract some common types into a top level location (like types.ts type thing)
- [x] Too many menu options, refactor so that they have a logical and usable hierarchy
- [x] Chore: Rearrange some of the colors in the color area eg make rg on xy and b on z etc, blocking polar stuff
- [x] Polar stuff
- [ ] Insert color theory options, eg insert opposing, inserting analogous color, etc, mine from the adobe picker
- [ ] Labels, tooltips, etc
- [ ] Nice to have: Rest of basic geometry manipulations: flip (horizontal, vertical), scale, Distribute radially
- [x] Make lints have configurable parameters
- [x] Examples: A (default) example showing annotated math stuff
- [x] Examples: SVG Upload
Expand Down
2 changes: 1 addition & 1 deletion netlify/functions/get-color-suggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Background Color: ${pal.background}
Prompt: ${pal.search}
Your response: \`\`\`json`;
Your response: `;
return result;
};

Expand Down
7 changes: 7 additions & 0 deletions public/examples/albers.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 changes: 57 additions & 51 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
import colorStore from "./stores/color-store";
import focusStore from "./stores/focus-store";
import configStore from "./stores/config-store";
import { buttonStyle } from "./lib/styles";
import Nav from "./components/Nav.svelte";
import LeftPanel from "./content-modules/LeftPanel.svelte";
import ActionArea from "./content-modules/ActionArea.svelte";
import Examples from "./content-modules/Examples.svelte";
import Eval from "./content-modules/Eval.svelte";
import KeyboardHooks from "./components/KeyboardHooks.svelte";
Expand All @@ -18,23 +20,54 @@
import Sort from "./content-modules/context-free-tools/Sort.svelte";
import SuggestName from "./content-modules/context-free-tools/SuggestName.svelte";
import GetColorsFromString from "./content-modules/context-free-tools/GetColorsFromString.svelte";
import NewPal from "./content-modules/context-free-tools/NewPal.svelte";
import ContentEditable from "./components/ContentEditable.svelte";
const tabs = ["examples", "compare", "eval"] as const;
const tabs = ["examples", "compare", "eval"];
</script>

<main class="flex h-full">
<LeftPanel />
<div class="h-full flex flex-col grow main-content">
<ActionArea />
<div class="flex w-full grow overflow-auto">
<div class="flex flex-col">
<div class="w-full flex bg-slate-100 px-2 py-3">
<div class="w-full flex bg-stone-800 px-2 py-3 text-white">
<div class="flex">
<NewPal />
<button
id="save"
class={`${buttonStyle} `}
on:click={() => {
const newPal = {
...$colorStore.currentPal,
name: `${$colorStore.currentPal.name} copy`,
colors: [...$colorStore.currentPal.colors],
};
colorStore.createNewPal(newPal);
}}
>
Save
</button>
</div>
<SetSimulation />
<Zoom />
</div>
<div class="flex flex-col h-full">
<div class="flex flex-col h-full px-4">
<!-- naming stuff -->
<div class="flex justify-between">
<div class="flex text-xl">
<span class="italic">Current Pal:</span>
<div class="flex">
<span>✎</span>
<ContentEditable
onChange={(x) => colorStore.setCurrentPalName(x)}
value={$colorStore.currentPal.name}
/>
</div>
</div>
<SuggestName />
</div>
<ColorScatterPlot
scatterPlotMode="moving"
colorSpace={$colorStore.currentPal.colorSpace}
Expand All @@ -57,60 +90,29 @@
colorSpace={$colorStore.currentPal.colorSpace}
onChange={(space) => colorStore.setColorSpace(space)}
/>
<Sort />
</div>
<div class="flex flex-col pl-2">
<!-- naming stuff -->
<div class="flex justify-between">
<div class="flex">
<span class="italic">Current Pal:</span>
<div class="flex">
<span>✎</span>
<ContentEditable
onChange={(x) => colorStore.setCurrentPalName(x)}
value={$colorStore.currentPal.name}
/>
</div>
</div>
<SuggestName />
</div>
<!-- overview / preview -->
<div class="flex w-full items-center">
<PalPreview
highlightSelected={true}
pal={$colorStore.currentPal}
allowModification={true}
/>
<div class="pl-2">
<Sort />
</div>
</div>
<PalPreview
highlightSelected={true}
pal={$colorStore.currentPal}
allowModification={true}
/>
<GetColorsFromString />
</div>
</div>
</div>
<div class="grow">
<nav
aria-label="Page navigation"
class="bg-slate-100 flex justify-center"
>
<ul class="inline-flex">
{#each tabs as tab}
<li class="py-3">
<button
class="h-6 px-2 transition-colors duration-150 border border-slate-500 focus:shadow-outline uppercase italic"
class:bg-slate-500={$configStore.route === tab}
class:bg-white={$configStore.route !== tab}
class:text-white={$configStore.route === tab}
class:rounded-r-lg={tab === "eval"}
class:rounded-l-lg={tab === "examples"}
on:click={() => configStore.setRoute(tab)}
>
{tab}
</button>
</li>
{/each}
</ul>
</nav>
<Nav
className="bg-stone-800 text-white h-12 items-center "
{tabs}
isTabSelected={(x) => $configStore.route === x}
selectTab={(x) => {
// @ts-ignore
configStore.setRoute(x);
}}
/>

{#if $configStore.route === "examples"}
<Examples />
Expand All @@ -131,4 +133,8 @@
.main-content {
min-width: 0;
}
#save {
position: relative;
top: 2px;
}
</style>
18 changes: 18 additions & 0 deletions src/components/ColorButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts">
import { buttonStyle } from "../lib/styles";
export let color: string;
export let clickColor: (color: string) => void;
export let removeColor: (color: string) => void;
</script>

<div
class=" {buttonStyle} h-12 flex justify-between items-center mb-2 opacity-100"
>
<button
class="w-3 h-3 rounded-full mr-2"
style="background-color: {color}"
on:click={() => clickColor(color)}
></button>
<button class="" on:click={() => clickColor(color)}>{color}</button>
<button class="ml-2" on:click={() => removeColor(color)}>X</button>
</div>
16 changes: 9 additions & 7 deletions src/components/ColorChannelPicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
],
lab: [
{ name: "L", min: 0, max: 100, step: 1 },
{ name: "a", min: -110, max: 110, step: 1 },
{ name: "b", min: -110, max: 110, step: 1 },
{ name: "a", min: -125, max: 125, step: 1 },
{ name: "b", min: -125, max: 125, step: 1 },
],
oklab: [
{ name: "L", min: 0, max: 1, step: 0.01 },
Expand Down Expand Up @@ -137,18 +137,20 @@
<option value={colorMode}>{colorMode}</option>
{/each}
</select>
<div class="flex h-full pl-2 mr-2">
<div class="flex h-full mr-2">
<div class="flex flex-col">
<div class="flex flex-col">
<div class="w-full">
{#each colorConfigs[colorMode] as channel, idx}
<div class="flex items-start flex-col mb-2">
<div class="flex">
<label class="block uppercase text-sm mt-2">
<div class="flex w-full justify-between">
<span>{channel.name} ({channel.min}-{channel.max})</span>
<div class="flex w-full justify-between items-center">
<span class="whitespace-nowrap mr-2">
{channel.name} ({channel.min}-{channel.max})
</span>
<input
class="w-full h-4 text-right"
class="h-4 text-right w-16 text-sm"
type="number"
value={formatter(channel.value)}
min={channel.min}
Expand Down Expand Up @@ -195,7 +197,7 @@
height: 2.2em;
border-radius: 0.3em;
box-shadow: 0 0 1px rgba(0, 0, 0, 0.5);
min-width: 300px;
min-width: 285px;
}
.color-slider::-webkit-slider-thumb {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ColorScatterPlotXYGuides.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
label: `${config.xChannel}: ${axisFormatter(xScale.domain()[1])}`,
},
};
const bgResolution = 25;
const bgResolution = 15;
const avgNums = (nums: number[]) =>
nums.reduce((acc, x) => acc + x, 0) / nums.length;
$: fColors = focusedColors.map((x) => colors[x].toChannels());
Expand Down
12 changes: 9 additions & 3 deletions src/components/Example.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import focusStore from "../stores/focus-store";
import { idxToKey } from "../lib/charts";
export let example: string;
export let size = 300;
let focusedColor = false as false | number;
function countNumberOfExamplesInUse(example: string): number {
let inUse = 0;
Expand All @@ -18,17 +19,21 @@
function insertColorsToExample(
example: string,
colors: string[],
bg: string
bg: string,
size: number = 250
) {
const numInUse = countNumberOfExamplesInUse(example);
let svg = example.replace("rebekkablue", bg);
// .replace("<svg", `<svg overflow="visible" `);
if (!svg.match(/<svg[^>]*\sheight="([^"]*)"/)) {
svg = svg.replace("<svg", `<svg height="300px" `);
}
if (!svg.match(/<svg[^>]*\width="([^"]*)"/)) {
svg = svg.replace("<svg", `<svg width="300px" `);
}
// set the width and height
svg = svg.replace(/\sheight="([^"]*)"/, `height="${size}px" `);
svg = svg.replace(/\width="([^"]*)"/, `width="${size}px" `);
for (let i = 0; i < numInUse; i++) {
svg = svg.replace(
new RegExp(idxToKey(i), "g"),
Expand All @@ -49,6 +54,7 @@
const colorIdx = colors.findIndex((x) => x.toHex().toLowerCase() === color);
if (colorIdx > -1) {
focusedColor = colorIdx;
focusStore.setColors([colorIdx]);
}
}
Expand Down Expand Up @@ -79,7 +85,7 @@

<div class="relative">
<div bind:this={container} class="example-container">
{@html insertColorsToExample(example, mappedColors, bg.toHex())}
{@html insertColorsToExample(example, mappedColors, bg.toHex(), size)}
</div>
{#if color && focusedColor !== false}
<Tooltip
Expand Down
8 changes: 7 additions & 1 deletion src/components/KeyboardHooks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,18 @@
function onKeyDown(e: any) {
const tagName = e.target.tagName.toLowerCase();
const tagType = e.target.type;
if (tagName === "input") {
const isUIElement = tagType === "number" || tagType === "range";
const isUIElement =
tagType === "number" || tagType === "range" || tagType === "text";
if (isUIElement) {
return;
}
}
// block code mirror editing
if ((e.target.getAttribute("class") || "").includes("cm-content")) {
return;
}
if (tagName === "textarea") {
return;
}
Expand Down
20 changes: 20 additions & 0 deletions src/components/MiniPalPreview.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import type { Palette } from "../stores/color-store";
export let pal: Palette;
export let onClick: () => void;
</script>

<div class="relative mr-2 mb-2 flex justify-center items-center">
<div class="w-full flex absolute top-0 opacity-50 pointer-events-none">
{#each pal.colors as color}
<div
class="h-6"
style="background-color: {color.toHex()}; width: {100 /
pal.colors.length}%"
></div>
{/each}
</div>
<button on:click={onClick}>
{pal.name}
</button>
</div>
Loading

0 comments on commit e780c4b

Please sign in to comment.