mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 18:38:05 +08:00
Populate tool shelf and tool options bar (#66)
This commit is contained in:
@@ -9,6 +9,10 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
<div class="tab-group">
|
||||
<div class="tab" :class="{ active: tabIndex === tabActiveIndex }" v-for="(tabLabel, tabIndex) in tabLabels" :key="tabLabel">
|
||||
<span>{{tabLabel}}</span>
|
||||
<button v-if="tabCloseButtons">
|
||||
<CloseX width="16" height="16" />
|
||||
</button>
|
||||
<IconButton :size="16" v-if="tabCloseButtons">
|
||||
<CloseX />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-options-ellipsis">
|
||||
<VerticalEllipsis />
|
||||
</div>
|
||||
<DropdownButton :icon="DropdownButtonIcon.VerticalEllipsis" />
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<component :is="panelType" />
|
||||
@@ -88,26 +86,8 @@
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
button {
|
||||
flex: 0 0 auto;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: none;
|
||||
color: #ddd;
|
||||
font-weight: bold;
|
||||
font-size: 10px;
|
||||
border-radius: 2px;
|
||||
.icon-button {
|
||||
margin-left: 8px;
|
||||
fill: #ddd;
|
||||
|
||||
&:hover {
|
||||
background: #555;
|
||||
color: white;
|
||||
fill: white;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.active) + .tab:not(.active) {
|
||||
@@ -137,24 +117,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-options-ellipsis {
|
||||
width: 16px;
|
||||
height: 24px;
|
||||
margin: 2px 4px;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 24px;
|
||||
border-radius: 2px;
|
||||
fill: #ddd;
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
background: #555;
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
@@ -170,6 +132,8 @@ import Document from "../panels/Document.vue";
|
||||
import Properties from "../panels/Properties.vue";
|
||||
import LayerTree from "../panels/LayerTree.vue";
|
||||
import Minimap from "../panels/Minimap.vue";
|
||||
import IconButton from "../widgets/IconButton.vue";
|
||||
import DropdownButton, { DropdownButtonIcon } from "../widgets/DropdownButton.vue";
|
||||
import VerticalEllipsis from "../../../assets/svg/16x24-bounds-8x16-icon/vertical-ellipsis.svg";
|
||||
import CloseX from "../../../assets/svg/16x16-bounds-12x12-icon/close-x.svg";
|
||||
|
||||
@@ -179,6 +143,8 @@ export default defineComponent({
|
||||
Properties,
|
||||
LayerTree,
|
||||
Minimap,
|
||||
IconButton,
|
||||
DropdownButton,
|
||||
CloseX,
|
||||
VerticalEllipsis,
|
||||
},
|
||||
@@ -189,5 +155,10 @@ export default defineComponent({
|
||||
tabActiveIndex: { type: Number, required: true },
|
||||
panelType: { type: String, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
DropdownButtonIcon,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -2,16 +2,154 @@
|
||||
<LayoutCol :class="'document'">
|
||||
<LayoutRow :class="'options-bar'">
|
||||
<div class="left side">
|
||||
<!-- <span class="label">Select</span>
|
||||
<div class="divider"></div> -->
|
||||
<span class="label">Select</span>
|
||||
|
||||
<ItemDivider />
|
||||
|
||||
<IconButton :size="24" title="Horizontal Align Left">
|
||||
<AlignHorizontalLeft />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Horizontal Align Center">
|
||||
<AlignHorizontalCenter />
|
||||
</IconButton>
|
||||
<IconButton :size="24" gapAfter title="Horizontal Align Right">
|
||||
<AlignHorizontalRight />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Vertical Align Top">
|
||||
<AlignVerticalTop />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Vertical Align Center">
|
||||
<AlignVerticalCenter />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Vertical Align Bottom">
|
||||
<AlignVerticalBottom />
|
||||
</IconButton>
|
||||
<DropdownButton />
|
||||
|
||||
<ItemDivider />
|
||||
|
||||
<IconButton :size="24" title="Flip Horizontal">
|
||||
<FlipHorizontal />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Flip Vertical">
|
||||
<FlipVertical />
|
||||
</IconButton>
|
||||
<DropdownButton />
|
||||
|
||||
<ItemDivider />
|
||||
|
||||
<IconButton :size="24" title="Boolean Union">
|
||||
<BooleanUnion />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Boolean Subtract Front">
|
||||
<BooleanSubtractFront />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Boolean Subtract Back">
|
||||
<BooleanSubtractBack />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Boolean Intersect">
|
||||
<BooleanIntersect />
|
||||
</IconButton>
|
||||
<IconButton :size="24" title="Boolean Difference">
|
||||
<BooleanDifference />
|
||||
</IconButton>
|
||||
<DropdownButton />
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="right side">
|
||||
<!-- <span class="label">Layer 1</span> -->
|
||||
</div>
|
||||
<div class="right side"></div>
|
||||
</LayoutRow>
|
||||
<LayoutRow :class="'shelf-and-viewport'">
|
||||
<LayoutCol :class="'shelf'"></LayoutCol>
|
||||
<LayoutCol :class="'shelf'">
|
||||
<div class="tools">
|
||||
<ShelfItem active title="Select Tool (V)">
|
||||
<SelectTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Crop Tool">
|
||||
<CropTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Navigate Tool">
|
||||
<NavigateTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Sample Tool">
|
||||
<SampleTool />
|
||||
</ShelfItem>
|
||||
<ItemDivider horizontal />
|
||||
<ShelfItem title="Text Tool">
|
||||
<TextTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Fill Tool">
|
||||
<FillTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Gradient Tool">
|
||||
<GradientTool />
|
||||
</ShelfItem>
|
||||
<ItemDivider horizontal />
|
||||
<ShelfItem title="Brush Tool">
|
||||
<BrushTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Heal Tool">
|
||||
<HealTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Clone Tool">
|
||||
<CloneTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Patch Tool">
|
||||
<PatchTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Blur/Sharpen Tool">
|
||||
<BlurSharpenTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Relight Tool">
|
||||
<RelightTool />
|
||||
</ShelfItem>
|
||||
<ItemDivider horizontal />
|
||||
<ShelfItem title="Path Tool">
|
||||
<PathTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Pen Tool">
|
||||
<PenTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Freehand Tool">
|
||||
<FreehandTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Spline Tool">
|
||||
<SplineTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Line Tool">
|
||||
<LineTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Rectangle Tool (M)">
|
||||
<RectangleTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Ellipse Tool (E)">
|
||||
<EllipseTool />
|
||||
</ShelfItem>
|
||||
<ShelfItem title="Shape Tool">
|
||||
<ShapeTool />
|
||||
</ShelfItem>
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="working-colors">
|
||||
<div class="swatch-pair">
|
||||
<button
|
||||
class="secondary swatch"
|
||||
style="background: white;"
|
||||
></button>
|
||||
<button
|
||||
class="primary swatch"
|
||||
style="background: black;"
|
||||
></button>
|
||||
</div>
|
||||
<div class="swap-and-reset">
|
||||
<IconButton :size="16">
|
||||
<SwapButton />
|
||||
</IconButton>
|
||||
<IconButton :size="16">
|
||||
<ResetColorsButton />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</LayoutCol>
|
||||
<LayoutCol :class="'viewport'">
|
||||
<div
|
||||
class="canvas"
|
||||
@@ -38,32 +176,46 @@
|
||||
flex: 0 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 4px;
|
||||
|
||||
> * {
|
||||
margin: 0 4px;
|
||||
}
|
||||
margin: 0 8px;
|
||||
|
||||
.label {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 24px;
|
||||
background: #888;
|
||||
}
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.shelf-and-viewport {
|
||||
.shelf {
|
||||
flex: 0 0 32px;
|
||||
|
||||
.swatch-pair {
|
||||
display: flex;
|
||||
// Reversed order of elements paired with `column-reverse` allows primary to overlap secondary without relying on `z-index`
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.working-colors {
|
||||
.swatch {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 2px #888 solid;
|
||||
box-shadow: 0 0 0 2px #333;
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
box-sizing: unset;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.primary.swatch {
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.swap-and-reset {
|
||||
font-size: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.viewport {
|
||||
@@ -82,12 +234,57 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The `where` pseduo-class does not contribtue to specificity
|
||||
:where(.document .options-bar .side > :not(:first-child)) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import LayoutRow from "../layout/LayoutRow.vue";
|
||||
import LayoutCol from "../layout/LayoutCol.vue";
|
||||
import ShelfItem from "../widgets/ShelfItem.vue";
|
||||
import ItemDivider from "../widgets/ItemDivider.vue";
|
||||
import IconButton from "../widgets/IconButton.vue";
|
||||
import DropdownButton from "../widgets/DropdownButton.vue";
|
||||
import SwapButton from "../../../assets/svg/16x16-bounds-12x12-icon/swap.svg";
|
||||
import ResetColorsButton from "../../../assets/svg/16x16-bounds-12x12-icon/reset-colors.svg";
|
||||
import SelectTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-layout-select.svg";
|
||||
import CropTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-layout-crop.svg";
|
||||
import NavigateTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-layout-navigate.svg";
|
||||
import SampleTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-layout-sample.svg";
|
||||
import TextTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-parametric-text.svg";
|
||||
import FillTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-parametric-fill.svg";
|
||||
import GradientTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-parametric-gradient.svg";
|
||||
import BrushTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-brush.svg";
|
||||
import HealTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-heal.svg";
|
||||
import CloneTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-clone.svg";
|
||||
import PatchTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-patch.svg";
|
||||
import BlurSharpenTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-blur-sharpen.svg";
|
||||
import RelightTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-raster-relight.svg";
|
||||
import PathTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-path.svg";
|
||||
import PenTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-pen.svg";
|
||||
import FreehandTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-freehand.svg";
|
||||
import SplineTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-spline.svg";
|
||||
import LineTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-line.svg";
|
||||
import RectangleTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-rectangle.svg";
|
||||
import EllipseTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-ellipse.svg";
|
||||
import ShapeTool from "../../../assets/svg/24x24-bounds-24x24-icon/document-tool-vector-shape.svg";
|
||||
import AlignHorizontalLeft from "../../../assets/svg/24x24-bounds-16x16-icon/align-horizontal-left.svg";
|
||||
import AlignHorizontalCenter from "../../../assets/svg/24x24-bounds-16x16-icon/align-horizontal-center.svg";
|
||||
import AlignHorizontalRight from "../../../assets/svg/24x24-bounds-16x16-icon/align-horizontal-right.svg";
|
||||
import AlignVerticalTop from "../../../assets/svg/24x24-bounds-16x16-icon/align-vertical-top.svg";
|
||||
import AlignVerticalCenter from "../../../assets/svg/24x24-bounds-16x16-icon/align-vertical-center.svg";
|
||||
import AlignVerticalBottom from "../../../assets/svg/24x24-bounds-16x16-icon/align-vertical-bottom.svg";
|
||||
import FlipHorizontal from "../../../assets/svg/24x24-bounds-16x16-icon/flip-horizontal.svg";
|
||||
import FlipVertical from "../../../assets/svg/24x24-bounds-16x16-icon/flip-vertical.svg";
|
||||
import BooleanUnion from "../../../assets/svg/24x24-bounds-16x16-icon/boolean-union.svg";
|
||||
import BooleanSubtractFront from "../../../assets/svg/24x24-bounds-16x16-icon/boolean-subtract-front.svg";
|
||||
import BooleanSubtractBack from "../../../assets/svg/24x24-bounds-16x16-icon/boolean-subtract-back.svg";
|
||||
import BooleanIntersect from "../../../assets/svg/24x24-bounds-16x16-icon/boolean-intersect.svg";
|
||||
import BooleanDifference from "../../../assets/svg/24x24-bounds-16x16-icon/boolean-difference.svg";
|
||||
|
||||
const wasm = import("../../../wasm/pkg");
|
||||
|
||||
@@ -95,6 +292,46 @@ export default defineComponent({
|
||||
components: {
|
||||
LayoutRow,
|
||||
LayoutCol,
|
||||
ShelfItem,
|
||||
ItemDivider,
|
||||
IconButton,
|
||||
DropdownButton,
|
||||
SwapButton,
|
||||
ResetColorsButton,
|
||||
SelectTool,
|
||||
CropTool,
|
||||
NavigateTool,
|
||||
SampleTool,
|
||||
TextTool,
|
||||
FillTool,
|
||||
GradientTool,
|
||||
BrushTool,
|
||||
HealTool,
|
||||
CloneTool,
|
||||
PatchTool,
|
||||
BlurSharpenTool,
|
||||
RelightTool,
|
||||
PathTool,
|
||||
PenTool,
|
||||
FreehandTool,
|
||||
SplineTool,
|
||||
LineTool,
|
||||
RectangleTool,
|
||||
EllipseTool,
|
||||
ShapeTool,
|
||||
AlignHorizontalLeft,
|
||||
AlignHorizontalCenter,
|
||||
AlignHorizontalRight,
|
||||
AlignVerticalTop,
|
||||
AlignVerticalCenter,
|
||||
AlignVerticalBottom,
|
||||
FlipHorizontal,
|
||||
FlipVertical,
|
||||
BooleanUnion,
|
||||
BooleanSubtractFront,
|
||||
BooleanSubtractBack,
|
||||
BooleanIntersect,
|
||||
BooleanDifference,
|
||||
},
|
||||
methods: {
|
||||
async canvasMouseDown(e: MouseEvent) {
|
||||
@@ -118,10 +355,9 @@ export default defineComponent({
|
||||
on_key_up(e.key);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
let self = this;
|
||||
window.addEventListener("keyup", (evt: KeyboardEvent) => {self.keyUp(evt)})
|
||||
window.addEventListener("keydown", (evt: KeyboardEvent) => {self.keyDown(evt)})
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener("keyup", (e: KeyboardEvent) => this.keyUp(e));
|
||||
window.addEventListener("keydown", (e: KeyboardEvent) => this.keyDown(e));
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
45
client/web/src/components/widgets/DropdownButton.vue
Normal file
45
client/web/src/components/widgets/DropdownButton.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<button class="dropdown-button">
|
||||
<component :is="icon" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdown-button {
|
||||
width: 16px;
|
||||
height: 24px;
|
||||
margin: 2px 4px;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background: #111;
|
||||
fill: #ddd;
|
||||
|
||||
&:hover {
|
||||
background: #555;
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import DropdownArrow from "../../../assets/svg/16x24-bounds-8x16-icon/dropdown-arrow.svg";
|
||||
import VerticalEllipsis from "../../../assets/svg/16x24-bounds-8x16-icon/vertical-ellipsis.svg";
|
||||
|
||||
export enum DropdownButtonIcon {
|
||||
"DropdownArrow" = "DropdownArrow",
|
||||
"VerticalEllipsis" = "VerticalEllipsis",
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
VerticalEllipsis,
|
||||
DropdownArrow,
|
||||
},
|
||||
props: {
|
||||
icon: { type: String, default: DropdownButtonIcon.DropdownArrow },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
64
client/web/src/components/widgets/IconButton.vue
Normal file
64
client/web/src/components/widgets/IconButton.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<button class="icon-button" :class="[`size-${String(size)}`, gapAfter && 'gap-after']">
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-button {
|
||||
display: inline-block;
|
||||
flex: 0 0 auto;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: none;
|
||||
font-weight: bold;
|
||||
font-size: 10px;
|
||||
border-radius: 2px;
|
||||
color: #ddd;
|
||||
fill: #ddd;
|
||||
|
||||
&:not(.gap-after) + .icon-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #555;
|
||||
color: white;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
&.size-10 {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
&.size-12 {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
&.size-16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&.size-24 {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
size: { type: Number, required: true },
|
||||
gapAfter: { type: Boolean, default: false },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
51
client/web/src/components/widgets/ItemDivider.vue
Normal file
51
client/web/src/components/widgets/ItemDivider.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div class="item-spacer" :class="{ horizontal: horizontal }">
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.item-spacer {
|
||||
margin-left: 0;
|
||||
|
||||
& + * {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:not(.horizontal) {
|
||||
height: 100%;
|
||||
padding: 0 8px;
|
||||
|
||||
div {
|
||||
height: calc(100% - 8px);
|
||||
width: 1px;
|
||||
margin: 4px 0;
|
||||
background: #888;
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
width: 100%;
|
||||
padding: 8px 0;
|
||||
|
||||
div {
|
||||
height: 1px;
|
||||
width: calc(100% - 8px);
|
||||
margin: 0 4px;
|
||||
background: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
},
|
||||
props: {
|
||||
horizontal: { type: Boolean, default: false },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
35
client/web/src/components/widgets/ShelfItem.vue
Normal file
35
client/web/src/components/widgets/ShelfItem.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="shelf-item" :class="{ active: active }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.shelf-item {
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
|
||||
&:hover {
|
||||
background: #555;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #428bbb;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
active: { type: Boolean, default: false },
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user