Multiple improvement to option configuration
This commit is contained in:
parent
f30142831e
commit
d9a00cc6d4
|
@ -2,7 +2,7 @@
|
||||||
import { flip } from "svelte/animate"
|
import { flip } from "svelte/animate"
|
||||||
import { dndzone } from "svelte-dnd-action"
|
import { dndzone } from "svelte-dnd-action"
|
||||||
import { Icon, Popover } from "@budibase/bbui"
|
import { Icon, Popover } from "@budibase/bbui"
|
||||||
import { onMount } from "svelte"
|
import { onMount, tick } from "svelte"
|
||||||
import { Constants } from "@budibase/frontend-core"
|
import { Constants } from "@budibase/frontend-core"
|
||||||
|
|
||||||
export let constraints
|
export let constraints
|
||||||
|
@ -22,13 +22,16 @@
|
||||||
anchors.pop(undefined)
|
anchors.pop(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewInput = () => {
|
const addNewInput = async () => {
|
||||||
const newOption = `Option ${constraints.inclusion.length + 1}`
|
const newName = `Option ${constraints.inclusion.length + 1}`
|
||||||
options = [...options, { name: newOption, id: Math.random() }]
|
const id = Math.random()
|
||||||
constraints.inclusion = [...constraints.inclusion, newOption]
|
options = [...options, { name: newName, id }]
|
||||||
optionColors[newOption] = Constants.OptionColours[(options.length - 1) % 9]
|
constraints.inclusion = [...constraints.inclusion, newName]
|
||||||
|
optionColors[newName] = Constants.OptionColours[(options.length - 1) % 9]
|
||||||
colorPopovers.push(undefined)
|
colorPopovers.push(undefined)
|
||||||
anchors.push(undefined)
|
anchors.push(undefined)
|
||||||
|
await tick()
|
||||||
|
document.getElementById(`option-${id}`)?.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDndConsider = e => {
|
const handleDndConsider = e => {
|
||||||
|
@ -75,154 +78,101 @@
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<div>
|
<div
|
||||||
<div
|
class="options"
|
||||||
class="actions"
|
use:dndzone={{
|
||||||
use:dndzone={{
|
items: options,
|
||||||
items: options,
|
flipDurationMs,
|
||||||
flipDurationMs,
|
dropTargetStyle: { outline: "none" },
|
||||||
dropTargetStyle: { outline: "none" },
|
}}
|
||||||
}}
|
on:consider={handleDndConsider}
|
||||||
on:consider={handleDndConsider}
|
on:finalize={handleDndFinalize}
|
||||||
on:finalize={handleDndFinalize}
|
>
|
||||||
>
|
{#each options as option, idx (`${option.id}-${idx}`)}
|
||||||
{#each options as option, idx (`${option.id}-${idx}`)}
|
<div class="option" animate:flip={{ duration: flipDurationMs }}>
|
||||||
|
<div class="drag-handle">
|
||||||
|
<Icon name="DragHandle" size="L" />
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="no-border action-container"
|
bind:this={anchors[idx]}
|
||||||
animate:flip={{ duration: flipDurationMs }}
|
class="color-picker"
|
||||||
|
on:click={e => openColorPickerPopover(idx, e.target)}
|
||||||
>
|
>
|
||||||
<div class="child drag-handle-spacing">
|
|
||||||
<Icon name="DragHandle" size="L" />
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
bind:this={anchors[idx]}
|
class="circle"
|
||||||
class="child color-picker"
|
style="--color:{optionColors?.[option.name] ||
|
||||||
on:click={e => openColorPickerPopover(idx, e.target)}
|
'hsla(0, 1%, 50%, 0.3)'}"
|
||||||
>
|
>
|
||||||
<div
|
<Popover
|
||||||
class="circle"
|
bind:this={colorPopovers[idx]}
|
||||||
style="--color:{optionColors?.[option.name] ||
|
anchor={anchors[idx]}
|
||||||
'hsla(0, 1%, 50%, 0.3)'}"
|
align="left"
|
||||||
|
offset={0}
|
||||||
|
animate={false}
|
||||||
>
|
>
|
||||||
<Popover
|
<div class="colors" data-ignore-click-outside="true">
|
||||||
bind:this={colorPopovers[idx]}
|
{#each Constants.OptionColours as color}
|
||||||
anchor={anchors[idx]}
|
<div
|
||||||
align="left"
|
on:click={() => handleColorChange(option.name, color, idx)}
|
||||||
offset={0}
|
style="--color:{color};"
|
||||||
animate={false}
|
class="circle circle-hover"
|
||||||
>
|
/>
|
||||||
<div class="colors" data-ignore-click-outside="true">
|
{/each}
|
||||||
{#each Constants.OptionColours as color}
|
</div>
|
||||||
<div
|
</Popover>
|
||||||
on:click={() => handleColorChange(option.name, color, idx)}
|
|
||||||
style="--color:{color};"
|
|
||||||
class="circle circle-hover"
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="child">
|
|
||||||
<input
|
|
||||||
class="input-field"
|
|
||||||
type="text"
|
|
||||||
on:change={e => handleNameChange(option.name, idx, e.target.value)}
|
|
||||||
value={option.name}
|
|
||||||
placeholder="Option name"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="child">
|
|
||||||
<Icon name="Close" hoverable size="S" on:click={removeInput(idx)} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
<input
|
||||||
</div>
|
class="option-name"
|
||||||
|
type="text"
|
||||||
|
on:change={e => handleNameChange(option.name, idx, e.target.value)}
|
||||||
|
value={option.name}
|
||||||
|
placeholder="Option name"
|
||||||
|
id="option-{option.id}"
|
||||||
|
/>
|
||||||
|
<Icon name="Close" hoverable size="S" on:click={removeInput(idx)} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
<div on:click={addNewInput} class="add-option">
|
<div on:click={addNewInput} class="add-option">
|
||||||
<Icon hoverable name="Add" />
|
<Icon name="Add" />
|
||||||
<div>Add option</div>
|
<div>Add option</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.action-container {
|
/* Container */
|
||||||
background-color: var(--spectrum-alias-background-color-primary);
|
.options {
|
||||||
border-radius: 0px;
|
overflow: hidden;
|
||||||
|
border-radius: 4px;
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
|
background-color: var(--spectrum-global-color-gray-50);
|
||||||
|
}
|
||||||
|
.options > * {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Options row */
|
||||||
|
.option {
|
||||||
transition: background-color 130ms ease-in-out, color 130ms ease-in-out,
|
transition: background-color 130ms ease-in-out, color 130ms ease-in-out,
|
||||||
border-color 130ms ease-in-out;
|
border-color 130ms ease-in-out;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
border-bottom: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
.no-border {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-container:last-child {
|
|
||||||
border-bottom: 1px solid var(--spectrum-global-color-gray-300) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.child {
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
.child:hover,
|
|
||||||
.child:focus {
|
|
||||||
background: var(--spectrum-global-color-gray-200);
|
|
||||||
}
|
|
||||||
.add-option {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
padding: var(--spacing-m);
|
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-m);
|
||||||
cursor: pointer;
|
padding: 0 var(--spacing-m) 0 var(--spacing-s);
|
||||||
|
}
|
||||||
|
.option:hover,
|
||||||
|
.option:focus {
|
||||||
|
background: var(--spectrum-global-color-gray-100);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
/* Option row components */
|
||||||
border: none;
|
.color-picker {
|
||||||
outline: none;
|
align-self: stretch;
|
||||||
background-color: transparent;
|
display: grid;
|
||||||
width: 100%;
|
place-items: center;
|
||||||
color: var(--text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.child input[type="text"] {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-field:hover,
|
|
||||||
.input-field:focus {
|
|
||||||
background: var(--spectrum-global-color-gray-200);
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-container > :nth-child(1) {
|
|
||||||
flex-grow: 1;
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-container > :nth-child(2) {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-container > :nth-child(3) {
|
|
||||||
flex-grow: 4;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.action-container > :nth-child(4) {
|
|
||||||
flex-grow: 1;
|
|
||||||
justify-content: center;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-picker:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
@ -230,18 +180,39 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: border 130ms ease-out;
|
||||||
}
|
}
|
||||||
|
.circle:hover {
|
||||||
.circle-hover:hover {
|
border: 1px solid var(--spectrum-global-color-blue-600);
|
||||||
border: 1px solid var(--spectrum-global-color-blue-400);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colors {
|
.colors {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||||
gap: var(--spacing-xl);
|
gap: var(--spacing-xl);
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
margin: var(--spacing-m);
|
margin: var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
.option-name {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background-color: transparent;
|
||||||
|
width: 100%;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add option */
|
||||||
|
.add-option {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: var(--spacing-m);
|
||||||
|
gap: var(--spacing-m);
|
||||||
|
}
|
||||||
|
.add-option:hover {
|
||||||
|
cursor: pointer !important;
|
||||||
|
background: var(--spectrum-global-color-gray-200);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue