mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 16:02:28 +00:00
style: move step count tab to right side of group bounding box
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -209,6 +209,9 @@
|
||||
|
||||
let outputPickerInner: OutputPickerInner | undefined = $state(undefined)
|
||||
let historyOpen = $derived.by(() => outputPickerInner?.getHistoryOpen?.() ?? false)
|
||||
|
||||
const NODE_ACTION_CLASS =
|
||||
'center-center p-1 text-secondary cursor-grab hover:bg-surface-hover hover:text-primary'
|
||||
</script>
|
||||
|
||||
{#if deletable && id && editId}
|
||||
@@ -532,7 +535,7 @@
|
||||
|
||||
{#if !isMultiSelected && id !== 'preprocessor' && moveManager && id}
|
||||
<div
|
||||
class="absolute -translate-y-[100%] top-2 right-5 h-7 p-1 min-w-7"
|
||||
class="absolute -translate-y-[100%] top-1 right-5 h-7 p-1 min-w-7"
|
||||
style="will-change: transform;"
|
||||
>
|
||||
<MoveHandleButton
|
||||
@@ -548,7 +551,7 @@
|
||||
|
||||
{#if !isMultiSelected && menuItems && menuItems.length > 0}
|
||||
<div
|
||||
class="absolute -translate-y-[100%] top-2 -right-2 h-7 p-1 min-w-7"
|
||||
class="absolute -translate-y-[100%] top-1 -right-1 h-7 p-1 min-w-7"
|
||||
style="will-change: transform;"
|
||||
>
|
||||
<DropdownV2
|
||||
@@ -561,9 +564,8 @@
|
||||
{#snippet buttonReplacement()}
|
||||
<button
|
||||
class={twMerge(
|
||||
'trash center-center p-1 text-secondary shadow-sm bg-surface duration-0 hover:bg-surface-tertiary',
|
||||
NODE_ACTION_CLASS,
|
||||
hover || selected || dropdownOpen ? 'block' : '!hidden',
|
||||
'shadow-md rounded-md',
|
||||
'group-hover:block'
|
||||
)}
|
||||
onpointerdown={stopPropagation(preventDefault(() => {}))}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="absolute -translate-y-[100%] top-2 right-0 h-7 p-1 min-w-7"
|
||||
class="absolute -translate-y-[100%] top-1 right-0 h-7 p-1 min-w-7"
|
||||
style="will-change: transform;"
|
||||
>
|
||||
<DropdownV2
|
||||
@@ -47,9 +47,8 @@
|
||||
{#snippet buttonReplacement()}
|
||||
<button
|
||||
class={twMerge(
|
||||
'center-center p-1 text-secondary shadow-sm bg-surface duration-0 hover:bg-surface-tertiary',
|
||||
visible || menuOpen ? 'block' : '!hidden',
|
||||
'shadow-md rounded-md'
|
||||
'center-center p-1 text-secondary duration-0 hover:bg-surface-hover hover:text-primary rounded-md',
|
||||
visible || menuOpen ? 'block' : '!hidden'
|
||||
)}
|
||||
onpointerdown={stopPropagation(preventDefault(() => {}))}
|
||||
title="Actions"
|
||||
@@ -58,7 +57,9 @@
|
||||
</button>
|
||||
{/snippet}
|
||||
{#snippet menu()}
|
||||
<div class="bg-surface-tertiary dark:border w-56 origin-top-right rounded-lg shadow-lg focus:outline-none py-1">
|
||||
<div
|
||||
class="bg-surface-tertiary dark:border w-56 origin-top-right rounded-lg shadow-lg focus:outline-none py-1"
|
||||
>
|
||||
<!-- Color picker -->
|
||||
<div class="px-4 py-2">
|
||||
<div class="grid grid-cols-5 gap-1">
|
||||
@@ -89,10 +90,15 @@
|
||||
<!-- Add / Remove note -->
|
||||
<button
|
||||
class="px-4 py-2 text-primary font-normal hover:bg-surface-hover cursor-pointer text-xs w-full flex flex-row gap-2 items-center rounded-sm"
|
||||
onclick={() => { note == null ? onAddNote() : onRemoveNote(); menuOpen = false }}
|
||||
onclick={() => {
|
||||
note == null ? onAddNote() : onRemoveNote()
|
||||
menuOpen = false
|
||||
}}
|
||||
>
|
||||
<StickyNote size={14} class="shrink-0" />
|
||||
<p class="truncate grow min-w-0 whitespace-nowrap text-left">{note == null ? 'Add note' : 'Remove note'}</p>
|
||||
<p class="truncate grow min-w-0 whitespace-nowrap text-left"
|
||||
>{note == null ? 'Add note' : 'Remove note'}</p
|
||||
>
|
||||
</button>
|
||||
|
||||
{#if onDeleteGroup}
|
||||
@@ -101,7 +107,10 @@
|
||||
<!-- Ungroup -->
|
||||
<button
|
||||
class="px-4 py-2 font-normal hover:bg-red-500/10 cursor-pointer text-xs w-full flex flex-row gap-2 items-center rounded-sm text-red-600 dark:text-red-400"
|
||||
onclick={() => { onDeleteGroup?.(); menuOpen = false }}
|
||||
onclick={() => {
|
||||
onDeleteGroup?.()
|
||||
menuOpen = false
|
||||
}}
|
||||
>
|
||||
<Ungroup size={14} class="shrink-0" />
|
||||
<p class="truncate grow min-w-0 whitespace-nowrap text-left">Ungroup</p>
|
||||
|
||||
@@ -86,12 +86,11 @@
|
||||
if (group.module_ids.length === 0) return null
|
||||
const { minX, minY, maxX, maxY } = calculateNodesBoundsWithOffset(group.module_ids, allNodes)
|
||||
const padding = 16
|
||||
const topPadding = 28
|
||||
return {
|
||||
x: minX - padding,
|
||||
y: minY - topPadding,
|
||||
y: minY - padding,
|
||||
width: maxX - minX + 2 * padding,
|
||||
height: maxY - minY + topPadding + padding
|
||||
height: maxY - minY + 2 * padding
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +166,7 @@
|
||||
// Include the header node itself in the bounds
|
||||
const allIds = [node.id, ...innerIds]
|
||||
const { minX, minY, maxX, maxY } = calculateNodesBoundsWithOffset(allIds, allNodes)
|
||||
const padding = 16
|
||||
const padding = 8
|
||||
return {
|
||||
x: minX - padding,
|
||||
y: minY - padding,
|
||||
@@ -198,11 +197,11 @@
|
||||
<ViewportPortal target="front">
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class="absolute flex items-start justify-between"
|
||||
class="absolute flex items-start justify-end"
|
||||
style="pointer-events: auto; transform: translate({bounds.x}px, {bounds.y}px); width: {bounds.width}px;"
|
||||
style:z-index="4"
|
||||
>
|
||||
<div class="relative" style="margin-left: 16px;">
|
||||
<div class="relative" style="margin-right: 16px;">
|
||||
<StepCountTab
|
||||
stepCount={group.module_ids.length}
|
||||
color={group.color}
|
||||
@@ -210,42 +209,43 @@
|
||||
short
|
||||
onExpand={() => toggleCollapse(group.id)}
|
||||
/>
|
||||
{#if editingGroupId === group.id}
|
||||
{@const textColorClass =
|
||||
NOTE_COLORS[(group.color as NoteColor) ?? NoteColor.BLUE]?.text ?? ''}
|
||||
<input
|
||||
bind:this={summaryInputEl}
|
||||
bind:value={summaryInput}
|
||||
class="absolute !text-3xs !font-medium !h-4 !bg-transparent !outline-none {textColorClass}"
|
||||
style="top: 2px; left:-3px; width: 160px; padding: 2px 2px;"
|
||||
onblur={() => saveSummary(group.id)}
|
||||
onkeydown={(e) => handleSummaryKeydown(e, group.id)}
|
||||
onclick={stopPropagation(preventDefault(() => {}))}
|
||||
onpointerdown={stopPropagation(preventDefault(() => {}))}
|
||||
spellcheck={false}
|
||||
/>
|
||||
{:else}
|
||||
{@const textColorClass =
|
||||
NOTE_COLORS[(group.color as NoteColor) ?? NoteColor.BLUE]?.text ?? ''}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<span
|
||||
class="absolute text-3xs font-medium truncate max-w-[150px] text-opacity-60 {textColorClass} {editMode
|
||||
? 'cursor-text rounded px-0.5 -mx-0.5 hover:text-opacity-100'
|
||||
: ''}"
|
||||
style="top: 2px; left: 0px;"
|
||||
onclick={editMode
|
||||
? stopPropagation(
|
||||
preventDefault(() => startEditingSummary(group.id, group.summary ?? ''))
|
||||
)
|
||||
: undefined}
|
||||
onpointerdown={editMode ? stopPropagation(preventDefault(() => {})) : undefined}
|
||||
>{group.summary || (editMode ? 'Group' : '')}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if editingGroupId === group.id}
|
||||
{@const textColorClass =
|
||||
NOTE_COLORS[(group.color as NoteColor) ?? NoteColor.BLUE]?.text ?? ''}
|
||||
<input
|
||||
bind:this={summaryInputEl}
|
||||
bind:value={summaryInput}
|
||||
class="absolute !text-3xs !font-medium !h-4 !bg-transparent !outline-none {textColorClass}"
|
||||
style="top: -18px; left:-3px; width: 160px; padding: 2px 2px;"
|
||||
onblur={() => saveSummary(group.id)}
|
||||
onkeydown={(e) => handleSummaryKeydown(e, group.id)}
|
||||
onclick={stopPropagation(preventDefault(() => {}))}
|
||||
onpointerdown={stopPropagation(preventDefault(() => {}))}
|
||||
spellcheck={false}
|
||||
/>
|
||||
{:else}
|
||||
{@const textColorClass =
|
||||
NOTE_COLORS[(group.color as NoteColor) ?? NoteColor.BLUE]?.text ?? ''}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<span
|
||||
class="absolute text-3xs font-medium truncate max-w-[150px] text-opacity-60 {textColorClass} {editMode
|
||||
? 'cursor-text rounded px-0.5 -mx-0.5 hover:text-opacity-100'
|
||||
: ''}"
|
||||
style="top: -18px; left: 0px;"
|
||||
onclick={editMode
|
||||
? stopPropagation(
|
||||
preventDefault(() => startEditingSummary(group.id, group.summary ?? ''))
|
||||
)
|
||||
: undefined}
|
||||
onpointerdown={editMode ? stopPropagation(preventDefault(() => {})) : undefined}
|
||||
>{group.summary || (editMode ? 'Group' : '')}</span
|
||||
>
|
||||
{/if}
|
||||
{#if editMode}
|
||||
<div class="relative" style="margin-top: -8px;">
|
||||
<div class="absolute" style="top: 0px; right: 16px;">
|
||||
<GroupActionBar
|
||||
note={group.note}
|
||||
color={group.color}
|
||||
|
||||
@@ -61,9 +61,9 @@
|
||||
|
||||
<button
|
||||
class={twMerge(
|
||||
'center-center p-1 text-secondary shadow-sm bg-surface duration-0 hover:bg-surface-tertiary cursor-grab',
|
||||
'center-center p-1 text-secondary cursor-grab hover:bg-surface-hover hover:text-primary',
|
||||
visible ? '' : '!hidden',
|
||||
'shadow-md rounded-md',
|
||||
'rounded-md',
|
||||
'touch-none',
|
||||
extraClass
|
||||
)}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class="absolute left-0 rounded-t-md px-2 text-3xs font-medium z-[-1] flex items-start gap-0.5 {colorConfig.background} {colorConfig.text} {onExpand
|
||||
class="absolute right-[48px] rounded-t-md px-2 text-3xs font-medium z-[-1] flex items-start gap-0.5 {colorConfig.background} {colorConfig.text} {onExpand
|
||||
? 'cursor-pointer hover:opacity-80'
|
||||
: ''}"
|
||||
style="top: -20px; height: {short ? 20 : 34}px;"
|
||||
|
||||
@@ -261,7 +261,7 @@ export function getGroupEditorContext(): GroupEditorContext | undefined {
|
||||
/** Extra vertical space pushed above the topmost node of each group for the tab */
|
||||
export const GROUP_HEADER_HEIGHT = 0
|
||||
|
||||
const GROUP_TOP_MARGIN = 28
|
||||
const GROUP_TOP_MARGIN = 16
|
||||
|
||||
/**
|
||||
* Compute adjusted node positions for collapsed groups whose note is visible.
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
if (data.isCollapsedContainer) return data.containerModules?.length ?? 0
|
||||
const v = data.module.value
|
||||
if (v.type === 'branchall') return v.branches.flatMap((b) => b.modules).length
|
||||
if (v.type === 'branchone') return v.default.length + v.branches.flatMap((b) => b.modules).length
|
||||
if (v.type === 'branchone')
|
||||
return v.default.length + v.branches.flatMap((b) => b.modules).length
|
||||
if (v.type === 'forloopflow' || v.type === 'whileloopflow') return v.modules.length
|
||||
return 0
|
||||
})
|
||||
@@ -61,7 +62,7 @@
|
||||
// Define context menu items
|
||||
let noteDisabled = $derived(
|
||||
!noteEditorContext?.noteEditor ||
|
||||
(noteEditorContext?.noteEditor?.isNodeOnlyMemberOfGroupNote(data.id) ?? false)
|
||||
(noteEditorContext?.noteEditor?.isNodeOnlyMemberOfGroupNote(data.id) ?? false)
|
||||
)
|
||||
|
||||
let isPreprocessor = $derived(data.id === 'preprocessor')
|
||||
|
||||
Reference in New Issue
Block a user