mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 00:01:55 +00:00
147 lines
3.8 KiB
Svelte
147 lines
3.8 KiB
Svelte
<script lang="ts">
|
|
import { twMerge } from 'tailwind-merge'
|
|
import Popover from '../Popover.svelte'
|
|
import { createEventDispatcher } from 'svelte'
|
|
import SideBarNotification from './SideBarNotification.svelte'
|
|
import { conditionalMelt } from '$lib/utils'
|
|
import type { MenubarMenuElements } from '@melt-ui/svelte'
|
|
import { triggerableByAI } from '$lib/actions/triggerableByAI.svelte'
|
|
|
|
interface Props {
|
|
aiId?: string | undefined
|
|
aiDescription?: string | undefined
|
|
label?: string | undefined
|
|
icon?: any | undefined
|
|
iconClasses?: string | null
|
|
iconProps?: any | null
|
|
isCollapsed: boolean
|
|
disabled?: boolean
|
|
lightMode?: boolean
|
|
stopPropagationOnClick?: boolean
|
|
shortcut?: string
|
|
notificationsCount?: number
|
|
color?: string | null
|
|
trigger?: MenubarMenuElements['trigger'] | undefined
|
|
href?: string | undefined
|
|
class?: string | undefined
|
|
}
|
|
|
|
let {
|
|
aiId = undefined,
|
|
aiDescription = undefined,
|
|
label = undefined,
|
|
icon = undefined,
|
|
iconClasses = null,
|
|
iconProps = null,
|
|
isCollapsed,
|
|
disabled = false,
|
|
lightMode = false,
|
|
stopPropagationOnClick = false,
|
|
shortcut = '',
|
|
notificationsCount = 0,
|
|
color = null,
|
|
trigger = undefined,
|
|
href = undefined,
|
|
class: classNames = undefined
|
|
}: Props = $props()
|
|
|
|
let buttonRef: HTMLButtonElement | HTMLAnchorElement | undefined = $state(undefined)
|
|
|
|
let dispatch = createEventDispatcher()
|
|
|
|
// Dynamic component based on whether href is provided
|
|
const Element = href ? 'a' : 'button'
|
|
</script>
|
|
|
|
{#if !disabled}
|
|
<Popover
|
|
appearTimeout={0}
|
|
disappearTimeout={0}
|
|
class="w-full"
|
|
disablePopup={!isCollapsed}
|
|
placement="right"
|
|
>
|
|
<svelte:element
|
|
this={Element}
|
|
bind:this={buttonRef}
|
|
use:triggerableByAI={{
|
|
id: aiId,
|
|
description: aiDescription,
|
|
callback: () => {
|
|
if (buttonRef) {
|
|
buttonRef.click()
|
|
}
|
|
}
|
|
}}
|
|
onclick={href
|
|
? undefined
|
|
: (e) => {
|
|
if (stopPropagationOnClick) e.preventDefault()
|
|
dispatch('click')
|
|
}}
|
|
{href}
|
|
class={twMerge(
|
|
'group flex items-center px-2 py-2 font-light rounded-md h-8 gap-3 w-full',
|
|
lightMode
|
|
? 'text-primary data-[highlighted]:bg-surface-hover hover:bg-surface-hover'
|
|
: 'data-[highlighted]:bg-[#2A3648] hover:bg-[#2A3648] text-primary-inverse dark:text-primary',
|
|
color ? 'border-4' : '',
|
|
'transition-all relative',
|
|
classNames
|
|
)}
|
|
style={color ? `border-color: ${color}; padding: 0 calc(0.5rem - 4px);` : ''}
|
|
use:conditionalMelt={trigger}
|
|
title={isCollapsed ? undefined : label}
|
|
{...$trigger}
|
|
>
|
|
{#if icon}
|
|
{@const SvelteComponent = icon}
|
|
<SvelteComponent
|
|
size={16}
|
|
class={twMerge(
|
|
'flex-shrink-0',
|
|
lightMode
|
|
? 'text-primary group-hover:text-secondary'
|
|
: 'text-primary-inverse group-hover:text-secondary-inverse dark:group-hover:text-secondary dark:text-primary',
|
|
'transition-all',
|
|
iconClasses
|
|
)}
|
|
{...iconProps}
|
|
/>
|
|
{/if}
|
|
|
|
{#if !isCollapsed && label}
|
|
<span
|
|
class={twMerge(
|
|
'whitespace-pre truncate',
|
|
lightMode ? 'text-primary' : 'text-primary-inverse dark:text-primary',
|
|
'transition-all',
|
|
classNames
|
|
)}
|
|
>
|
|
{label}
|
|
<span class="pl-2 text-xs dark:text-secondary light:text-secondary-inverse font-semibold">
|
|
{shortcut}
|
|
</span>
|
|
</span>
|
|
{/if}
|
|
|
|
{#if isCollapsed && notificationsCount > 0}
|
|
<div class="absolute translate-x-1/2 translate-y-1/2 -top-2 right-1 flex h-fit w-fit">
|
|
<SideBarNotification notificationCount={notificationsCount} small={true} />
|
|
</div>
|
|
{:else if notificationsCount > 0}
|
|
<div class="ml-auto">
|
|
<SideBarNotification notificationCount={notificationsCount} small={false} />
|
|
</div>
|
|
{/if}
|
|
</svelte:element>
|
|
|
|
{#snippet text()}
|
|
{#if label}
|
|
{label}
|
|
{/if}
|
|
{/snippet}
|
|
</Popover>
|
|
{/if}
|