diff options
Diffstat (limited to 'llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte')
| -rw-r--r-- | llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte new file mode 100644 index 0000000..2ce0305 --- /dev/null +++ b/llama.cpp/tools/server/webui/src/lib/components/ui/sidebar/sidebar-menu-button.svelte | |||
| @@ -0,0 +1,106 @@ | |||
| 1 | <script lang="ts" module> | ||
| 2 | import { tv, type VariantProps } from 'tailwind-variants'; | ||
| 3 | |||
| 4 | export const sidebarMenuButtonVariants = tv({ | ||
| 5 | base: 'peer/menu-button outline-hidden ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground group-has-data-[sidebar=menu-action]/menu-item:pr-8 data-[active=true]:bg-sidebar-accent 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! flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', | ||
| 6 | variants: { | ||
| 7 | variant: { | ||
| 8 | default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground', | ||
| 9 | outline: | ||
| 10 | 'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_var(--sidebar-border)] hover:shadow-[0_0_0_1px_var(--sidebar-accent)]' | ||
| 11 | }, | ||
| 12 | size: { | ||
| 13 | default: 'h-8 text-sm', | ||
| 14 | sm: 'h-7 text-xs', | ||
| 15 | lg: 'group-data-[collapsible=icon]:p-0! h-12 text-sm' | ||
| 16 | } | ||
| 17 | }, | ||
| 18 | defaultVariants: { | ||
| 19 | variant: 'default', | ||
| 20 | size: 'default' | ||
| 21 | } | ||
| 22 | }); | ||
| 23 | |||
| 24 | export type SidebarMenuButtonVariant = VariantProps<typeof sidebarMenuButtonVariants>['variant']; | ||
| 25 | export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>['size']; | ||
| 26 | </script> | ||
| 27 | |||
| 28 | <script lang="ts"> | ||
| 29 | import * as Tooltip from '$lib/components/ui/tooltip/index.js'; | ||
| 30 | import { | ||
| 31 | cn, | ||
| 32 | type WithElementRef, | ||
| 33 | type WithoutChildrenOrChild | ||
| 34 | } from '$lib/components/ui/utils.js'; | ||
| 35 | import { mergeProps } from 'bits-ui'; | ||
| 36 | import type { ComponentProps, Snippet } from 'svelte'; | ||
| 37 | import type { HTMLAttributes } from 'svelte/elements'; | ||
| 38 | import { useSidebar } from './context.svelte.js'; | ||
| 39 | |||
| 40 | let { | ||
| 41 | ref = $bindable(null), | ||
| 42 | class: className, | ||
| 43 | children, | ||
| 44 | child, | ||
| 45 | variant = 'default', | ||
| 46 | size = 'default', | ||
| 47 | isActive = false, | ||
| 48 | tooltipContent, | ||
| 49 | tooltipContentProps, | ||
| 50 | ...restProps | ||
| 51 | }: WithElementRef<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & { | ||
| 52 | isActive?: boolean; | ||
| 53 | variant?: SidebarMenuButtonVariant; | ||
| 54 | size?: SidebarMenuButtonSize; | ||
| 55 | tooltipContent?: Snippet | string; | ||
| 56 | tooltipContentProps?: WithoutChildrenOrChild<ComponentProps<typeof Tooltip.Content>>; | ||
| 57 | child?: Snippet<[{ props: Record<string, unknown> }]>; | ||
| 58 | } = $props(); | ||
| 59 | |||
| 60 | const sidebar = useSidebar(); | ||
| 61 | |||
| 62 | const buttonProps = $derived({ | ||
| 63 | class: cn(sidebarMenuButtonVariants({ variant, size }), className), | ||
| 64 | 'data-slot': 'sidebar-menu-button', | ||
| 65 | 'data-sidebar': 'menu-button', | ||
| 66 | 'data-size': size, | ||
| 67 | 'data-active': isActive, | ||
| 68 | ...restProps | ||
| 69 | }); | ||
| 70 | </script> | ||
| 71 | |||
| 72 | {#snippet Button({ props }: { props?: Record<string, unknown> })} | ||
| 73 | {@const mergedProps = mergeProps(buttonProps, props)} | ||
| 74 | {#if child} | ||
| 75 | {@render child({ props: mergedProps })} | ||
| 76 | {:else} | ||
| 77 | <button bind:this={ref} {...mergedProps}> | ||
| 78 | {@render children?.()} | ||
| 79 | </button> | ||
| 80 | {/if} | ||
| 81 | {/snippet} | ||
| 82 | |||
| 83 | {#if !tooltipContent} | ||
| 84 | {@render Button({})} | ||
| 85 | {:else} | ||
| 86 | <Tooltip.Root> | ||
| 87 | <Tooltip.Trigger> | ||
| 88 | {#snippet child({ props })} | ||
| 89 | {@render Button({ props })} | ||
| 90 | {/snippet} | ||
| 91 | </Tooltip.Trigger> | ||
| 92 | |||
| 93 | <Tooltip.Content | ||
| 94 | side="right" | ||
| 95 | align="center" | ||
| 96 | hidden={sidebar.state !== 'collapsed' || sidebar.isMobile} | ||
| 97 | {...tooltipContentProps} | ||
| 98 | > | ||
| 99 | {#if typeof tooltipContent === 'string'} | ||
| 100 | {tooltipContent} | ||
| 101 | {:else if tooltipContent} | ||
| 102 | {@render tooltipContent()} | ||
| 103 | {/if} | ||
| 104 | </Tooltip.Content> | ||
| 105 | </Tooltip.Root> | ||
| 106 | {/if} | ||
