Display tag and performer image on hover. on the scene edit page (#5739)

* add component for PerformerPopover
* show PerformerPopover for performer select values
* show TagPopover for tag select values
This commit is contained in:
blaspheme-ship-it 2025-04-02 04:27:35 +02:00 committed by GitHub
parent 1d3bc40a6b
commit 3489dca83a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 8 deletions

View file

@ -0,0 +1,71 @@
import React from "react";
import { ErrorMessage } from "../Shared/ErrorMessage";
import { LoadingIndicator } from "../Shared/LoadingIndicator";
import { HoverPopover } from "../Shared/HoverPopover";
import { useFindPerformer } from "../../core/StashService";
import { PerformerCard } from "./PerformerCard";
import { ConfigurationContext } from "../../hooks/Config";
import { Placement } from "react-bootstrap/esm/Overlay";
interface IPeromerPopoverCardProps {
id: string;
}
export const PerformerPopoverCard: React.FC<IPeromerPopoverCardProps> = ({
id,
}) => {
const { data, loading, error } = useFindPerformer(id);
if (loading)
return (
<div className="tag-popover-card-placeholder">
<LoadingIndicator card={true} message={""} />
</div>
);
if (error) return <ErrorMessage error={error.message} />;
if (!data?.findPerformer)
return <ErrorMessage error={`No tag found with id ${id}.`} />;
const performer = data.findPerformer;
return (
<div className="tag-popover-card">
<PerformerCard performer={performer} zoomIndex={0} />
</div>
);
};
interface IPeroformerPopoverProps {
id: string;
hide?: boolean;
placement?: Placement;
target?: React.RefObject<HTMLElement>;
}
export const PerformerPopover: React.FC<IPeroformerPopoverProps> = ({
id,
hide,
children,
placement = "top",
target,
}) => {
const { configuration: config } = React.useContext(ConfigurationContext);
const showPerformerCardOnHover = config?.ui.showTagCardOnHover ?? true;
if (hide || !showPerformerCardOnHover) {
return <>{children}</>;
}
return (
<HoverPopover
target={target}
placement={placement}
enterDelay={500}
leaveDelay={100}
content={<PerformerPopoverCard id={id} />}
>
{children}
</HoverPopover>
);
};

View file

@ -30,6 +30,8 @@ import { sortByRelevance } from "src/utils/query";
import { PatchComponent, PatchFunction } from "src/patch";
import { TruncatedText } from "../Shared/TruncatedText";
import TextUtils from "src/utils/text";
import { PerformerPopover } from "./PerformerPopover";
import { Placement } from "react-bootstrap/esm/Overlay";
export type SelectObject = {
id: string;
@ -71,7 +73,12 @@ const performerSelectSort = PatchFunction(
);
const _PerformerSelect: React.FC<
IFilterProps & IFilterValueProps<Performer> & { ageFromDate?: string | null }
IFilterProps &
IFilterValueProps<Performer> & {
ageFromDate?: string | null;
hoverPlacementLabel?: Placement;
hoverPlacementOptions?: Placement;
}
> = (props) => {
const [createPerformer] = usePerformerCreate();
@ -201,12 +208,17 @@ const _PerformerSelect: React.FC<
thisOptionProps = {
...optionProps,
children: (
<span className="performer-select-value">
<span>{object.name}</span>
{object.disambiguation && (
<span className="performer-disambiguation">{` (${object.disambiguation})`}</span>
)}
</span>
<PerformerPopover
id={object.id}
placement={props.hoverPlacementLabel ?? "top"}
>
<span className="performer-select-value">
<span>{object.name}</span>
{object.disambiguation && (
<span className="performer-disambiguation">{` (${object.disambiguation})`}</span>
)}
</span>
</PerformerPopover>
),
};

View file

@ -57,6 +57,7 @@ const tagSelectSort = PatchFunction("TagSelect.sort", sortTagsByRelevance);
export type TagSelectProps = IFilterProps &
IFilterValueProps<Tag> & {
hoverPlacement?: Placement;
hoverPlacementLabel?: Placement;
excludeIds?: string[];
};
@ -151,7 +152,14 @@ const _TagSelect: React.FC<TagSelectProps> = (props) => {
thisOptionProps = {
...optionProps,
children: object.name,
children: (
<TagPopover
id={object.id}
placement={props.hoverPlacementLabel ?? "top"}
>
<span>{object.name}</span>
</TagPopover>
),
};
return <reactSelectComponents.MultiValueLabel {...thisOptionProps} />;