Add the checkbox input widget (#204)
* Add the checkbox input widget * Add OptionalInput widget
4
.vscode/vuecomp.code-snippets
vendored
|
@ -22,10 +22,10 @@
|
|||
"import { defineComponent } from \"vue\";",
|
||||
"",
|
||||
"export default defineComponent({",
|
||||
"\tcomponents: {",
|
||||
"\t},",
|
||||
"\tprops: {",
|
||||
"\t},",
|
||||
"\tcomponents: {",
|
||||
"\t},",
|
||||
"});",
|
||||
"</script>",
|
||||
"",
|
||||
|
|
3
client/web/assets/12px-solid/checkmark.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<polygon points="5.19,11.83 0.18,7.44 1.82,5.56 4.81,8.17 10,1.25 12,2.75" />
|
||||
</svg>
|
After Width: | Height: | Size: 147 B |
10
client/web/assets/12px-solid/grid.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<rect width="1" height="12" x="4" y="0" />
|
||||
<rect width="1" height="12" x="1" y="0" />
|
||||
<rect width="1" height="12" x="7" y="0" />
|
||||
<rect width="1" height="12" x="10" y="0" />
|
||||
<rect width="12" height="1" x="0" y="4" />
|
||||
<rect width="12" height="1" x="0" y="1" />
|
||||
<rect width="12" height="1" x="0" y="7" />
|
||||
<rect width="12" height="1" x="0" y="10" />
|
||||
</svg>
|
After Width: | Height: | Size: 422 B |
4
client/web/assets/12px-solid/link.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<path d="M4.68,9.32L4,10c-0.53,0.53-1.47,0.53-2,0C1.73,9.73,1.59,9.38,1.59,9S1.73,8.27,2,8l2.5-2.5c0.27-0.27,0.62-0.41,1-0.41s0.73,0.15,1,0.41l1-1c-1.07-1.07-2.93-1.07-4,0L1,7C0.47,7.53,0.17,8.24,0.17,9S0.47,10.47,1,11s1.24,0.83,2,0.83S4.47,11.53,5,11l1.27-1.27C5.71,9.7,5.17,9.56,4.68,9.32z" />
|
||||
<path d="M11,1C9.93-0.07,8.07-0.07,7,1L5.7,2.3c0.56,0.03,1.11,0.16,1.61,0.39L8,2c0.27-0.27,0.62-0.41,1-0.41S9.73,1.73,10,2s0.41,0.62,0.41,1S10.27,3.73,10,4L7.5,6.5c-0.53,0.53-1.47,0.53-2,0l-1,1c0.53,0.53,1.24,0.83,2,0.83s1.47-0.29,2-0.83L11,5c0.53-0.53,0.83-1.24,0.83-2S11.53,1.53,11,1z" />
|
||||
</svg>
|
After Width: | Height: | Size: 657 B |
10
client/web/assets/12px-solid/overlays.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<rect width="3" height="3" />
|
||||
<rect width="3" height="3" y="9" />
|
||||
<rect width="1" height="4" y="4" />
|
||||
<rect width="4" height="1" x="4" y="11" />
|
||||
<rect width="1" height="4" x="11" y="4" />
|
||||
<rect width="3" height="3" x="9" />
|
||||
<rect width="3" height="3" x="9" y="9" />
|
||||
<rect width="4" height="1" x="4" />
|
||||
</svg>
|
After Width: | Height: | Size: 378 B |
6
client/web/assets/12px-solid/snapping.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12">
|
||||
<path d="M7.5,7.5L6,9C5.17,9.83,3.83,9.83,3,9S2.17,6.83,3,6l1.5-1.5L3,3L1.5,4.5c-1.66,1.66-1.66,4.34,0,6s4.34,1.66,6,0L9,9L7.5,7.5z" />
|
||||
<polygon points="4,2 5.5,0.5 7,2 5.5,3.5" />
|
||||
<polygon points="8.5,6.5 10,5 11.5,6.5 10,8" />
|
||||
<polygon points="12,0 8.29,1.21 9.29,3.21 7,4 7,5 10.71,3.79 9.71,1.79 12,1" />
|
||||
</svg>
|
After Width: | Height: | Size: 381 B |
|
@ -1,5 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<rect x="15" width="1" height="16" />
|
||||
<rect x="6" y="9" width="7" height="5" />
|
||||
<rect y="2" width="13" height="5" />
|
||||
<rect x="6" y="2" width="7" height="5" />
|
||||
<rect y="9" width="13" height="5" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 188 B |
|
@ -1,5 +1,5 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<rect y="15" width="16" height="1" />
|
||||
<rect x="2" y="6" width="5" height="7" />
|
||||
<rect x="9" width="5" height="13" />
|
||||
<rect x="9" y="6" width="5" height="7" />
|
||||
<rect x="2" width="5" height="13" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 188 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 216 B After Width: | Height: | Size: 216 B |
|
@ -52,15 +52,39 @@
|
|||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="right side">
|
||||
<OptionalInput v-model:checked="snappingEnabled" :icon="'Snapping'" />
|
||||
<PopoverButton>
|
||||
<h3>Snapping</h3>
|
||||
<p>More snapping options will be here</p>
|
||||
</PopoverButton>
|
||||
|
||||
<Separator :type="SeparatorType.Unrelated" />
|
||||
|
||||
<OptionalInput v-model:checked="gridEnabled" :icon="'Grid'" />
|
||||
<PopoverButton>
|
||||
<h3>Grid</h3>
|
||||
<p>More grid options will be here</p>
|
||||
</PopoverButton>
|
||||
|
||||
<Separator :type="SeparatorType.Unrelated" />
|
||||
|
||||
<OptionalInput v-model:checked="overlaysEnabled" :icon="'Overlays'" />
|
||||
<PopoverButton>
|
||||
<h3>Overlays</h3>
|
||||
<p>More overlays options will be here</p>
|
||||
</PopoverButton>
|
||||
|
||||
<Separator :type="SeparatorType.Unrelated" />
|
||||
|
||||
<RadioInput v-model:index="viewModeIndex">
|
||||
<IconButton :icon="'ViewModeNormal'" :size="24" title="View Mode: Normal" />
|
||||
<IconButton :icon="'ViewModeOutline'" :size="24" title="View Mode: Outline" />
|
||||
<IconButton :icon="'ViewModePixels'" :size="24" title="View Mode: Pixels" />
|
||||
<PopoverButton>
|
||||
<h3>Display Mode</h3>
|
||||
<p>More display mode options will be here</p>
|
||||
</PopoverButton>
|
||||
</RadioInput>
|
||||
<PopoverButton>
|
||||
<h3>Display Mode</h3>
|
||||
<p>More display mode options will be here</p>
|
||||
</PopoverButton>
|
||||
|
||||
<Separator :type="SeparatorType.Section" />
|
||||
|
||||
|
@ -176,6 +200,7 @@ import PopoverButton from "../widgets/buttons/PopoverButton.vue";
|
|||
import RadioInput from "../widgets/inputs/RadioInput.vue";
|
||||
import NumberInput from "../widgets/inputs/NumberInput.vue";
|
||||
import DropdownInput from "../widgets/inputs/DropdownInput.vue";
|
||||
import OptionalInput from "../widgets/inputs/OptionalInput.vue";
|
||||
import { SectionsOfMenuListEntries } from "../widgets/floating-menus/MenuList.vue";
|
||||
|
||||
const modeMenuEntries: SectionsOfMenuListEntries = [
|
||||
|
@ -282,6 +307,9 @@ export default defineComponent({
|
|||
SeparatorType,
|
||||
modeMenuEntries,
|
||||
viewModeIndex: 0,
|
||||
snappingEnabled: true,
|
||||
gridEnabled: true,
|
||||
overlaysEnabled: true,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
|
@ -295,6 +323,7 @@ export default defineComponent({
|
|||
RadioInput,
|
||||
NumberInput,
|
||||
DropdownInput,
|
||||
OptionalInput,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div class="working-colors">
|
||||
<SwatchPairInput />
|
||||
<div class="swap-and-reset">
|
||||
<IconButton @click="swapColors" :icon="'SwapButton'" title="Swap (Shift+X)" :size="16" />
|
||||
<IconButton @click="resetColors" :icon="'ResetColorsButton'" title="Reset (Ctrl+Shift+X)" :size="16" />
|
||||
<IconButton @click="swapColors" :icon="'Swap'" title="Swap (Shift+X)" :size="16" />
|
||||
<IconButton @click="resetColors" :icon="'ResetColors'" title="Reset (Ctrl+Shift+X)" :size="16" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -35,6 +35,15 @@
|
|||
fill: var(--color-f-white);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Refactor this and other complicated cases dealing with joined widget margins and border-radius by adding a single standard set of classes: joined-first, joined-inner, and joined-last
|
||||
div[class*="-input"] + & {
|
||||
margin-left: 1px;
|
||||
|
||||
.icon-button {
|
||||
border-radius: 0 2px 2px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
74
client/web/src/components/widgets/inputs/CheckboxInput.vue
Normal file
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<div class="checkbox-input">
|
||||
<input type="checkbox" :id="`checkbox-${id}`" :checked="checked" @input="(e) => $emit('update:checked', e.target.checked)" />
|
||||
<label :for="`checkbox-${id}`">
|
||||
<div class="checkbox-box">
|
||||
<Icon :icon="icon" />
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.checkbox-input {
|
||||
display: inline-block;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
|
||||
.checkbox-box {
|
||||
display: block;
|
||||
background: var(--color-e-nearwhite);
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-f-white);
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--color-2-mildblack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input:checked + label .checkbox-box {
|
||||
background: var(--color-accent);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-accent-hover);
|
||||
}
|
||||
|
||||
.icon {
|
||||
fill: var(--color-f-white);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import Icon from "../labels/Icon.vue";
|
||||
|
||||
export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
id: `${Math.random()}`.substring(2),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isChecked() {
|
||||
return this.checked;
|
||||
},
|
||||
},
|
||||
props: {
|
||||
checked: { type: Boolean, required: true },
|
||||
icon: { type: String, default: "Checkmark" },
|
||||
},
|
||||
components: { Icon },
|
||||
});
|
||||
</script>
|
80
client/web/src/components/widgets/inputs/OptionalInput.vue
Normal file
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<div class="optional-input">
|
||||
<CheckboxInput :checked="checked" @input="(e) => $emit('update:checked', e.target.checked)" :icon="icon" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.optional-input {
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 2px 0 0 2px;
|
||||
background: var(--color-5-dullgray);
|
||||
|
||||
.checkbox-box {
|
||||
background: var(--color-e-nearwhite);
|
||||
|
||||
.icon {
|
||||
fill: var(--color-5-dullgray);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-6-lowergray);
|
||||
|
||||
.checkbox-box {
|
||||
background: var(--color-f-white);
|
||||
|
||||
.icon {
|
||||
fill: var(--color-6-lowergray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input:checked + label {
|
||||
background: var(--color-accent);
|
||||
|
||||
.checkbox-box,
|
||||
.checkbox-box:hover {
|
||||
background: var(--color-f-white);
|
||||
|
||||
.icon {
|
||||
fill: var(--color-accent);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--color-accent-hover);
|
||||
|
||||
.checkbox-box,
|
||||
.checkbox-box:hover {
|
||||
.icon {
|
||||
fill: var(--color-accent-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import CheckboxInput from "./CheckboxInput.vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
checked: { type: Boolean, required: true },
|
||||
icon: { type: String, default: "Checkmark" },
|
||||
},
|
||||
components: {
|
||||
CheckboxInput,
|
||||
},
|
||||
});
|
||||
</script>
|
|
@ -30,27 +30,27 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
import SelectTool from "../../../../assets/24px-two-tone/document-tool-layout-select.svg";
|
||||
import CropTool from "../../../../assets/24px-two-tone/document-tool-layout-crop.svg";
|
||||
import NavigateTool from "../../../../assets/24px-two-tone/document-tool-layout-navigate.svg";
|
||||
import EyedropperTool from "../../../../assets/24px-two-tone/document-tool-layout-eyedropper.svg";
|
||||
import TextTool from "../../../../assets/24px-two-tone/document-tool-parametric-text.svg";
|
||||
import FillTool from "../../../../assets/24px-two-tone/document-tool-parametric-fill.svg";
|
||||
import GradientTool from "../../../../assets/24px-two-tone/document-tool-parametric-gradient.svg";
|
||||
import BrushTool from "../../../../assets/24px-two-tone/document-tool-raster-brush.svg";
|
||||
import HealTool from "../../../../assets/24px-two-tone/document-tool-raster-heal.svg";
|
||||
import CloneTool from "../../../../assets/24px-two-tone/document-tool-raster-clone.svg";
|
||||
import PatchTool from "../../../../assets/24px-two-tone/document-tool-raster-patch.svg";
|
||||
import BlurSharpenTool from "../../../../assets/24px-two-tone/document-tool-raster-detail.svg";
|
||||
import RelightTool from "../../../../assets/24px-two-tone/document-tool-raster-relight.svg";
|
||||
import PathTool from "../../../../assets/24px-two-tone/document-tool-vector-path.svg";
|
||||
import PenTool from "../../../../assets/24px-two-tone/document-tool-vector-pen.svg";
|
||||
import FreehandTool from "../../../../assets/24px-two-tone/document-tool-vector-freehand.svg";
|
||||
import SplineTool from "../../../../assets/24px-two-tone/document-tool-vector-spline.svg";
|
||||
import LineTool from "../../../../assets/24px-two-tone/document-tool-vector-line.svg";
|
||||
import RectangleTool from "../../../../assets/24px-two-tone/document-tool-vector-rectangle.svg";
|
||||
import EllipseTool from "../../../../assets/24px-two-tone/document-tool-vector-ellipse.svg";
|
||||
import ShapeTool from "../../../../assets/24px-two-tone/document-tool-vector-shape.svg";
|
||||
import SelectTool from "../../../../assets/24px-two-tone/document-tool-layout-select.svg"; // TODO: Rename
|
||||
import CropTool from "../../../../assets/24px-two-tone/document-tool-layout-crop.svg"; // TODO: Rename
|
||||
import NavigateTool from "../../../../assets/24px-two-tone/document-tool-layout-navigate.svg"; // TODO: Rename
|
||||
import EyedropperTool from "../../../../assets/24px-two-tone/document-tool-layout-eyedropper.svg"; // TODO: Rename
|
||||
import TextTool from "../../../../assets/24px-two-tone/document-tool-parametric-text.svg"; // TODO: Rename
|
||||
import FillTool from "../../../../assets/24px-two-tone/document-tool-parametric-fill.svg"; // TODO: Rename
|
||||
import GradientTool from "../../../../assets/24px-two-tone/document-tool-parametric-gradient.svg"; // TODO: Rename
|
||||
import BrushTool from "../../../../assets/24px-two-tone/document-tool-raster-brush.svg"; // TODO: Rename
|
||||
import HealTool from "../../../../assets/24px-two-tone/document-tool-raster-heal.svg"; // TODO: Rename
|
||||
import CloneTool from "../../../../assets/24px-two-tone/document-tool-raster-clone.svg"; // TODO: Rename
|
||||
import PatchTool from "../../../../assets/24px-two-tone/document-tool-raster-patch.svg"; // TODO: Rename
|
||||
import BlurSharpenTool from "../../../../assets/24px-two-tone/document-tool-raster-detail.svg"; // TODO: Rename
|
||||
import RelightTool from "../../../../assets/24px-two-tone/document-tool-raster-relight.svg"; // TODO: Rename
|
||||
import PathTool from "../../../../assets/24px-two-tone/document-tool-vector-path.svg"; // TODO: Rename
|
||||
import PenTool from "../../../../assets/24px-two-tone/document-tool-vector-pen.svg"; // TODO: Rename
|
||||
import FreehandTool from "../../../../assets/24px-two-tone/document-tool-vector-freehand.svg"; // TODO: Rename
|
||||
import SplineTool from "../../../../assets/24px-two-tone/document-tool-vector-spline.svg"; // TODO: Rename
|
||||
import LineTool from "../../../../assets/24px-two-tone/document-tool-vector-line.svg"; // TODO: Rename
|
||||
import RectangleTool from "../../../../assets/24px-two-tone/document-tool-vector-rectangle.svg"; // TODO: Rename
|
||||
import EllipseTool from "../../../../assets/24px-two-tone/document-tool-vector-ellipse.svg"; // TODO: Rename
|
||||
import ShapeTool from "../../../../assets/24px-two-tone/document-tool-vector-shape.svg"; // TODO: Rename
|
||||
|
||||
import AlignHorizontalLeft from "../../../../assets/16px-solid/align-horizontal-left.svg";
|
||||
import AlignHorizontalCenter from "../../../../assets/16px-solid/align-horizontal-center.svg";
|
||||
|
@ -71,8 +71,8 @@ import ZoomOut from "../../../../assets/16px-solid/zoom-out.svg";
|
|||
import ViewModeNormal from "../../../../assets/16px-solid/view-mode-normal.svg";
|
||||
import ViewModeOutline from "../../../../assets/16px-solid/view-mode-outline.svg";
|
||||
import ViewModePixels from "../../../../assets/16px-solid/view-mode-pixels.svg";
|
||||
import EyeVisible from "../../../../assets/16px-solid/visibility-eye-visible.svg";
|
||||
import EyeHidden from "../../../../assets/16px-solid/visibility-eye-hidden.svg";
|
||||
import EyeVisible from "../../../../assets/16px-solid/eye-visible.svg";
|
||||
import EyeHidden from "../../../../assets/16px-solid/eye-hidden.svg";
|
||||
import GraphiteLogo from "../../../../assets/16px-solid/graphite-logo.svg";
|
||||
import File from "../../../../assets/16px-solid/file.svg";
|
||||
import Copy from "../../../../assets/16px-solid/copy.svg";
|
||||
|
@ -81,8 +81,13 @@ import ViewportDesignMode from "../../../../assets/16px-solid/viewport-design-mo
|
|||
import ViewportSelectMode from "../../../../assets/16px-solid/viewport-select-mode.svg";
|
||||
import ViewportGuideMode from "../../../../assets/16px-solid/viewport-guide-mode.svg";
|
||||
|
||||
import SwapButton from "../../../../assets/12px-solid/swap.svg";
|
||||
import ResetColorsButton from "../../../../assets/12px-solid/reset-colors.svg";
|
||||
import Checkmark from "../../../../assets/12px-solid/checkmark.svg";
|
||||
import Link from "../../../../assets/12px-solid/link.svg";
|
||||
import Grid from "../../../../assets/12px-solid/grid.svg";
|
||||
import Overlays from "../../../../assets/12px-solid/overlays.svg";
|
||||
import Snapping from "../../../../assets/12px-solid/snapping.svg";
|
||||
import Swap from "../../../../assets/12px-solid/swap.svg";
|
||||
import ResetColors from "../../../../assets/12px-solid/reset-colors.svg";
|
||||
import DropdownArrow from "../../../../assets/12px-solid/dropdown-arrow.svg";
|
||||
import VerticalEllipsis from "../../../../assets/12px-solid/vertical-ellipsis.svg";
|
||||
import CloseX from "../../../../assets/12px-solid/close-x.svg";
|
||||
|
@ -154,8 +159,13 @@ const icons = {
|
|||
ViewportDesignMode: { component: ViewportDesignMode, size: 16 },
|
||||
ViewportSelectMode: { component: ViewportSelectMode, size: 16 },
|
||||
ViewportGuideMode: { component: ViewportGuideMode, size: 16 },
|
||||
SwapButton: { component: SwapButton, size: 12 },
|
||||
ResetColorsButton: { component: ResetColorsButton, size: 12 },
|
||||
Checkmark: { component: Checkmark, size: 12 },
|
||||
Link: { component: Link, size: 12 },
|
||||
Grid: { component: Grid, size: 12 },
|
||||
Overlays: { component: Overlays, size: 12 },
|
||||
Snapping: { component: Snapping, size: 12 },
|
||||
Swap: { component: Swap, size: 12 },
|
||||
ResetColors: { component: ResetColors, size: 12 },
|
||||
DropdownArrow: { component: DropdownArrow, size: 12 },
|
||||
VerticalEllipsis: { component: VerticalEllipsis, size: 12 },
|
||||
CloseX: { component: CloseX, size: 12 },
|
||||
|
|