Skip to content

Commit

Permalink
- Add popover stack.
Browse files Browse the repository at this point in the history
- Improve song itemcontext menu.
  • Loading branch information
duduBTW committed Nov 1, 2024
1 parent add155d commit 71b0f53
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 124 deletions.
3 changes: 3 additions & 0 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Scenes } from "../../@types";
import NoticeContainer from "./components/notice/NoticeContainer";
import Popover from "./components/popover/Popover";
import "./keyboard-registers/initialize";
import { fetchOs, os, setOs } from "./lib/os";
import { TokenNamespace } from "./lib/tungsten/token";
Expand Down Expand Up @@ -55,6 +56,8 @@ export default function App(): JSX.Element {
<ErrorScene />
</Match>
</Switch>

<Popover.PortalMountStack />
</Show>
);
}
Expand Down
36 changes: 34 additions & 2 deletions src/renderer/src/components/popover/Popover.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Token, TokenNamespace } from "@renderer/lib/tungsten/token";
import PopoverContent from "./PopoverContent";
import PopoverOverlay from "./PopoverOverlay";
import PopoverTrigger, { PopoverAnchor } from "./PopoverTrigger";
Expand All @@ -22,7 +23,10 @@ import {
ParentComponent,
Accessor,
createEffect,
onMount,
onCleanup,
} from "solid-js";
import { PopoverPortal, PopoverPortalMountStack } from "./PopoverPortal";

export const DEFAULT_POPOVER_OPEN = false;

Expand All @@ -37,6 +41,9 @@ export type Props = {
onValueChange?: (newOpen: boolean) => void;
};

export const [popoverStack, setPopoverStack] = createSignal<Token[]>([]);
const stackIds = new TokenNamespace();

export type Context = ReturnType<typeof useProviderValue>;

