Skip to content

Commit

Permalink
feat: elements naming (#34)
Browse files Browse the repository at this point in the history
* feat: elements naming

* feat: naming section in right panel

* fix: remove reduntant section

* fix: rebase the branch
  • Loading branch information
vshakitskiy authored Dec 31, 2023
1 parent 67c022c commit bd4f65d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
78 changes: 75 additions & 3 deletions apps/dashboard/src/components/LeftPanel/ElementRow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useSortable } from "@dnd-kit/sortable"
import { CSS } from '@dnd-kit/utilities';
import { useRef, useState } from "react";
import type { FormEvent } from "react";
import type { OGElement } from "../../lib/types";
import { NotVisibleIcon } from "../icons/NotVisibleIcon"
import { TextIcon } from "../icons/TextIcon"
Expand All @@ -8,6 +10,7 @@ import { BoxIcon } from "../icons/BoxIcon"
import { CircleIcon } from "../icons/CircleIcon"
import { ImageIcon } from "../icons/ImageIcon"
import { MagicWandIcon } from "../icons/MagicWandIcon"
import { CheckIcon } from "../icons/CheckIcon";
import { useElementsStore } from "../../stores/elementsStore";

interface ElementRowProps {
Expand All @@ -31,11 +34,47 @@ export function ElementRow({ element }: ElementRowProps) {
transition,
};

const [isEditing, setIsEditing] = useState(false)
const formRef = useRef<HTMLFormElement>(null)

function onSubmit(event: FormEvent) {
event.preventDefault()

if (!element.name) {
let defaultName = ""

if (element.tag === 'p') {
defaultName = "Text"
} else if (element.tag === 'div' && element.backgroundImage) {
defaultName = "Image"
} else if (element.tag === 'div' && !element.backgroundImage && !element.radius) {
defaultName = "Box"
} else if (element.tag === 'div' && !element.backgroundImage && element.radius) {
defaultName = "Rounded box"
} else {
defaultName = "Dynamic text"
}

updateElement({
...element,
name: defaultName
})
}

setIsEditing(false)
}

return (
<div className="flex justify-between items-center cursor-auto group" ref={setNodeRef} style={style} {...attributes} {...listeners}>
<div className="flex justify-between items-center cursor-auto group h-7" ref={setNodeRef} style={style} {...attributes} {...listeners}>
<button
className={`flex gap-2 select-none py-1 text-gray-600 hover:text-gray-900 w-full ${selectedElementId === element.id ? '!text-blue-500' : ''} ${!element.visible ? '!text-gray-300' : ''}`}
className={`flex items-center gap-2 select-none text-gray-600 hover:text-gray-900 w-full ${selectedElementId === element.id ? '!text-blue-500' : ''} ${!element.visible ? '!text-gray-300' : ''}`}
onClick={() => { setSelectedElementId(element.id); }}
onDoubleClick={() => {
if (isEditing)
return

setIsEditing(true)
}}
type="button"
>
{element.tag === 'p'
Expand All @@ -58,7 +97,40 @@ export function ElementRow({ element }: ElementRowProps) {
? <MagicWandIcon height="1.4em" width="1.4em" />
: null
}
{element.name}
{isEditing ? (
<form className="flex items-center gap-2" onSubmit={onSubmit} ref={formRef}>
<input

// eslint-disable-next-line -- Usability and accessibility for users is not reduced here
autoFocus
className="w-48"
id="elementNameInput"
onChange={({ target }) => {
updateElement({
...element,
name: target.value
})
}}
onKeyDown={(event) => {
event.stopPropagation()
if (event.key === "Enter" || event.key === "Escape") {
formRef.current?.requestSubmit()
}
if (event.key === "Spacebar") {
console.log("!")
}
}}
type="text"
value={element.name}
/>
<button
className="text-gray-600 hover:text-gray-900"
type="submit"
>
<CheckIcon />
</button>
</form>
) : element.name}
</button>
<button
className={`text-gray-600 hover:text-gray-900 hidden group-hover:block ${!element.visible ? '!block' : ''}`}
Expand Down
7 changes: 7 additions & 0 deletions apps/dashboard/src/components/icons/CheckIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { SVGProps } from "react";

export function CheckIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg height="1em" viewBox="0 0 30 30" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}><path d="M 26.980469 5.9902344 A 1.0001 1.0001 0 0 0 26.292969 6.2929688 L 11 21.585938 L 4.7070312 15.292969 A 1.0001 1.0001 0 1 0 3.2929688 16.707031 L 10.292969 23.707031 A 1.0001 1.0001 0 0 0 11.707031 23.707031 L 27.707031 7.7070312 A 1.0001 1.0001 0 0 0 26.980469 5.9902344 z" /></svg>
)
}
2 changes: 2 additions & 0 deletions apps/dashboard/src/stores/elementsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export const useElementsStore = create<ElementsState>()(temporal((set, get) => (
// Blur the currently focused DOM element (e.g. an input) when the user
// edits an element
if (document.activeElement instanceof HTMLElement) {
if (document.activeElement.id === "elementNameInput")
return
document.activeElement.blur()
}
},
Expand Down

0 comments on commit bd4f65d

Please sign in to comment.