| author | |
| committer | |
| log | 3fce14bbcfca2329819e7e33f0960ac796a5942f |
| tree | f6a828c6e2ff9365247e95d2d6e81429d5c36bec |
| parent | d430a0624b570561a4d8eedc7c277fb6c31c46e1 |
| signature | Signed by PGP key B5690EEEBB952194 |
4 files changed, 58 insertions(+), 5 deletions(-)
apps/web/public/mockServiceWorker.js+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | * - Please do NOT modify this file. |
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | const PACKAGE_VERSION = '2.12.9' | |
| 10 | const PACKAGE_VERSION = '2.12.10' | |
| 11 | 11 | const INTEGRITY_CHECKSUM = '4db4a41e972cec1b64cc569c66952d82' |
| 12 | 12 | const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') |
| 13 | 13 | const activeClientIds = new Set() |
apps/web/src/components/Sidebar.logic.ts+1-1| ... | ... | @@ -51,7 +51,7 @@ export function resolveThreadRowClassName(input: { |
| 51 | 51 | isSelected: boolean; |
| 52 | 52 | }): string { |
| 53 | 53 | const baseClassName = |
| 54 | "h-7 w-full translate-x-0 cursor-default justify-start px-2 text-left select-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring"; | |
| 54 | "h-7 w-full translate-x-0 cursor-pointer justify-start px-2 text-left select-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring"; | |
| 55 | 55 | |
| 56 | 56 | if (input.isSelected && input.isActive) { |
| 57 | 57 | return cn( |
apps/web/src/components/ui/sidebar.test.tsx created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | import { renderToStaticMarkup } from "react-dom/server"; | |
| 2 | import { describe, expect, it } from "vitest"; | |
| 3 | ||
| 4 | import { | |
| 5 | SidebarMenuAction, | |
| 6 | SidebarMenuButton, | |
| 7 | SidebarMenuSubButton, | |
| 8 | SidebarProvider, | |
| 9 | } from "./sidebar"; | |
| 10 | ||
| 11 | function renderSidebarButton(className?: string) { | |
| 12 | return renderToStaticMarkup( | |
| 13 | <SidebarProvider> | |
| 14 | <SidebarMenuButton className={className}>Projects</SidebarMenuButton> | |
| 15 | </SidebarProvider>, | |
| 16 | ); | |
| 17 | } | |
| 18 | ||
| 19 | describe("sidebar interactive cursors", () => { | |
| 20 | it("uses a pointer cursor for menu buttons by default", () => { | |
| 21 | const html = renderSidebarButton(); | |
| 22 | ||
| 23 | expect(html).toContain('data-slot="sidebar-menu-button"'); | |
| 24 | expect(html).toContain("cursor-pointer"); | |
| 25 | }); | |
| 26 | ||
| 27 | it("lets project drag handles override the default pointer cursor", () => { | |
| 28 | const html = renderSidebarButton("cursor-grab"); | |
| 29 | ||
| 30 | expect(html).toContain("cursor-grab"); | |
| 31 | expect(html).not.toContain("cursor-pointer"); | |
| 32 | }); | |
| 33 | ||
| 34 | it("uses a pointer cursor for menu actions", () => { | |
| 35 | const html = renderToStaticMarkup( | |
| 36 | <SidebarMenuAction aria-label="Create thread"> | |
| 37 | <span>+</span> | |
| 38 | </SidebarMenuAction>, | |
| 39 | ); | |
| 40 | ||
| 41 | expect(html).toContain('data-slot="sidebar-menu-action"'); | |
| 42 | expect(html).toContain("cursor-pointer"); | |
| 43 | }); | |
| 44 | ||
| 45 | it("uses a pointer cursor for submenu buttons", () => { | |
| 46 | const html = renderToStaticMarkup( | |
| 47 | <SidebarMenuSubButton render={<button type="button" />}>Show more</SidebarMenuSubButton>, | |
| 48 | ); | |
| 49 | ||
| 50 | expect(html).toContain('data-slot="sidebar-menu-sub-button"'); | |
| 51 | expect(html).toContain("cursor-pointer"); | |
| 52 | }); | |
| 53 | }); |
apps/web/src/components/ui/sidebar.tsx+3-3| ... | ... | @@ -750,7 +750,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) { |
| 750 | 750 | } |
| 751 | 751 | |
| 752 | 752 | const sidebarMenuButtonVariants = cva( |
| 753 | "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-lg p-2 text-left text-sm outline-hidden ring-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pe-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0", | |
| 753 | "peer/menu-button flex w-full cursor-pointer items-center gap-2 overflow-hidden rounded-lg p-2 text-left text-sm outline-hidden ring-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pe-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0", | |
| 754 | 754 | { |
| 755 | 755 | defaultVariants: { |
| 756 | 756 | size: "default", |
| ... | ... | @@ -834,7 +834,7 @@ function SidebarMenuAction({ |
| 834 | 834 | }) { |
| 835 | 835 | const defaultProps = { |
| 836 | 836 | className: cn( |
| 837 | "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-lg p-0 text-sidebar-foreground outline-hidden ring-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0", | |
| 837 | "absolute top-1.5 right-1 flex aspect-square w-5 cursor-pointer items-center justify-center rounded-lg p-0 text-sidebar-foreground outline-hidden ring-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0", | |
| 838 | 838 | // Increases the hit area of the button on mobile. |
| 839 | 839 | "after:-inset-2 after:absolute md:after:hidden", |
| 840 | 840 | "peer-data-[size=sm]/menu-button:top-1", |
| ... | ... | @@ -946,7 +946,7 @@ function SidebarMenuSubButton({ |
| 946 | 946 | }) { |
| 947 | 947 | const defaultProps = { |
| 948 | 948 | className: cn( |
| 949 | "-translate-x-px flex h-7 min-w-0 items-center gap-2 overflow-hidden rounded-lg px-2 text-sidebar-foreground outline-hidden ring-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", | |
| 949 | "-translate-x-px flex h-7 min-w-0 cursor-pointer items-center gap-2 overflow-hidden rounded-lg px-2 text-sidebar-foreground outline-hidden ring-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg:not([class*='size-'])]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", | |
| 950 | 950 | "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", |
| 951 | 951 | size === "sm" && "text-xs", |
| 952 | 952 | size === "md" && "text-sm", |