Created
January 3, 2024 14:35
-
-
Save ZanzyTHEbar/75d7e2f83bcf7193d3238c07dc00fe62 to your computer and use it in GitHub Desktop.
Solid-DND
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createDraggable, transformStyle } from '@thisbeyond/solid-dnd' | |
import { JSXElement, createSignal, type ParentComponent, onMount } from 'solid-js' | |
import { TabsTrigger } from '@components/ui/tabs' | |
import { UITab, useAppContextUI } from '@context/ui' | |
/* Handle Dockable using solid-dnd */ | |
const activeTabClasses = [ | |
'tab-active', | |
'drop-shadow-2xl', | |
'shadow-2xl', | |
'[--tab-bg:var(--fallback-a,oklch(var(--p)/var(--tw-bg-opacity)))]', | |
'[--tab-border-color:var(--fallback-a,oklch(var(--p)/var(--tw-bg-opacity)))]', | |
'text-primary', | |
] | |
const DockableTab: ParentComponent<{ | |
icon: string | JSXElement | |
id: string | |
tab: UITab | |
}> = (props) => { | |
const [tabRef, setTabRef] = createSignal<Element | null>(null) | |
const { setSelectedTab, defaultTab } = useAppContextUI() | |
const draggable = createDraggable(props.id) | |
/** | |
* @description Set the default tab | |
*/ | |
onMount(() => { | |
handleActiveTab() | |
}) | |
/** | |
* @description Handle the click event | |
* @param {MouseEvent & { currentTarget: HTMLButtonElement; target: Element }} e - The click event | |
*/ | |
const handleClick = ( | |
e: MouseEvent & { | |
currentTarget: HTMLButtonElement | |
target: Element | |
}, | |
) => { | |
setSelectedTab(props.tab) | |
setTabRef(e.currentTarget) | |
handleActiveTab() | |
} | |
/** | |
* @description Set the selected tab element | |
* @returns {void} | |
*/ | |
const handleActiveTab = () => { | |
if (!tabRef()) { | |
setSelectedTab(defaultTab()) | |
const defaultTabElement = document.querySelector(`#${defaultTab().id}`) | |
setTabRef(defaultTabElement) | |
defaultTabElement!.classList.add(...activeTabClasses) | |
} | |
const tabs = document.querySelectorAll('.tab') | |
tabs.forEach((tab) => { | |
if (tab.classList.contains('tab-active')) { | |
tab.classList.remove(...activeTabClasses) | |
} | |
}) | |
tabRef()!.classList.add(...activeTabClasses) | |
} | |
return ( | |
<TabsTrigger | |
style={transformStyle(draggable.transform)} | |
class="draggable-container tab" | |
ref={draggable.ref} | |
id={props.id} | |
onClick={handleClick} | |
value={props.id}> | |
{props.icon} | |
</TabsTrigger> | |
) | |
} | |
export default DockableTab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DragDropProvider, DragDropSensors, createDroppable } from '@thisbeyond/solid-dnd' | |
import { | |
type Component, | |
For, | |
Show, | |
createSignal, | |
JSXElement, | |
onMount, | |
createEffect, | |
} from 'solid-js' | |
import DockableTab from '@components/DockableTab' | |
import { CardContent } from '@components/ui/card' | |
import { Tabs, TabsList, TabsContent } from '@components/ui/tabs' | |
import { useAppContextUI } from '@src/context/ui' | |
/* Handle Dockable using solid-dnd */ | |
const TabBar: Component = () => { | |
let ref: Element | |
// read in the tab context | |
const { tabs, defaultTab, selectedTab } = useAppContextUI() | |
const [id, setID] = createSignal<string>('') | |
const [content, setContent] = createSignal<JSXElement | null>(null) | |
const droppable = createDroppable('tab-bar') | |
onMount(() => { | |
setID(defaultTab().id) | |
setContent(defaultTab().content) | |
}) | |
createEffect(() => { | |
if (selectedTab() === null) return | |
setID(selectedTab()!.id) | |
setContent(selectedTab()!.content) | |
}) | |
const onDragEnd = ({ draggable, droppable }) => { | |
if (droppable) { | |
droppable.node.append(draggable.node) | |
} else { | |
ref.append(draggable.node) | |
} | |
} | |
return ( | |
<DragDropProvider onDragEnd={onDragEnd}> | |
<Tabs defaultValue={defaultTab().id} class="p-2 w-full"> | |
<TabsList> | |
<DragDropSensors /> | |
<For each={tabs()}> | |
{(tab) => ( | |
<Show when={tab.visible}> | |
<div | |
ref={droppable.ref} | |
class="droppable" | |
classList={{ | |
'!droppable-accept': droppable.isActiveDroppable, | |
}}> | |
<DockableTab ref={ref} id={tab.id} icon={tab.icon} tab={tab} /> | |
</div> | |
</Show> | |
)} | |
</For> | |
</TabsList> | |
<TabsContent class="h-full w-full p-2" value={id()}> | |
<CardContent class="bg-base-100 rounded-box">{content()}</CardContent> | |
</TabsContent> | |
</Tabs> | |
</DragDropProvider> | |
) | |
} | |
export default TabBar |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment