Skip to content

Commit

Permalink
fix: UX enhancements (#240)
Browse files Browse the repository at this point in the history
closes: #229
  • Loading branch information
surajshetty3416 authored Nov 2, 2024
1 parent 9143f34 commit 99fc69f
Show file tree
Hide file tree
Showing 13 changed files with 233 additions and 123 deletions.
5 changes: 4 additions & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ const isDark = useDark({
[id^="headlessui-menu-items"],
[id^="headlessui-combobox-options"] {
@apply bg-surface-gray-1;
@apply bg-surface-white;
@apply dark:bg-surface-gray-1;
@apply text-text-icons-gray-7;
@apply overflow-y-auto;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none;
Expand Down
67 changes: 43 additions & 24 deletions frontend/src/components/BlockEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,22 @@
:class="getStyleClasses">
<PaddingHandler
:data-block-id="block.blockId"
v-if="
isBlockSelected &&
!resizing &&
!editable &&
!blockController.multipleBlocksSelected() &&
!block.isSVG()
"
v-show="showPaddingHandler"
:target-block="block"
:target="target"
:on-update="updateTracker"
:disable-handlers="false"
:breakpoint="breakpoint" />
<MarginHandler
v-if="
isBlockSelected &&
!block.isRoot() &&
!resizing &&
!editable &&
!blockController.multipleBlocksSelected()
"
v-show="showMarginHandler"
:target-block="block"
:target="target"
:on-update="updateTracker"
:disable-handlers="false"
:breakpoint="breakpoint" />
<BorderRadiusHandler
:data-block-id="block.blockId"
v-if="
isBlockSelected &&
!block.isRoot() &&
!block.isText() &&
!block.isHTML() &&
!block.isSVG() &&
!editable &&
!resizing &&
!blockController.multipleBlocksSelected()
"
v-if="showBorderRadiusHandler"
:target-block="block"
:target="target" />
<BoxResizer v-if="showResizer" :targetBlock="block" @resizing="resizing = $event" :target="target" />
Expand Down Expand Up @@ -114,6 +93,41 @@ const guides = setGuides(props.target, canvasProps);
const moving = ref(false);
const preventCLick = ref(false);
const showPaddingHandler = computed(() => {
return (
isBlockSelected.value &&
!resizing.value &&
!props.editable &&
!blockController.multipleBlocksSelected() &&
!props.block.isSVG() &&
!props.block.isText()
);
});
const showMarginHandler = computed(() => {
return (
isBlockSelected.value &&
!props.block.isRoot() &&
!resizing.value &&
!props.editable &&
!blockController.multipleBlocksSelected() &&
!props.block.isText()
);
});
const showBorderRadiusHandler = computed(() => {
return (
isBlockSelected &&
!props.block.isRoot() &&
!props.block.isText() &&
!props.block.isHTML() &&
!props.block.isSVG() &&
!props.editable &&
!resizing &&
!blockController.multipleBlocksSelected()
);
});
watchEffect(() => {
props.block.getStyle("top");
props.block.getStyle("left");
Expand Down Expand Up @@ -189,6 +203,11 @@ const handleClick = (ev: MouseEvent) => {
preventCLick.value = false;
return;
}
if (props.block.isText() || props.block.isButton() || props.block.isLink()) {
store.editableBlock = props.block;
}
const editorWrapper = editor.value;
editorWrapper.classList.add("pointer-events-none");
let element = document.elementFromPoint(ev.x, ev.y) as HTMLElement;
Expand Down
55 changes: 48 additions & 7 deletions frontend/src/components/BlockLayers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
</span>
</span>
<div v-show="canShowChildLayer(element)">
<BlockLayers :blocks="element.children" ref="childLayer" :indent="childIndent" />
<BlockLayers :blocks="element.children" :ref="childLayer" :indent="childIndent" />
</div>
</div>
</BlockContextMenu>
Expand All @@ -91,8 +91,15 @@ import BlockContextMenu from "./BlockContextMenu.vue";
import BlockLayers from "./BlockLayers.vue";
import BlocksIcon from "./Icons/Blocks.vue";
type LayerInstance = InstanceType<typeof BlockLayers>;
const store = useStore();
const childLayer = ref<InstanceType<typeof BlockLayers> | null>(null);
const childLayers = ref<LayerInstance[]>([]);
const childLayer = (el) => {
if (el) {
childLayers.value.push(el);
}
};
const props = defineProps({
blocks: {
Expand Down Expand Up @@ -123,19 +130,39 @@ const isExpanded = (block: Block) => {
return expandedLayers.value.has(block.blockId);
};
// TODO: Refactor this!
const toggleExpanded = (block: Block) => {
const blockIndex = props.blocks.findIndex((b) => b.blockId === block.blockId);
if (blockIndex === -1) {
childLayer.value?.toggleExpanded(block);
if (block.isRoot()) {
return;
}
if (isExpanded(block) && !block.isRoot()) {
if (!blockExits(block)) {
const child = childLayers.value.find((layer) => layer.blockExitsInTree(block)) as LayerInstance;
if (child) {
child.toggleExpanded(block);
}
}
if (isExpanded(block)) {
expandedLayers.value.delete(block.blockId);
} else {
expandedLayers.value.add(block.blockId);
}
};
// @ts-ignore
const isExpandedInTree = (block: Block) => {
if (!blockExits(block)) {
const child = childLayers.value.find((layer) => layer.blockExitsInTree(block)) as LayerInstance;
if (child) {
return child.isExpandedInTree(block);
}
}
return isExpanded(block);
};
const blockExits = (block: Block) => {
return props.blocks.find((b) => b.blockId === block.blockId);
};
const canShowChildLayer = (block: Block) => {
return (
((isExpanded(block) && block.hasChildren()) || (block.canHaveChildren() && !block.hasChildren())) &&
Expand All @@ -161,15 +188,29 @@ watch(
},
);
// @ts-ignore
const updateParent = (event) => {
event.item.__draggable_context.element.parentBlock = store.activeCanvas?.findBlock(
event.to.closest("[data-block-layer-id]").dataset.blockLayerId,
);
};
const blockExitsInTree = (block: Block) => {
if (blockExits(block)) {
return true;
}
for (const layer of childLayers.value) {
if (layer.blockExitsInTree(block)) {
return true;
}
}
return false;
};
defineExpose({
isExpanded,
toggleExpanded,
isExpandedInTree,
blockExitsInTree,
});
</script>
<style>
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/components/BlockProperties.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@
</div>
</div>
<div v-else>
<p class="mt-2 text-center text-sm text-gray-600 dark:text-zinc-500">
Select a block to edit properties.
</p>
<p class="mt-2 text-center text-sm text-gray-600 dark:text-zinc-500">Select a block to edit properties</p>
</div>
</template>
<script setup lang="ts">
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/components/BuilderBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<!-- prettier-ignore -->
<BlockEditor
ref="editor"
v-show="!isEditable"
v-if="loadEditor"
:block="block"
:breakpoint="breakpoint"
Expand Down Expand Up @@ -231,6 +232,12 @@ const triggerContextMenu = (e: MouseEvent) => {
const handleClick = (e: MouseEvent) => {
if (isEditable.value) return;
if (store.preventClick) {
e.stopPropagation();
e.preventDefault();
store.preventClick = false;
return;
}
selectBlock(e);
e.stopPropagation();
e.preventDefault();
Expand Down
119 changes: 58 additions & 61 deletions frontend/src/components/BuilderCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ import {
getBlockInstance,
getBlockObject,
getNumberFromPx,
isCtrlOrCmd,
isTargetEditable,
uploadImage,
} from "@/utils/helpers";
Expand Down Expand Up @@ -428,68 +427,66 @@ function setEvents() {
});
useEventListener(document, "keydown", (ev: KeyboardEvent) => {
if (isTargetEditable(ev)) {
return;
}
if (ev.shiftKey && ev.key === "ArrowLeft") {
if (isCtrlOrCmd(ev)) {
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
store.activeLayers?.toggleExpanded(selectedBlock);
return;
}
}
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
const parentBlock = selectedBlock.getParentBlock();
if (parentBlock) {
selectionTrail.push(selectedBlock.blockId);
maintainTrail = true;
store.selectBlock(parentBlock, null, true, true);
maintainTrail = false;
}
}
}
if (ev.shiftKey && ev.key === "ArrowRight") {
const blockId = selectionTrail.pop();
if (blockId) {
const block = findBlock(blockId);
if (block) {
maintainTrail = true;
store.selectBlock(block, null, true, true);
maintainTrail = false;
}
} else {
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
if (selectedBlock.children && selectedBlock.isVisible()) {
let child = selectedBlock.children[0];
while (child && !child.isVisible()) {
child = child.getSiblingBlock("next") as Block;
if (!child) {
break;
}
}
child && store.selectBlock(child, null, true, true);
}
}
}
}
if (ev.shiftKey && ev.key === "ArrowUp") {
if (selectedBlocks.value.length) {
let sibling = selectedBlocks.value[0].getSiblingBlock("previous");
if (sibling) {
store.selectBlock(sibling, null, true, true);
}
if (isTargetEditable(ev) || selectedBlocks.value.length !== 1) return;
const selectedBlock = selectedBlocks.value[0];
const selectBlock = (block: Block | null) => {
if (block) store.selectBlock(block, null, true, true);
return !!block;
};
const selectSibling = (direction: "previous" | "next", fallback: () => void) => {
selectBlock(selectedBlock.getSiblingBlock(direction)) || fallback();
};
const selectParent = () => selectBlock(selectedBlock.getParentBlock());
const selectFirstChild = () => selectBlock(selectedBlock.children[0]);
const selectNextSiblingOrParent = () => {
let sibling = selectedBlock.getSiblingBlock("next");
let parentBlock = selectedBlock.getParentBlock();
while (!sibling && parentBlock) {
sibling = parentBlock.getSiblingBlock("next");
parentBlock = parentBlock.getParentBlock();
}
}
if (ev.shiftKey && ev.key === "ArrowDown") {
if (selectedBlocks.value.length) {
let sibling = selectedBlocks.value[0].getSiblingBlock("next");
if (sibling) {
store.selectBlock(sibling, null, true, true);
}
selectBlock(sibling);
};
const selectLastChildInTree = (block: Block) => {
let currentBlock = block;
while (store.activeLayers?.isExpandedInTree(currentBlock)) {
const lastChild = currentBlock.getLastChild() as Block;
if (!lastChild) break;
currentBlock = lastChild;
}
selectBlock(currentBlock);
};
switch (ev.key) {
case "ArrowLeft":
store.activeLayers?.isExpandedInTree(selectedBlock)
? store.activeLayers.toggleExpanded(selectedBlock)
: selectSibling("previous", selectParent);
break;
case "ArrowRight":
selectedBlock.hasChildren() && selectedBlock.isVisible()
? (store.activeLayers?.toggleExpanded(selectedBlock), selectFirstChild())
: selectNextSiblingOrParent();
break;
case "ArrowUp":
selectBlock(selectedBlock.getSiblingBlock("previous"))
? selectLastChildInTree(selectedBlock.getSiblingBlock("previous") as Block)
: selectParent();
break;
case "ArrowDown":
store.activeLayers?.isExpandedInTree(selectedBlock) &&
selectedBlock.hasChildren() &&
selectedBlock.isVisible()
? selectFirstChild()
: selectNextSiblingOrParent();
break;
}
});
}
Expand Down
Loading

0 comments on commit 99fc69f

Please sign in to comment.