Skip to content

Commit

Permalink
feat: add support for pointer cursor (#517)
Browse files Browse the repository at this point in the history
* feat: add support for pointer cursor

(cherry picked from commit dcabf91)

* fix: correct useEffect update

(cherry picked from commit cbf0a82)

* feat: remove default values

* feat: pointer cursor

Signed-off-by: Innei <[email protected]>

* fix: remove select content animation when position is `item-aligned`

Signed-off-by: Innei <[email protected]>

* update hover

Signed-off-by: Innei <[email protected]>

---------

Signed-off-by: Innei <[email protected]>
Co-authored-by: Innei <[email protected]>
  • Loading branch information
yuzhang9804 and Innei authored Sep 21, 2024
1 parent 4dadd31 commit b6ff6fb
Show file tree
Hide file tree
Showing 34 changed files with 97 additions and 49 deletions.
1 change: 1 addition & 0 deletions apps/renderer/src/atoms/settings/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const createDefaultSettings = (): UISettings => ({
modalDraggable: true,
modalOpaque: true,
reduceMotion: false,
usePointerCursor: false,

// Font
uiFontFamily: "SN Pro",
Expand Down
4 changes: 3 additions & 1 deletion apps/renderer/src/components/common/ShadowDOM.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const ShadowDOM: FC<PropsWithChildren<React.HTMLProps<HTMLElement>>> & {

const uiFont = useUISettingKey("uiFontFamily")
const reduceMotion = useReduceMotion()
const usePointerCursor = useUISettingKey("usePointerCursor")

return (
<root.div {...rest}>
Expand All @@ -111,8 +112,9 @@ export const ShadowDOM: FC<PropsWithChildren<React.HTMLProps<HTMLElement>>> & {
style={useMemo(
() => ({
fontFamily: `${uiFont},"SN Pro", system-ui, sans-serif`,
"--pointer": usePointerCursor ? "pointer" : "default",
}),
[uiFont],
[uiFont, usePointerCursor],
)}
id="shadow-html"
data-motion-reduce={reduceMotion}
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/components/ui/button/variants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cn } from "~/lib/utils"

export const styledButtonVariant = cva(
[
"inline-flex cursor-default select-none items-center justify-center gap-2 outline-offset-2 transition active:transition-none disabled:cursor-not-allowed",
"inline-flex cursor-button select-none items-center justify-center gap-2 outline-offset-2 transition active:transition-none disabled:cursor-not-allowed",
"ring-accent/20 duration-200 disabled:ring-0",
"align-middle",
],
Expand Down
6 changes: 3 additions & 3 deletions apps/renderer/src/components/ui/context-menu/context-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const ContextMenuSubTrigger = React.forwardRef<
<ContextMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[state=open]:bg-theme-item-hover data-[state=open]:text-theme-foreground",
"flex cursor-menu select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[state=open]:bg-theme-item-hover data-[state=open]:text-theme-foreground",
inset && "pl-8",
"center gap-2",
className,
Expand Down Expand Up @@ -81,7 +81,7 @@ const ContextMenuItem = React.forwardRef<
<ContextMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-menu select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"focus-within:outline-transparent data-[highlighted]:bg-theme-item-hover dark:data-[highlighted]:bg-neutral-800",
inset && "pl-8",
className,
Expand All @@ -98,7 +98,7 @@ const ContextMenuCheckboxItem = React.forwardRef<
<ContextMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"relative flex cursor-checkbox select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-theme-item-hover focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"focus-within:outline-transparent",
className,
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover data-[state=open]:bg-theme-item-active",
"flex cursor-menu select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-theme-item-hover data-[state=open]:bg-theme-item-active",
inset && "pl-8",
className,
)}
Expand Down Expand Up @@ -80,7 +80,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-theme-item-hover data-[disabled]:pointer-events-none data-[state=open]:bg-theme-item-active data-[disabled]:opacity-50",
"relative flex cursor-menu select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-theme-item-hover data-[disabled]:pointer-events-none data-[state=open]:bg-theme-item-active data-[disabled]:opacity-50",
inset && "pl-8",
"focus-within:!outline-transparent",
className,
Expand All @@ -104,7 +104,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-theme-item-hover data-[disabled]:pointer-events-none data-[state=open]:bg-theme-item-active data-[disabled]:opacity-50",
"relative flex cursor-menu select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-theme-item-hover data-[disabled]:pointer-events-none data-[state=open]:bg-theme-item-active data-[disabled]:opacity-50",
className,
)}
checked={checked}
Expand Down
4 changes: 2 additions & 2 deletions apps/renderer/src/components/ui/media.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const MediaImpl: FC<MediaProps> = ({
onError={errorHandle}
className={cn(
!(props.width || props.height) && "size-full",
"bg-gray-200 object-cover duration-200 dark:bg-neutral-800",
"cursor-card bg-gray-200 object-cover duration-200 dark:bg-neutral-800",
popper && "cursor-zoom-in",
mediaLoadState === "loaded" ? "opacity-100" : "opacity-0",

Expand All @@ -126,7 +126,7 @@ const MediaImpl: FC<MediaProps> = ({
className={cn(
"center",
!(props.width || props.height) && "size-full",
"relative bg-stone-100 object-cover",
"relative cursor-card bg-stone-100 object-cover",
mediaContainerClassName,
)}
onClick={handleClick}
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/components/ui/media/SwipeMedia.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function SwipeMedia({
<div
ref={hoverRef}
className={cn(
"relative flex w-full items-center overflow-hidden",
"relative flex w-full items-center overflow-hidden ",
styles["swipe-wrapper"],
className,
)}
Expand Down
13 changes: 8 additions & 5 deletions apps/renderer/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const SelectTrigger = React.forwardRef<
"ring-accent/20 duration-200 focus:border-accent/80 focus:outline-none focus:ring-2",
"border border-border",
size === "sm" ? "h-7 p-2 text-sm" : "h-9 px-3 py-2 text-sm",
"hover:border-accent/80",
className,
)}
{...props}
Expand All @@ -40,7 +41,7 @@ const SelectScrollUpButton = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollUpButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
className={cn("flex cursor-select items-center justify-center py-1", className)}
{...props}
>
<i className="i-mingcute-up-line" />
Expand All @@ -54,7 +55,7 @@ const SelectScrollDownButton = React.forwardRef<
>(({ className, ...props }, ref) => (
<SelectPrimitive.ScrollDownButton
ref={ref}
className={cn("flex cursor-default items-center justify-center py-1", className)}
className={cn("flex cursor-select items-center justify-center py-1", className)}
{...props}
>
<i className="i-mingcute-down-line" />
Expand All @@ -70,9 +71,11 @@ const SelectContent = React.forwardRef<
<SelectPrimitive.Content
ref={ref}
className={cn(
"shadow-perfect relative z-[1000] max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
position === "popper" &&
"shadow-perfect relative z-[1000] max-h-96 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground",
position === "popper" && [
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
],
className,
)}
position={position}
Expand Down Expand Up @@ -113,7 +116,7 @@ const SelectItem = React.forwardRef<
<SelectPrimitive.Item
ref={ref}
className={cn(
"pointer-events-auto relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-theme-item-active focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
"pointer-events-auto relative flex w-full cursor-select items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-theme-item-active focus:text-theme-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className,
)}
{...props}
Expand Down
7 changes: 5 additions & 2 deletions apps/renderer/src/components/ui/switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ const Switch = React.forwardRef<
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
"peer inline-flex h-5 w-9 shrink-0 cursor-switch items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
"duration-200 data-[state=checked]:bg-accent data-[state=unchecked]:bg-theme-inactive dark:data-[state=unchecked]:bg-theme-accent-100/10",
"hover:data-[state=unchecked]:bg-theme-inactive/80 dark:hover:data-[state=unchecked]:bg-theme-accent-100/15",
"hover:data-[state=checked]:bg-accent/80 dark:hover:data-[state=checked]:bg-accent",
"group",
className,
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb className="pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0" />
<SwitchPrimitives.Thumb className="pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform duration-200 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 group-hover:dark:data-[state=checked]:!bg-black/80" />
</SwitchPrimitives.Root>
))
Switch.displayName = SwitchPrimitives.Root.displayName
Expand Down
6 changes: 6 additions & 0 deletions apps/renderer/src/initialize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import duration from "dayjs/plugin/duration"
import localizedFormat from "dayjs/plugin/localizedFormat"
import relativeTime from "dayjs/plugin/relativeTime"
import { enableMapSet } from "immer"
import React from "react"
import ReactDOM from "react-dom"
import { toast } from "sonner"

import { getUISettings } from "~/atoms/settings/ui"
Expand Down Expand Up @@ -119,6 +121,10 @@ export const initializeApp = async () => {
data_hydrated_time: dataHydratedTime,
version: APP_VERSION,
})

// expose `React` `ReactDOM` to global, it's easier for developers to make plugins
window.React = React
window.ReactDOM = ReactDOM
}

import.meta.hot?.dispose(cleanup)
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/ai/ai-daily/daily.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const DailyReportTitle = ({
<div className="font-medium">{t("ai_daily.title", { title })}</div>
<Tooltip>
<TooltipTrigger asChild>
<i className="i-mgc-question-cute-re translate-y-px text-sm" />
<i className="i-mgc-question-cute-re text-sm" />
</TooltipTrigger>
<TooltipPortal>
<TooltipContent>
Expand Down
29 changes: 15 additions & 14 deletions apps/renderer/src/modules/discover/recommendations-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ export const RecommendationCard: FC<RecommendationCardProps> = memo(({ data, rou
<CardContent className="p-5 pt-0">
<ul className="space-y-1 text-sm text-muted-foreground">
{Object.keys(data.routes).map((route) => (
<li
key={route}
className="duration-200 hover:text-theme-foreground-hover"
onClick={() => {
present({
content: () => (
<RecommendationContent routePrefix={routePrefix} route={data.routes[route]} />
),
icon: <FeedIcon className="size-4" size={16} siteUrl={`https://${data.url}`} />,
title: `${data.name} - ${data.routes[route].name}`,
})
}}
>
{data.routes[route].name}
<li key={route} className="duration-200 hover:text-theme-foreground-hover">
<button
type="button"
onClick={() => {
present({
content: () => (
<RecommendationContent routePrefix={routePrefix} route={data.routes[route]} />
),
icon: <FeedIcon className="size-4" size={16} siteUrl={`https://${data.url}`} />,
title: `${data.name} - ${data.routes[route].name}`,
})
}}
>
{data.routes[route].name}
</button>
</li>
))}
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function VideoItem({ entryId, entryPreview, translation }: UniversalItemP
return (
<GridItem entryId={entryId} entryPreview={entryPreview} translation={translation}>
<div
className="w-full"
className="w-full cursor-card"
onClick={() => {
if (iframeSrc) {
modalStack.present({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export function ListItem({
onMouseEnter={handlePrefetchEntry}
onMouseLeave={handlePrefetchEntry.cancel}
className={cn(
"group relative flex py-4 pl-3 pr-2",
"group relative flex cursor-menu py-4 pl-3 pr-2",
!asRead &&
"before:absolute before:-left-0.5 before:top-[1.4375rem] before:block before:size-2 before:rounded-full before:bg-accent",
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/entry-content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export const EntryContentRender: Component<{ entryId: string }> = ({ entryId, cl
<a
href={populatedFullHref || void 0}
target="_blank"
className="-mx-6 block cursor-default rounded-lg p-6 transition-colors hover:bg-theme-item-hover focus-visible:bg-theme-item-hover focus-visible:!outline-none @sm:-mx-3 @sm:p-3"
className="-mx-6 block cursor-button rounded-lg p-6 transition-colors hover:bg-theme-item-hover focus-visible:bg-theme-item-hover focus-visible:!outline-none @sm:-mx-3 @sm:p-3"
rel="noreferrer"
>
<div className="select-text break-words text-3xl font-bold">
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/feed-column/category.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function FeedCategoryImpl({
{!!showCollapse && (
<div
className={cn(
"flex w-full items-center justify-between rounded-md px-2.5 transition-colors",
"flex w-full cursor-menu items-center justify-between rounded-md px-2.5 transition-colors",
(isActive || isContextMenuOpen) && "bg-native-active",
)}
onClick={(e) => {
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/feed-column/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const LogoContextMenu: FC<PropsWithChildren> = ({ children }) => {
toast.success(t.common("app.copied_to_clipboard"))
}}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-1 py-0.5 text-sm outline-none",
"relative flex cursor-menu select-none items-center rounded-sm px-1 py-0.5 text-sm outline-none",
"focus-within:outline-transparent hover:bg-theme-item-hover dark:hover:bg-neutral-800",
"gap-2 text-foreground/80 [&_svg]:size-3",
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/feed-column/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const FeedItemImpl = ({ view, feedId, className, showUnreadCount = true }: FeedI
<div
data-feed-id={feedId}
className={cn(
"flex w-full items-center justify-between rounded-md py-[2px] pr-2.5 text-sm font-medium leading-loose",
"flex w-full cursor-menu items-center justify-between rounded-md py-[2px] pr-2.5 text-sm font-medium leading-loose",
(isActive || isContextMenuOpen) && "bg-native-active",

className,
Expand Down
4 changes: 2 additions & 2 deletions apps/renderer/src/modules/feed-column/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
<ScrollArea.ScrollArea mask={false} flex viewportClassName="!px-3" rootClassName="h-full">
<div
className={cn(
"flex h-8 w-full shrink-0 items-center rounded-md px-2.5 transition-colors",
"flex h-8 w-full shrink-0 cursor-menu items-center rounded-md px-2.5 transition-colors",
feedId === FEED_COLLECTION_LIST && "bg-native-active",
)}
onClick={(e) => {
Expand All @@ -140,7 +140,7 @@ function FeedListImpl({ className, view }: { className?: string; view: number })
<div className="flex h-full flex-1 items-center font-normal text-zinc-500">
<Link
to="/discover"
className="absolute inset-0 mt-[-3.75rem] flex h-full flex-1 cursor-default flex-col items-center justify-center gap-2"
className="absolute inset-0 mt-[-3.75rem] flex h-full flex-1 cursor-menu flex-col items-center justify-center gap-2"
onClick={stopPropagation}
>
<i className="i-mgc-add-cute-re text-3xl" />
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/profile/user-profile-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ const SubscriptionItem: FC<{
data-feed-id={subscription.feedId}
>
<a
className="flex flex-1 cursor-default items-center"
className="flex flex-1 cursor-menu items-center"
href={subscription.feeds.siteUrl!}
target="_blank"
>
Expand Down
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/settings/control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const SettingSwitch: Component<{
return (
<div className={cn("mb-3 flex items-center justify-between gap-4", className)}>
<Label htmlFor={id}>{label}</Label>
<Switch id={id} checked={checked} onCheckedChange={onCheckedChange} className="cursor-auto" />
<Switch id={id} checked={checked} onCheckedChange={onCheckedChange} />
</div>
)
}
Expand Down
4 changes: 4 additions & 0 deletions apps/renderer/src/modules/settings/tabs/apperance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export const SettingAppearance = () => {
label: t("appearance.reduce_motion.label"),
description: t("appearance.reduce_motion.description"),
}),
defineItem("usePointerCursor", {
label: t("appearance.use_pointer_cursor.label"),
description: t("appearance.use_pointer_cursor.description"),
}),
]}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const UserRenderer = ({
onClick={() => {
if (user?.id) presentUserModal(user.id)
}}
className={cn("flex items-center", user?.id ? "cursor-pointer" : "cursor-default")}
className="flex cursor-button items-center"
>
{name === APP_NAME ? (
<Logo className="aspect-square size-4" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function Component() {
{subscriptions.data?.[category].map((subscription) => (
<div key={subscription.feedId} className="group relative border-b py-5">
<a
className="flex flex-1 cursor-default"
className="flex flex-1 cursor-button"
href={`/feed/${subscription.feedId}`}
target="_blank"
>
Expand Down
Loading

0 comments on commit b6ff6fb

Please sign in to comment.