feat(frontend): Button rework (#3216)
* feat(frontend): wip * feat(frontend): wip * feat(frontend): wip * fix(frontend): improve buttons * fix(frontend): improve buttons wip * fix(frontend): wip * fix(frontend): rework done * feat(frontend): Fix grey buttons
This commit is contained in:
@@ -29,8 +29,9 @@
|
||||
on:click={() => copyToClipboard(JSON.stringify(jsonViewerContent, null, 4))}
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{ icon: ClipboardCopy }}
|
||||
>
|
||||
<div class="flex gap-2 items-center">Copy <ClipboardCopy /> </div>
|
||||
Copy
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{#if isString(jsonViewerContent)}
|
||||
|
||||
@@ -533,16 +533,26 @@
|
||||
<Drawer bind:this={jsonViewer} size="900px">
|
||||
<DrawerContent title="Expanded Result" on:close={jsonViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
<a
|
||||
class="text-sm text-secondary mr-2 inline-flex gap-2 items-center py-2 px-2 hover:bg-gray-100 rounded-lg"
|
||||
<Button
|
||||
download="{filename ?? 'result'}.json"
|
||||
href={workspaceId && jobId
|
||||
? `/api/w/${workspaceId}/jobs_u/completed/get_result/${jobId}`
|
||||
: `data:text/json;charset=utf-8,${encodeURIComponent(toJsonStr(result))}`}
|
||||
>Download <Download size={14} /></a
|
||||
startIcon={{ icon: Download }}
|
||||
color="light"
|
||||
size="xs"
|
||||
>
|
||||
<Button on:click={() => copyToClipboard(toJsonStr(result))} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Copy to clipboard <ClipboardCopy /> </div>
|
||||
Download
|
||||
</Button>
|
||||
<Button
|
||||
on:click={() => copyToClipboard(toJsonStr(result))}
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{
|
||||
icon: ClipboardCopy
|
||||
}}
|
||||
>
|
||||
Copy to clipboard
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{#if largeObject}
|
||||
|
||||
@@ -56,13 +56,15 @@
|
||||
|
||||
<div class="relative overflow-x-auto">
|
||||
<Button
|
||||
class="absolute top-2 right-2"
|
||||
wrapperClasses="absolute top-2 right-2"
|
||||
on:click={() => copyToClipboard(code)}
|
||||
color="light"
|
||||
size="xs"
|
||||
>
|
||||
<ClipboardCopy size={12} />
|
||||
</Button>
|
||||
size="xs2"
|
||||
startIcon={{
|
||||
icon: ClipboardCopy
|
||||
}}
|
||||
iconOnly
|
||||
/>
|
||||
{#if code?.length < 5000}
|
||||
{#if !lines}
|
||||
<Highlight class="nowrap {$$props.class}" language={lang} {code} />
|
||||
|
||||
@@ -93,17 +93,30 @@ ${Object.entries(args)
|
||||
<Drawer bind:this={jsonViewer} size="900px">
|
||||
<DrawerContent title="Expanded Args" on:close={jsonViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
<a
|
||||
class="text-sm text-secondary mr-2 inline-flex gap-2 items-center py-2 px-2 hover:bg-surface-hover rounded-lg"
|
||||
<Button
|
||||
download="windmill-args.json"
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(jsonStr)}"
|
||||
>Download <Download size={14} /></a
|
||||
startIcon={{ icon: Download }}
|
||||
size="xs"
|
||||
color="light"
|
||||
>
|
||||
<Button on:click={runLocally.openDrawer} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Use in a local script<ChevronRightSquare /> </div>
|
||||
Download
|
||||
</Button>
|
||||
<Button on:click={() => copyToClipboard(jsonStr)} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Copy to clipboard <ClipboardCopy /> </div>
|
||||
<Button
|
||||
on:click={runLocally.openDrawer}
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{ icon: ChevronRightSquare }}
|
||||
>
|
||||
Use in a local script
|
||||
</Button>
|
||||
<Button
|
||||
on:click={() => copyToClipboard(jsonStr)}
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{ icon: ClipboardCopy }}
|
||||
>
|
||||
Copy to clipboard
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{#if jsonStr.length > 100000}
|
||||
|
||||
@@ -52,17 +52,32 @@
|
||||
<Drawer bind:this={logViewer} size="900px">
|
||||
<DrawerContent title="Expanded Logs" on:close={logViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
<a
|
||||
class="text-sm text-secondary mr-2 inline-flex gap-2 items-center py-2 px-2 hover:bg-surface-hover rounded-lg"
|
||||
<Button
|
||||
href="/api/w/{$workspaceStore}/jobs_u/get_logs/{jobId}"
|
||||
download="windmill-logs.json"
|
||||
href="/api/w/{$workspaceStore}/jobs_u/get_logs/{jobId}">Download <Download size={14} /></a
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{
|
||||
icon: Download
|
||||
}}
|
||||
>
|
||||
<Button on:click={() => copyToClipboard(content)} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Copy to clipboard <ClipboardCopy /> </div>
|
||||
Downlaod
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
on:click={() => copyToClipboard(content)}
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{
|
||||
icon: ClipboardCopy
|
||||
}}
|
||||
>
|
||||
Copy to clipboard
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
<div>
|
||||
<pre class="bg-surface-secondary text-secondary text-xs w-full p-2"
|
||||
<pre
|
||||
class="bg-surface-secondary text-secondary text-xs w-full p-2 whitespace-pre-wrap border rounded-md"
|
||||
>{#if content}{#if content?.length > LOG_LIMIT}(truncated to the last {LOG_LIMIT} characters)... <button
|
||||
on:click={() => {
|
||||
scroll = false
|
||||
|
||||
@@ -20,8 +20,11 @@
|
||||
{/if}
|
||||
<Popover
|
||||
style="width: {(len / total) * 100}%"
|
||||
class="h-4 {gray ? 'bg-gray-500' : running ? 'bg-blue-400/90' : 'bg-blue-500/90'} {position ==
|
||||
'left'
|
||||
class="h-4 {gray
|
||||
? 'bg-gray-300 dark:bg-gray-600'
|
||||
: running
|
||||
? 'bg-blue-400/90'
|
||||
: 'bg-blue-500/90'} {position == 'left'
|
||||
? 'rounded-l-sm'
|
||||
: position == 'right'
|
||||
? 'rounded-r-sm'
|
||||
|
||||
@@ -220,19 +220,17 @@
|
||||
on:click={handleClick}
|
||||
size={resolvedConfig.size}
|
||||
color={resolvedConfig.color}
|
||||
startIcon={{
|
||||
icon: resolvedConfig.beforeIcon ? beforeIconComponent : undefined
|
||||
}}
|
||||
endIcon={{
|
||||
icon: resolvedConfig.afterIcon ? afterIconComponent : undefined
|
||||
}}
|
||||
{loading}
|
||||
>
|
||||
<span class="truncate inline-flex gap-2 items-center">
|
||||
{#if resolvedConfig.beforeIcon && beforeIconComponent}
|
||||
<svelte:component this={beforeIconComponent} size={14} />
|
||||
{/if}
|
||||
{#if resolvedConfig.label?.toString() && resolvedConfig.label?.toString()?.length > 0}
|
||||
<div>{resolvedConfig.label.toString()}</div>
|
||||
{/if}
|
||||
{#if resolvedConfig.afterIcon && afterIconComponent}
|
||||
<svelte:component this={afterIconComponent} size={14} />
|
||||
{/if}
|
||||
</span>
|
||||
{#if resolvedConfig.label?.toString() && resolvedConfig.label?.toString()?.length > 0}
|
||||
<div>{resolvedConfig.label.toString()}</div>
|
||||
{/if}
|
||||
</Button>
|
||||
{/key}
|
||||
</AlignWrapper>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<button
|
||||
on:pointerdown|preventDefault|stopPropagation
|
||||
on:click|preventDefault|stopPropagation={refresh}
|
||||
class="center-center p-1 rounded border bg-surface/60 hover:bg-gray-200 z-10"
|
||||
class="center-center p-1 rounded border bg-surface/60 hover:bg-surface-hover z-10"
|
||||
>
|
||||
<RefreshCw class={loading ? 'animate-spin' : ''} size={16} />
|
||||
</button>
|
||||
|
||||
@@ -573,7 +573,7 @@
|
||||
style={$appStore.css?.['app']?.['viewer']?.style}
|
||||
>
|
||||
<div class="absolute bottom-2 left-2 z-50 border bg-surface">
|
||||
<div class="flex flex-row gap-2 text-xs items-center p-0.5">
|
||||
<div class="flex flex-row gap-2 text-xs items-center h-8 px-1">
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
@@ -584,7 +584,9 @@
|
||||
>
|
||||
<Minus size={14} />
|
||||
</Button>
|
||||
{$scale}%
|
||||
<div class="w-8 flex justify-center text-2xs h-full items-center">
|
||||
{$scale}%
|
||||
</div>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
|
||||
@@ -109,14 +109,14 @@
|
||||
<div class="divide-y">
|
||||
<div class="flex flex-row-reverse mb-2 items-center text-sm text-secondary px-2">
|
||||
<div class="flex gap-4 items-center">
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="flex gap-2 items-center text-xs">
|
||||
<div>Waiting for executor</div>
|
||||
<div class="h-4 w-4 bg-gray-500" />
|
||||
<div class="h-4 w-4 bg-gray-300 dark:bg-gray-600 rounded" />
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="flex gap-2 items-center text-xs">
|
||||
<div>Execution</div>
|
||||
<div class="h-4 w-4 bg-blue-500/90" />
|
||||
<div class="h-4 w-4 bg-blue-500/90 rounded" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-tertiary text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
'!text-tertiary text-left px-4 py-2 gap-2 cursor-pointer hover:bg-surface-hover !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{#if index === 0}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-tertiary text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
'!text-tertiary text-left px-4 py-2 gap-2 cursor-pointer hover:bg-surface-hover !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{#if index === tabs.length - 1}
|
||||
@@ -75,7 +75,7 @@
|
||||
>
|
||||
<div
|
||||
class={classNames(
|
||||
'!text-red-600 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-gray-100 !text-xs font-semibold'
|
||||
'!text-red-600 dark:!text-red-400 text-left px-4 py-2 gap-2 cursor-pointer hover:bg-surface-hover !text-xs font-semibold'
|
||||
)}
|
||||
>
|
||||
{`Reset debug mode`}
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
: 'bg-surface text-primay hover:bg-hover'}
|
||||
color="light"
|
||||
variant="border"
|
||||
size="xs">Cache</Button
|
||||
size="xs2"
|
||||
>
|
||||
Cache
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
<div class="block text-primary">
|
||||
<Toggle
|
||||
|
||||
@@ -209,32 +209,32 @@
|
||||
|
||||
<Button
|
||||
title="Delete"
|
||||
size="xs"
|
||||
size="xs2"
|
||||
color="red"
|
||||
variant="border"
|
||||
btnClasses="!px-2"
|
||||
aria-label="Delete"
|
||||
on:click={() => dispatch('delete')}
|
||||
endIcon={{ icon: Trash2 }}
|
||||
iconOnly
|
||||
/>
|
||||
{#if inlineScript.language != 'frontend'}
|
||||
<Button
|
||||
size="xs"
|
||||
size="xs2"
|
||||
color="light"
|
||||
title="Full Editor"
|
||||
btnClasses="!px-2 !bg-surface-secondary hover:!bg-surface-hover"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
inlineScriptEditorDrawer?.openDrawer()
|
||||
}}
|
||||
endIcon={{ icon: Maximize2 }}
|
||||
iconOnly
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<Button
|
||||
variant="border"
|
||||
size="xs"
|
||||
size="xs2"
|
||||
color="light"
|
||||
btnClasses="!px-2 !py-1"
|
||||
on:click={async () => {
|
||||
editor?.format()
|
||||
simpleEditor?.format()
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
</div>
|
||||
{#if subFieldType !== 'db-explorer'}
|
||||
<button
|
||||
class="z-10 rounded-full p-1 duration-200 hover:bg-gray-200"
|
||||
class="z-10 rounded-full p-1 duration-200 hover:bg-surface-hover"
|
||||
aria-label="Remove item"
|
||||
on:click|preventDefault|stopPropagation={() => deleteElementByType(index)}
|
||||
>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</script>
|
||||
|
||||
<div class={'border-y divide-y '}>
|
||||
<ScriptSettingHeader name={runnable.name} />
|
||||
<ScriptSettingHeader name={runnable.name} noBorder />
|
||||
<div class="p-2">
|
||||
<ScriptTransformer bind:appInput={runnable} {id} />
|
||||
{#if runnable.type == 'runnableByPath' || runnable.inlineScript}
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex flex-row items-center gap-2 text-xs"> Hide Refresh Button </div>
|
||||
|
||||
<Toggle bind:checked={appInput.hideRefreshButton} size="xs" />
|
||||
<Toggle bind:checked={appInput.hideRefreshButton} size="xs" class="my-2" />
|
||||
</div>
|
||||
{/if}
|
||||
{#if hasScript}
|
||||
|
||||
@@ -2,12 +2,19 @@
|
||||
import { FunctionSquare } from 'lucide-svelte'
|
||||
import type { ActionType } from '../ComponentScriptSettings.svelte'
|
||||
import ScriptSettingsActions from './ScriptSettingsActions.svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export let name: string
|
||||
export let actions: ActionType[] = []
|
||||
export let noBorder: boolean = false
|
||||
</script>
|
||||
|
||||
<div class="flex flex-row px-2 py-1 justify-between bg-surface-secondary border rounded">
|
||||
<div
|
||||
class={twMerge(
|
||||
'flex flex-row px-2 py-1 justify-between bg-surface-secondary ',
|
||||
noBorder ? '' : 'border rounded'
|
||||
)}
|
||||
>
|
||||
<div class="flex flex-row gap-2 items-center min-w-0">
|
||||
<FunctionSquare size={16} color="#3b82f6" />
|
||||
<span class="text-xs font-semibold truncate">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { ButtonType } from './model'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import ButtonDropdown from './ButtonDropdown.svelte'
|
||||
import { MenuItem } from '@rgossiaux/svelte-headlessui'
|
||||
import { classNames } from '$lib/utils'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
|
||||
export let size: ButtonType.Size = 'md'
|
||||
export let spacingSize: ButtonType.Size = size
|
||||
@@ -64,42 +64,42 @@
|
||||
|
||||
blue: {
|
||||
border:
|
||||
'border-frost-500 dark:border-frost-300 hover:border-frost-700 dark:hover:border-frost-400 focus:border-frost-700 bg-surface hover:bg-frost-100 dark:hover:bg-frost-900 focus:bg-frost-100 focus:dark:text-frost-100 dark:focus:bg-frost-900 text-frost-500 dark:text-frost-300 dark:hover:text-frost-400 hover:text-frost-700 focus:text-frost-700 focus:ring-frost-300',
|
||||
'border-frost-500 dark:border-frost-300 hover:border-frost-700 dark:hover:border-frost-400 focus-visible:border-frost-700 bg-surface hover:bg-frost-100 dark:hover:bg-frost-900 focus-visible:bg-frost-100 focus-visible:dark:text-frost-100 dark:focus-visible:bg-frost-900 text-frost-500 dark:text-frost-300 dark:hover:text-frost-400 hover:text-frost-700 focus-visible:text-frost-700 focus-visible:ring-frost-300',
|
||||
contained:
|
||||
'bg-frost-500 hover:bg-frost-700 focus:bg-frost-700 text-white focus:ring-frost-300',
|
||||
'bg-frost-500 hover:bg-frost-700 focus-visible:bg-frost-700 text-white focus-visible:ring-frost-300',
|
||||
divider: 'divide-x divide-frost-600'
|
||||
},
|
||||
red: {
|
||||
border:
|
||||
'border-red-600/60 hover:border-red-600 bg-surface hover:bg-red-100 text-red-600 hover:text-red-700 focus:ring-red-300',
|
||||
contained: 'bg-red-600 hover:bg-red-600 text-white focus:ring-red-300',
|
||||
'border-red-600/60 hover:border-red-600 bg-surface hover:bg-red-100 text-red-600 hover:text-red-700 focus-visible:ring-red-300 ',
|
||||
contained: 'bg-red-600 hover:bg-red-600 text-white focus-visible:ring-red-300',
|
||||
divider: 'divide-x divide-red-700'
|
||||
},
|
||||
green: {
|
||||
border:
|
||||
'border-green-600 hover:border-green-700 bg-surface hover:bg-green-100 text-green-600 hover:text-green-700 focus:ring-green-300',
|
||||
contained: 'bg-green-600 hover:bg-green-700 text-white focus:ring-green-300',
|
||||
'border-green-600 hover:border-green-700 bg-surface hover:bg-green-100 text-green-600 hover:text-green-700 focus-visible:ring-green-300',
|
||||
contained: 'bg-green-600 hover:bg-green-700 text-white focus-visible:ring-green-300',
|
||||
divider: 'divide-x divide-green-700'
|
||||
},
|
||||
dark: {
|
||||
border:
|
||||
'border-surface-inverse bg-surface hover:bg-surface-hover focus:bg-surface-hover text-primary hover:text-secondary focus:text-secondary focus:ring-surface-selected-inverse',
|
||||
'border-surface-inverse bg-surface hover:bg-surface-hover focus-visible:bg-surface-hover text-primary hover:text-secondary focus-visible:text-secondary focus-visible:ring-surface-selected-inverse',
|
||||
contained:
|
||||
'bg-surface-inverse hover:bg-surface-inverse-hover focus:bg-surface-hover-inverse text-primary-inverse focus:ring-surface-selected-inverse',
|
||||
'bg-surface-inverse hover:bg-surface-inverse-hover focus-visible:bg-surface-hover-inverse text-primary-inverse focus-visible:ring-surface-selected-inverse',
|
||||
divider: 'divide-x divide-gray-800 dark:divide-gray-200'
|
||||
},
|
||||
gray: {
|
||||
border:
|
||||
'border-gray-600 hover:border-gray-900 focus:border-gray-900 bg-surface hover:bg-gray-200 focus:bg-gray-200 text-gray-800 hover:text-primary focus:text-primary focus:ring-gray-300',
|
||||
'border-gray-500 dark:border-gray-300 hover:border-gray-700 dark:hover:border-gray-400 focus-visible:border-gray-700 bg-surface hover:bg-gray-100 dark:hover:bg-gray-900 focus-visible:bg-gray-100 focus-visible:dark:text-gray-100 dark:focus-visible:bg-gray-900 text-gray-500 dark:text-gray-300 dark:hover:text-gray-400 hover:text-gray-700 focus-visible:text-gray-700 focus-visible:ring-gray-300',
|
||||
contained:
|
||||
'bg-gray-700/90 hover:bg-gray-900/90 focus:bg-gray-900/90 text-white focus:ring-gray-300',
|
||||
divider: 'divide-x divide-gray-700 dark:divide-gray-200'
|
||||
'bg-gray-500 hover:bg-gray-700 focus-visible:bg-gray-700 text-white focus-visible:ring-gray-300',
|
||||
divider: 'divide-x divide-gray-600'
|
||||
},
|
||||
light: {
|
||||
border:
|
||||
'border bg-surface hover:bg-surface-hover focus:bg-surface-hover text-primary hover:text-secondary focus:text-secondary focus:ring-surface-selected',
|
||||
'border bg-surface hover:bg-surface-hover focus-visible:bg-surface-hover text-primary hover:text-secondary focus-visible:text-secondary focus-visible:ring-surface-selected',
|
||||
contained:
|
||||
'bg-surface border-transparent hover:bg-surface-hover focus:bg-surface-hover text-primary focus:ring-surface-selected',
|
||||
'bg-surface border-transparent hover:bg-surface-hover focus-visible:bg-surface-hover text-primary focus-visible:ring-surface-selected',
|
||||
divider: 'divide-x divide-gray-200 dark:divide-gray-700'
|
||||
}
|
||||
}
|
||||
@@ -129,18 +129,31 @@
|
||||
variant === 'border' ? 'border' : '',
|
||||
ButtonType.FontSizeClasses[size],
|
||||
ButtonType.SpacingClasses[spacingSize][variant],
|
||||
'focus:ring-2 font-semibold',
|
||||
'focus-visible:ring-2 font-semibold',
|
||||
dropdownItems ? 'rounded-l-md h-full' : 'rounded-md',
|
||||
'justify-center items-center text-center whitespace-nowrap inline-flex gap-2',
|
||||
btnClasses,
|
||||
'transition-all'
|
||||
'active:opacity-80 transition-all',
|
||||
disabled ? '!bg-surface-disabled !text-tertiary cursor-not-allowed' : '',
|
||||
loading ? 'cursor-wait' : ''
|
||||
)
|
||||
|
||||
const iconMap = {
|
||||
xs2: 14,
|
||||
xs: 14,
|
||||
sm: 16,
|
||||
md: 16,
|
||||
lg: 18
|
||||
lg: 18,
|
||||
xl: 18
|
||||
}
|
||||
|
||||
const iconOnlyPadding = {
|
||||
xs2: 'm-[1px]',
|
||||
xs: 'm-[1px]',
|
||||
sm: 'm-[2px]',
|
||||
md: 'm-[2px]',
|
||||
lg: 'm-[5px]',
|
||||
xl: 'm-[5px]'
|
||||
}
|
||||
|
||||
$: lucideIconSize = iconMap[size] ?? 12
|
||||
@@ -154,7 +167,6 @@
|
||||
>
|
||||
{#if href}
|
||||
<a
|
||||
data-sveltekit-preload-code="hover"
|
||||
bind:this={element}
|
||||
on:pointerdown
|
||||
on:focus
|
||||
@@ -168,10 +180,7 @@
|
||||
}}
|
||||
{href}
|
||||
{download}
|
||||
class={twMerge(
|
||||
buttonClass,
|
||||
disabled ? '!bg-surface-disabled !text-tertiary !cursor-not-allowed' : ''
|
||||
)}
|
||||
class={buttonClass}
|
||||
{id}
|
||||
{target}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
@@ -179,16 +188,24 @@
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin mr-1" size={14} />
|
||||
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
||||
{:else if startIcon?.icon}
|
||||
<svelte:component this={startIcon.icon} class={startIcon.classes} size={lucideIconSize} />
|
||||
<svelte:component
|
||||
this={startIcon.icon}
|
||||
class={twMerge(startIcon?.classes, iconOnlyPadding[size])}
|
||||
size={lucideIconSize}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon?.icon}
|
||||
<svelte:component this={endIcon.icon} class={endIcon.classes} size={lucideIconSize} />
|
||||
<svelte:component
|
||||
this={endIcon.icon}
|
||||
class={twMerge(endIcon?.classes, iconOnlyPadding[size])}
|
||||
size={lucideIconSize}
|
||||
/>
|
||||
{/if}
|
||||
</a>
|
||||
{:else}
|
||||
@@ -200,10 +217,7 @@
|
||||
on:blur
|
||||
on:mouseenter
|
||||
on:mouseleave
|
||||
class={twMerge(
|
||||
buttonClass,
|
||||
disabled ? '!bg-surface-disabled !text-tertiary border !cursor-not-allowed' : ''
|
||||
)}
|
||||
class={buttonClass}
|
||||
{id}
|
||||
tabindex={disabled ? -1 : 0}
|
||||
{title}
|
||||
@@ -212,23 +226,36 @@
|
||||
{style}
|
||||
>
|
||||
{#if loading}
|
||||
<Loader2 class={twMerge('animate-spin', !iconOnly ? 'mr-1' : '')} size={14} />
|
||||
<Loader2 class={twMerge('animate-spin', iconOnlyPadding[size])} size={lucideIconSize} />
|
||||
{:else if startIcon?.icon}
|
||||
<svelte:component this={startIcon.icon} class={startIcon.classes} size={lucideIconSize} />
|
||||
<svelte:component
|
||||
this={startIcon.icon}
|
||||
class={twMerge(startIcon?.classes, iconOnlyPadding[size])}
|
||||
size={lucideIconSize}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if !iconOnly}
|
||||
<slot />
|
||||
{/if}
|
||||
{#if endIcon?.icon}
|
||||
<svelte:component this={endIcon.icon} class={endIcon.classes} size={lucideIconSize} />
|
||||
<svelte:component
|
||||
this={endIcon.icon}
|
||||
class={twMerge(endIcon?.classes, iconOnlyPadding[size])}
|
||||
size={lucideIconSize}
|
||||
/>
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if dropdownItems && dropdownItems.length > 0}
|
||||
<div
|
||||
class={twMerge(buttonClass, 'rounded-r-md rounded-l-none m-0 p-0 h-auto !w-10 border-l-0')}
|
||||
class={twMerge(
|
||||
buttonClass,
|
||||
'rounded-md m-0 p-0 h-auto !w-10',
|
||||
variant === 'border' ? 'border-0 border-r border-y ' : 'border-0',
|
||||
'rounded-r-md !rounded-l-none'
|
||||
)}
|
||||
>
|
||||
<ButtonDropdown target={portalTarget}>
|
||||
<svelte:fragment slot="items">
|
||||
|
||||
@@ -2,7 +2,7 @@ export const BUTTON_COLORS = ['blue', 'red', 'dark', 'light', 'green', 'gray', '
|
||||
|
||||
export namespace ButtonType {
|
||||
export type Size = 'xs2' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||
export type Color = string;
|
||||
export type Color = string
|
||||
export type Variant = 'contained' | 'border' | 'divider'
|
||||
export type Target = '_self' | '_blank'
|
||||
export type Element = HTMLButtonElement | HTMLAnchorElement
|
||||
@@ -54,15 +54,6 @@ export namespace ButtonType {
|
||||
}
|
||||
} as const
|
||||
|
||||
export const IconScale: Record<ButtonType.Size, number> = {
|
||||
xs2: 0.6,
|
||||
xs: 0.7,
|
||||
sm: 0.8,
|
||||
md: 1,
|
||||
lg: 1.1,
|
||||
xl: 1.2
|
||||
} as const
|
||||
|
||||
export interface ItemProps {
|
||||
size: Size
|
||||
color: Color
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Menu, Transition, MenuButton, MenuItems } from '@rgossiaux/svelte-headlessui'
|
||||
import { MoreVertical } from 'lucide-svelte'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { createPopperActions, type PopperOptions } from 'svelte-popperjs'
|
||||
import Portal from 'svelte-portal'
|
||||
|
||||
export let hasPadding: boolean = true
|
||||
import Button from '../common/button/Button.svelte'
|
||||
|
||||
const [popperRef, popperContent] = createPopperActions({ placement: 'auto' })
|
||||
|
||||
@@ -26,10 +24,16 @@
|
||||
|
||||
<Menu let:open as="div" class="relative hover:z-50 flex w-full h-full">
|
||||
<span use:popperRef>
|
||||
<MenuButton
|
||||
class={twMerge('h-full w-full flex flex-row gap-2 items-center', hasPadding ? 'px-2' : '')}
|
||||
>
|
||||
<MoreVertical class="w-5 h-5" />
|
||||
<MenuButton>
|
||||
<Button
|
||||
nonCaptureEvent
|
||||
color="light"
|
||||
size="xs"
|
||||
startIcon={{
|
||||
icon: MoreVertical
|
||||
}}
|
||||
iconOnly
|
||||
/>
|
||||
</MenuButton>
|
||||
</span>
|
||||
|
||||
|
||||
@@ -291,7 +291,7 @@ done`
|
||||
copyToClipboard(curlCode())
|
||||
}}
|
||||
>
|
||||
<Highlight language={bash} code={curlCode()} class="" />
|
||||
<Highlight language={bash} code={curlCode()} />
|
||||
<Clipboard size={14} class="w-8 top-2 right-2 absolute" />
|
||||
</div>
|
||||
{/key}
|
||||
|
||||
@@ -381,10 +381,16 @@
|
||||
<Button
|
||||
on:click={() => contentSearch?.open()}
|
||||
variant="border"
|
||||
btnClasses="py-2.5"
|
||||
size="xs"
|
||||
color="light">Content <SearchCode size={16} /></Button
|
||||
size="sm"
|
||||
spacingSize="lg"
|
||||
wrapperClasses="h-10"
|
||||
color="light"
|
||||
endIcon={{
|
||||
icon: SearchCode
|
||||
}}
|
||||
>
|
||||
Content
|
||||
</Button>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<ListFilters
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
wrapperClasses="border rounded-md"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
const ts = computeMinMax()
|
||||
if (ts) {
|
||||
|
||||
@@ -305,13 +305,7 @@
|
||||
{#if job && 'deleted' in job && !job?.deleted && ($superadmin || ($userStore?.is_admin ?? false))}
|
||||
<ButtonDropdown target="body" hasPadding={false}>
|
||||
<svelte:fragment slot="buttonReplacement">
|
||||
<Button
|
||||
btnClasses="!py-2"
|
||||
nonCaptureEvent
|
||||
variant="border"
|
||||
size="sm"
|
||||
startIcon={{ icon: Trash }}
|
||||
/>
|
||||
<Button nonCaptureEvent variant="border" size="sm" startIcon={{ icon: Trash }} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="items">
|
||||
<MenuItem
|
||||
@@ -490,7 +484,7 @@
|
||||
goto(viewHref)
|
||||
}}
|
||||
color="blue"
|
||||
size="md"
|
||||
size="sm"
|
||||
startIcon={{ icon: RefreshCw }}>Run again</Button
|
||||
>
|
||||
{/if}
|
||||
@@ -503,7 +497,7 @@
|
||||
goto(`${stem}/edit/${job?.script_path}${isScript ? `` : `?nodraft=true`}`)
|
||||
}}
|
||||
color="blue"
|
||||
size="md"
|
||||
size="sm"
|
||||
startIcon={{ icon: Pen }}>Edit</Button
|
||||
>
|
||||
{/if}
|
||||
@@ -511,7 +505,7 @@
|
||||
<Button
|
||||
href={viewHref}
|
||||
color="blue"
|
||||
size="md"
|
||||
size="sm"
|
||||
startIcon={{
|
||||
icon:
|
||||
job?.job_kind === 'script' ? Code2 : job?.job_kind === 'flow' ? BarsStaggered : Scroll
|
||||
|
||||
@@ -634,7 +634,7 @@
|
||||
<HighlightCode
|
||||
language={script.language}
|
||||
code={script.content}
|
||||
class="whitespace-pre"
|
||||
class="whitespace-pre-wrap"
|
||||
/>
|
||||
</div>
|
||||
</TabContent>
|
||||
|
||||
@@ -1094,7 +1094,7 @@
|
||||
<br />By default everything is synced.
|
||||
</Tooltip></h4
|
||||
>
|
||||
<div class="flex flex-col gap-1 mt-1">
|
||||
<div class="flex flex-col gap-2 mt-1">
|
||||
<Toggle
|
||||
bind:checked={gitSyncSettings.include_type.scripts}
|
||||
on:change={(_) => resetGitSyncRepositoryExclude('scripts')}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import TabContent from '$lib/components/common/tabs/TabContent.svelte'
|
||||
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
|
||||
import DarkModeToggle from '$lib/components/sidebar/DarkModeToggle.svelte'
|
||||
import { Globe } from 'lucide-svelte'
|
||||
|
||||
let tab = 'button'
|
||||
let dropdownItems = [
|
||||
@@ -24,8 +25,15 @@
|
||||
<div class="font-bold text-md">Contained buttons</div>
|
||||
<div class="grid grid-cols-2 gap-2 md:grid-cols-4 lg:grid-cols-6">
|
||||
<Button>Lorem</Button>
|
||||
<Button color="dark">Lorem</Button>
|
||||
<Button color="gray">Lorem</Button>
|
||||
<Button color="dark" loading>Lorem</Button>
|
||||
<Button
|
||||
color="gray"
|
||||
startIcon={{
|
||||
icon: Globe
|
||||
}}
|
||||
>
|
||||
Lorem
|
||||
</Button>
|
||||
<Button color="green">Lorem</Button>
|
||||
<Button color="light">Lorem</Button>
|
||||
<Button color="none">Lorem</Button>
|
||||
|
||||
Reference in New Issue
Block a user