function useProviderValue(props: Props) {
Expand All @@ -51,6 +58,13 @@ function useProviderValue(props: Props) {
const [position, setPosition] = createSignal<ComputePositionReturn | null>(null);
const [triggerRef, _setTriggerRef] = createSignal<HTMLElement | null>(null);
const [contentRef, _setContentRef] = createSignal<HTMLDivElement | null>(null);
const [id, setId] = createSignal<string>("");

onMount(() => {
onCleanup(() => {
stackIds.destroy(id());
});
});

createEffect(() => {
const triggerElement = triggerRef();
Expand Down Expand Up @@ -124,10 +138,26 @@ function useProviderValue(props: Props) {
}).then(setPosition);
};

createEffect(() => {
if (isOpen()) {
const newId = stackIds.create();
setPopoverStack((p) => [...p, newId]);
setId(newId);
} else {
setPopoverStack((p) => p.filter((popoverId) => popoverId !== id()));
setId("");
}
});

return {
id,
isOpen,
open: () => setIsOpen(true),
close: () => setIsOpen(false),
open: () => {
setIsOpen(true);
},
close: () => {
setIsOpen(false);
},
toggle: () => setIsOpen((o) => !o),
position,
setPosition,
Expand All @@ -154,6 +184,8 @@ export function usePopover(): Context {
}

const Popover = Object.assign(PopoverRoot, {
Portal: PopoverPortal,
PortalMountStack: PopoverPortalMountStack,
Content: PopoverContent,
Trigger: PopoverTrigger,
Anchor: PopoverAnchor,
Expand Down
14 changes: 11 additions & 3 deletions src/renderer/src/components/popover/PopoverContent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { cn, sn } from "@renderer/lib/css.utils";
import { usePopover } from "./Popover";
import { popoverStack, usePopover } from "./Popover";
import { ComputePositionReturn } from "@floating-ui/dom";
import createFocusTrap from "solid-focus-trap";
import { Component, onCleanup, onMount, Show } from "solid-js";
import { Component, createMemo, onCleanup, onMount, Show } from "solid-js";
import { JSX } from "solid-js/jsx-runtime";

function stylesFromPosition(position: ComputePositionReturn | null): JSX.CSSProperties | undefined {
Expand All @@ -20,13 +20,21 @@ export type Props = JSX.IntrinsicElements["div"];
const PopoverContent: Component<Props> = (props) => {
const state = usePopover();

const isLastPopoupOpen = createMemo(() => {
return state.isOpen() && popoverStack().at(-1) === state.id();
});

createFocusTrap({
element: state.contentRef,
enabled: state.isOpen,
enabled: isLastPopoupOpen,
});

onMount(() => {
const handleKeyUp = (e: KeyboardEvent) => {
if (!isLastPopoupOpen()) {
return;
}

switch (e.key) {
case "Escape":
state.close();
Expand Down
28 changes: 28 additions & 0 deletions src/renderer/src/components/popover/PopoverPortal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { popoverStack, usePopover } from "./Popover";
import { Component, For, ParentComponent, Show } from "solid-js";
import { Portal } from "solid-js/web";

export const PopoverPortal: ParentComponent = (props) => {
const state = usePopover();
return (
<Show when={state.isOpen() && state.id()}>
<Portal mount={document.getElementById(state.id())!}>{props.children}</Portal>
</Show>
);
};

export const PopoverPortalMountStack: Component = () => {
return (
<For each={popoverStack()}>
{(id, index) => (
<div
style={{
"z-index": 100 + index(),
position: "relative",
}}
id={id}
/>
)}
</For>
);
};
4 changes: 2 additions & 2 deletions src/renderer/src/components/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const SelectContent: Component<ListProps> = (props) => {
});

return (
<>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content
style={{
Expand All @@ -50,7 +50,7 @@ export const SelectContent: Component<ListProps> = (props) => {
>
<List {...props} />
</Popover.Content>
</>
</Popover.Portal>
);
};
export const SelectOption: Component<ListItemProps> = (props) => {
Expand Down

This file was deleted.

27 changes: 0 additions & 27 deletions src/renderer/src/components/song/context-menu/items/PlayNext.tsx

This file was deleted.

This file was deleted.

8 changes: 4 additions & 4 deletions src/renderer/src/components/song/song-item/SongItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { transparentize } from "polished";
import Popover from "@renderer/components/popover/Popover";
import { EllipsisVerticalIcon } from "lucide-solid";
import { Component, createSignal, JSXElement, onMount, createMemo } from "solid-js";
import { Portal } from "solid-js/web";
import { twMerge } from "tailwind-merge";

type SongItemProps = {
Expand Down Expand Up @@ -83,7 +82,7 @@ const SongItem: Component<SongItemProps> = (props) => {
shift
flip
>
<Portal>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content
onClick={(e) => {
Expand All @@ -93,7 +92,8 @@ const SongItem: Component<SongItemProps> = (props) => {
>
{props.contextMenu}
</Popover.Content>
</Portal>
</Popover.Portal>

<div
onMouseEnter={() => {
setIsHovering(true);
Expand Down Expand Up @@ -128,7 +128,7 @@ const SongItem: Component<SongItemProps> = (props) => {
onImageLoaded={processImage}
/>
<div
class="flex flex-col justify-center overflow-hidden rounded-md p-3 transition-transform pr-10 group-hover:pr-3"
class="flex flex-col justify-center overflow-hidden rounded-md p-3 transition-transform pr-10 group-hover:pr-6"
style={{
background: backgrund(),
"transition-property": "padding, background",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Props as PopoverContentProps } from "@renderer/components/popover/Popov
import { cn } from "@renderer/lib/css.utils";
import { ChevronDownIcon } from "lucide-solid";
import { Component, createMemo, JSX, mergeProps, ParentComponent, splitProps } from "solid-js";
import { Portal } from "solid-js/web";

// ------------
// Container
Expand Down Expand Up @@ -67,7 +66,7 @@ export const FilterOptionTrigger: Component<FilterOptionTriggerProps> = (_props)
<Popover.Trigger
{...rest}
class={cn(
"hover:bg-surface py-1 px-2.5 rounded text-sm flex gap-1 items-center",
"hover:bg-surface py-1 px-2.5 rounded text-sm flex gap-1.5 items-center focus-visible:bg-surface",
props.class,
)}
>
Expand Down Expand Up @@ -102,7 +101,7 @@ export const FilterOptionItem: Component<FilterOptionItemProps> = (_props) => {
// ------------
const FilterOptionContent: ParentComponent<PopoverContentProps> = (props) => {
return (
<Portal>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content
{...props}
Expand All @@ -111,7 +110,7 @@ const FilterOptionContent: ParentComponent<PopoverContentProps> = (props) => {
props.class,
)}
/>
</Portal>
</Popover.Portal>
);
};

Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/components/song/song-list/SongList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import List from "@renderer/components/list/List";
import { Optional, Order, ResourceID, Song, SongsQueryPayload, Tag } from "../../../../../@types";
import { Optional, Order, ResourceID, SongsQueryPayload, Tag } from "../../../../../@types";
import { SearchQueryError } from "../../../../../main/lib/search-parser/@search-types";
import { namespace } from "../../../App";
import Impulse from "../../../lib/Impulse";
Expand Down Expand Up @@ -105,8 +105,8 @@ const SongList: Component<SongViewProps> = (props) => {

const SongListContextMenuContent: Component = () => {
return (
<List class="w-40" defaultValue="playlist">
<List.Item value="playlist">
<List class="w-40">
<List.Item>
<span>Add to Playlist</span>
<ListPlus class="text-subtext" size={20} />
</List.Item>
Expand Down
Loading

0 comments on commit 71b0f53

Please sign in to comment.