Add color picker component and tidy up style options

This commit is contained in:
Andrew Kingston 2021-06-23 09:54:31 +01:00
parent dd4c7a186e
commit 4b9a863c68
5 changed files with 230 additions and 77 deletions

View File

@ -0,0 +1,218 @@
<script>
import { createEventDispatcher } from "svelte"
import "@spectrum-css/popover/dist/index-vars.css"
import clickOutside from "../Actions/click_outside"
import { fly } from "svelte/transition"
import Icon from "../Icon/Icon.svelte"
import Input from "../Form/Input.svelte"
import { capitalise } from "helpers"
export let value
let open = false
$: color = value || "transparent"
$: customValue = getCustomValue(value)
$: checkColor = getCheckColor(value)
const dispatch = createEventDispatcher()
const categories = [
{
label: "Grays",
colors: [
"white",
"gray-50",
"gray-75",
"gray-100",
"gray-200",
"gray-300",
"gray-400",
"gray-500",
"gray-600",
"gray-700",
"gray-800",
"gray-900",
"black",
],
},
{
label: "Colors",
colors: [
"red-400",
"orange-400",
"yellow-400",
"green-400",
"seafoam-400",
"blue-400",
"indigo-400",
"magenta-400",
"red-500",
"orange-500",
"yellow-500",
"green-500",
"seafoam-500",
"blue-500",
"indigo-500",
"magenta-500",
"red-600",
"orange-600",
"yellow-600",
"green-600",
"seafoam-600",
"blue-600",
"indigo-600",
"magenta-600",
"red-700",
"orange-700",
"yellow-700",
"green-700",
"seafoam-700",
"blue-700",
"indigo-700",
"magenta-700",
],
},
]
const onChange = value => {
dispatch("change", value)
open = false
}
const getCustomValue = value => {
if (!value) {
return value
}
let found = false
const comparisonValue = value.substring(35, value.length - 1)
for (let category of categories) {
found = category.colors.includes(comparisonValue)
if (found) {
break
}
}
return found ? null : value
}
const prettyPrint = color => {
return capitalise(color.split("-").join(" "))
}
const getCheckColor = value => {
return /^.*(white|(gray-(50|75|100|200|300|400|500)))\)$/.test(value)
? "black"
: "white"
}
</script>
<div
class="preview"
style="background: {color};"
on:click={() => (open = true)}
/>
{#if open}
<div
use:clickOutside={() => (open = false)}
transition:fly={{ y: -20, duration: 200 }}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
>
{#each categories as category}
<div class="category">
<div class="heading">{category.label}</div>
<div class="colors">
{#each category.colors as color}
<div
on:click={() => {
onChange(`var(--spectrum-global-color-static-${color})`)
}}
class="color"
style="background: var(--spectrum-global-color-static-{color}); color: {checkColor};"
title={prettyPrint(color)}
>
{#if value === `var(--spectrum-global-color-static-${color})`}
<Icon name="Checkmark" size="S" />
{/if}
</div>
{/each}
</div>
</div>
{/each}
<div class="category category--custom">
<div class="heading">Custom</div>
<div class="custom">
<Input
updateOnChange={false}
quiet
placeholder="Hex, RGB, HSL..."
value={customValue}
on:change
/>
<Icon size="S" name="Close" hoverable on:click={() => onChange(null)} />
</div>
</div>
</div>
{/if}
<style>
.preview {
width: 32px;
height: 32px;
border-radius: 100%;
transition: border-color 130ms ease-in-out;
box-shadow: 0 0 0 1px var(--spectrum-global-color-gray-300);
}
.preview:hover {
cursor: pointer;
box-shadow: 0 0 2px 2px var(--spectrum-global-color-gray-300);
}
.spectrum-Popover {
width: 100%;
z-index: 999;
top: 100%;
padding: var(--spacing-l) var(--spacing-xl);
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
gap: var(--spacing-xl);
}
.colors {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
gap: var(--spacing-xs);
}
.heading {
font-size: var(--font-size-s);
font-weight: 600;
letter-spacing: 0.14px;
flex: 1 1 auto;
text-transform: uppercase;
grid-column: 1 / 5;
margin-bottom: var(--spacing-s);
}
.color {
height: 16px;
width: 16px;
border-radius: 100%;
box-shadow: 0 0 0 1px var(--spectrum-global-color-gray-300);
display: grid;
place-items: center;
}
.color:hover {
cursor: pointer;
box-shadow: 0 0 2px 2px var(--spectrum-global-color-gray-300);
}
.custom {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: var(--spacing-m);
margin-right: var(--spacing-xs);
}
.category--custom .heading {
margin-bottom: var(--spacing-xs);
}
</style>

View File

@ -10,6 +10,7 @@
export let id = null
export let readonly = false
export let updateOnChange = true
export let quiet = false
const dispatch = createEventDispatcher()
let focus = false
@ -59,6 +60,7 @@
<div
class="spectrum-Textfield"
class:spectrum-Textfield--quiet={quiet}
class:is-invalid={!!error}
class:is-disabled={disabled}
class:is-focused={focus}

View File

@ -12,6 +12,7 @@
export let readonly = false
export let error = null
export let updateOnChange = true
export let quiet = false
const dispatch = createEventDispatcher()
const onChange = e => {
@ -29,6 +30,7 @@
{value}
{placeholder}
{type}
{quiet}
on:change={onChange}
on:click
on:input

View File

@ -55,6 +55,7 @@ export { default as Search } from "./Form/Search.svelte"
export { default as Pagination } from "./Pagination/Pagination.svelte"
export { default as Badge } from "./Badge/Badge.svelte"
export { default as StatusLight } from "./StatusLight/StatusLight.svelte"
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
// Typography
export { default as Body } from "./Typography/Body.svelte"

View File

@ -1,6 +1,6 @@
import { Input, Select } from "@budibase/bbui"
import { Input, Select, ColorPicker } from "@budibase/bbui"
import FlatButtonGroup from "./PropertyControls/FlatButtonGroup"
import Colorpicker from "./PropertyControls/ColorPicker.svelte"
// import Colorpicker from "./PropertyControls/ColorPicker.svelte"
export const layout = [
{
@ -274,61 +274,6 @@ export const size = {
],
}
export const position = [
{
label: "Position",
key: "position",
control: Select,
options: [
{ label: "Static", value: "static" },
{ label: "Relative", value: "relative" },
{ label: "Fixed", value: "fixed" },
{ label: "Absolute", value: "absolute" },
{ label: "Sticky", value: "sticky" },
],
},
{
label: "Top",
key: "top",
control: Input,
placeholder: "px",
},
{
label: "Right",
key: "right",
control: Input,
placeholder: "px",
},
{
label: "Bottom",
key: "bottom",
control: Input,
placeholder: "px",
},
{
label: "Left",
key: "left",
control: Input,
placeholder: "px",
},
{
label: "Z-index",
key: "z-index",
control: Select,
options: [
{ label: "-9999", value: "-9999" },
{ label: "-3", value: "-3" },
{ label: "-2", value: "-2" },
{ label: "-1", value: "-1" },
{ label: "0", value: "0" },
{ label: "1", value: "1" },
{ label: "2", value: "2" },
{ label: "3", value: "3" },
{ label: "9999", value: "9999" },
],
},
]
export const typography = [
{
label: "Font",
@ -401,7 +346,7 @@ export const typography = [
{
label: "Color",
key: "color",
control: Colorpicker,
control: ColorPicker,
},
{
label: "align",
@ -445,14 +390,13 @@ export const background = {
{
label: "Color",
key: "background",
control: Colorpicker,
control: ColorPicker,
},
{
label: "Gradient",
key: "background-image",
control: Select,
options: [
{ label: "None", value: "none" },
{
label: "Warm Flame",
value:
@ -534,21 +478,17 @@ export const border = {
{
label: "Color",
key: "border-color",
control: Colorpicker,
control: ColorPicker,
},
{
label: "Radius",
key: "border-radius",
control: Select,
options: [
{ label: "None", value: "0" },
{ label: "X Small", value: "0.125rem" },
{ label: "Small", value: "0.25rem" },
{ label: "Medium", value: "0.5rem" },
{ label: "Large", value: "1rem" },
{ label: "X Large", value: "2rem" },
{ label: "XX Large", value: "4rem" },
{ label: "Round", value: "5678px" },
{ label: "Round", value: "100%" },
],
},
{
@ -556,12 +496,9 @@ export const border = {
key: "border-width",
control: Select,
options: [
{ label: "None", value: "0" },
{ label: "X Small", value: "0.5px" },
{ label: "Small", value: "1px" },
{ label: "Medium", value: "2px" },
{ label: "Large", value: "4px" },
{ label: "X large", value: "8px" },
],
},
{
@ -569,8 +506,6 @@ export const border = {
key: "box-shadow",
control: Select,
options: [
{ label: "None", value: "none" },
{ label: "X Small", value: "0 1px 2px 0 rgba(0, 0, 0, 0.05)" },
{
label: "Small",
value:
@ -584,12 +519,7 @@ export const border = {
{
label: "Large",
value:
"0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
},
{
label: "X Large",
value:
"0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
"0 8px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)",
},
],
},