Component: The Rest of the PrimeVue buttons (#7649)

## Summary

Automated initial change, cleaned up manually.

Please check the screenshot changes.

Includes a11y updates to icon buttons.

Doesn't hit the buttons in Desktop.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7649-WIP-Component-The-Rest-of-the-PrimeVue-buttons-2ce6d73d365081d68e06f200f1321267)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
Alexander Brown
2025-12-29 15:03:34 -08:00
committed by GitHub
parent ea96c71818
commit 7b68b19f11
159 changed files with 1330 additions and 1359 deletions

View File

@@ -110,16 +110,18 @@ type KeysOfType<T, Match> = {
}[keyof T] }[keyof T]
class ConfirmDialog { class ConfirmDialog {
private readonly root: Locator
public readonly delete: Locator public readonly delete: Locator
public readonly overwrite: Locator public readonly overwrite: Locator
public readonly reject: Locator public readonly reject: Locator
public readonly confirm: Locator public readonly confirm: Locator
constructor(public readonly page: Page) { constructor(public readonly page: Page) {
this.delete = page.locator('button.p-button[aria-label="Delete"]') this.root = page.getByRole('dialog')
this.overwrite = page.locator('button.p-button[aria-label="Overwrite"]') this.delete = this.root.getByRole('button', { name: 'Delete' })
this.reject = page.locator('button.p-button[aria-label="Cancel"]') this.overwrite = this.root.getByRole('button', { name: 'Overwrite' })
this.confirm = page.locator('button.p-button[aria-label="Confirm"]') this.reject = this.root.getByRole('button', { name: 'Cancel' })
this.confirm = this.root.getByRole('button', { name: 'Confirm' })
} }
async click(locator: KeysOfType<ConfirmDialog, Locator>) { async click(locator: KeysOfType<ConfirmDialog, Locator>) {

View File

@@ -30,7 +30,7 @@ export class ComfyNodeSearchFilterSelectionPanel {
async addFilter(filterValue: string, filterType: string) { async addFilter(filterValue: string, filterType: string) {
await this.selectFilterType(filterType) await this.selectFilterType(filterType)
await this.selectFilterValue(filterValue) await this.selectFilterValue(filterValue)
await this.page.locator('.p-button-label:has-text("Add")').click() await this.page.locator('button:has-text("Add")').click()
} }
} }

View File

@@ -85,11 +85,11 @@ test.describe('Missing models warning', () => {
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models') const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible() await expect(missingModelsWarning).toBeVisible()
const downloadButton = missingModelsWarning.getByLabel('Download') const downloadButton = missingModelsWarning.getByText('Download')
await expect(downloadButton).toBeVisible() await expect(downloadButton).toBeVisible()
// Check that the copy URL button is also visible for Desktop environment // Check that the copy URL button is also visible for Desktop environment
const copyUrlButton = missingModelsWarning.getByLabel('Copy URL') const copyUrlButton = missingModelsWarning.getByText('Copy URL')
await expect(copyUrlButton).toBeVisible() await expect(copyUrlButton).toBeVisible()
}) })
@@ -102,11 +102,11 @@ test.describe('Missing models warning', () => {
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models') const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible() await expect(missingModelsWarning).toBeVisible()
const downloadButton = missingModelsWarning.getByLabel('Download') const downloadButton = missingModelsWarning.getByText('Download')
await expect(downloadButton).toBeVisible() await expect(downloadButton).toBeVisible()
// Check that the copy URL button is also visible for Desktop environment // Check that the copy URL button is also visible for Desktop environment
const copyUrlButton = missingModelsWarning.getByLabel('Copy URL') const copyUrlButton = missingModelsWarning.getByText('Copy URL')
await expect(copyUrlButton).toBeVisible() await expect(copyUrlButton).toBeVisible()
}) })
@@ -176,7 +176,7 @@ test.describe('Missing models warning', () => {
const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models') const missingModelsWarning = comfyPage.page.locator('.comfy-missing-models')
await expect(missingModelsWarning).toBeVisible() await expect(missingModelsWarning).toBeVisible()
const downloadButton = comfyPage.page.getByLabel('Download') const downloadButton = comfyPage.page.getByText('Download')
await expect(downloadButton).toBeVisible() await expect(downloadButton).toBeVisible()
const downloadPromise = comfyPage.page.waitForEvent('download') const downloadPromise = comfyPage.page.waitForEvent('download')
await downloadButton.click() await downloadButton.click()
@@ -290,7 +290,7 @@ test.describe('Settings', () => {
// Save keybinding // Save keybinding
const saveButton = comfyPage.page const saveButton = comfyPage.page
.getByLabel('New Blank Workflow') .getByLabel('New Blank Workflow')
.getByLabel('Save') .getByText('Save')
await saveButton.click() await saveButton.click()
const request = await requestPromise const request = await requestPromise

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -123,8 +123,7 @@ test.describe('Node Help', () => {
await expect(helpPage).toContainText('KSampler') await expect(helpPage).toContainText('KSampler')
// Click the back button - use a more specific selector // Click the back button - use a more specific selector
const backButton = comfyPage.page.locator('button:has(.pi-arrow-left)') const backButton = helpPage.getByRole('button', { name: /back/i })
await expect(backButton).toBeVisible()
await backButton.click() await backButton.click()
// Verify that we're back to the node library view // Verify that we're back to the node library view

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

@@ -100,7 +100,7 @@ test.describe('Node library sidebar', () => {
const tab = comfyPage.menu.nodeLibraryTab const tab = comfyPage.menu.nodeLibraryTab
await tab.getFolder('foo').click({ button: 'right' }) await tab.getFolder('foo').click({ button: 'right' })
await comfyPage.page.getByLabel('New Folder').click() await comfyPage.page.getByRole('menuitem', { name: 'New Folder' }).click()
const textInput = comfyPage.page.locator('.editable-text input') const textInput = comfyPage.page.locator('.editable-text input')
await textInput.waitFor({ state: 'visible' }) await textInput.waitFor({ state: 'visible' })
await textInput.fill('bar') await textInput.fill('bar')
@@ -203,7 +203,7 @@ test.describe('Node library sidebar', () => {
await comfyPage.page await comfyPage.page
.locator('.color-field .p-selectbutton > *:nth-child(2)') .locator('.color-field .p-selectbutton > *:nth-child(2)')
.click() .click()
await comfyPage.page.getByLabel('Confirm').click() await comfyPage.page.getByRole('button', { name: 'Confirm' }).click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
expect( expect(
await comfyPage.getSetting('Comfy.NodeLibrary.BookmarksCustomization') await comfyPage.getSetting('Comfy.NodeLibrary.BookmarksCustomization')
@@ -223,7 +223,7 @@ test.describe('Node library sidebar', () => {
await comfyPage.page await comfyPage.page
.locator('.icon-field .p-selectbutton > *:nth-child(2)') .locator('.icon-field .p-selectbutton > *:nth-child(2)')
.click() .click()
await comfyPage.page.getByLabel('Confirm').click() await comfyPage.page.getByRole('button', { name: 'Confirm' }).click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
expect( expect(
await comfyPage.getSetting('Comfy.NodeLibrary.BookmarksCustomization') await comfyPage.getSetting('Comfy.NodeLibrary.BookmarksCustomization')
@@ -261,7 +261,7 @@ test.describe('Node library sidebar', () => {
await comfyPage.page await comfyPage.page
.locator('.icon-field .p-selectbutton > *:nth-child(2)') .locator('.icon-field .p-selectbutton > *:nth-child(2)')
.click() .click()
await comfyPage.page.getByLabel('Confirm').click() await comfyPage.page.getByRole('button', { name: 'Confirm' }).click()
await comfyPage.nextFrame() await comfyPage.nextFrame()
// Verify the color selection is saved // Verify the color selection is saved

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -5,23 +5,23 @@
> >
<Button <Button
v-tooltip="{ value: $t('menu.showMenu'), showDelay: 300 }" v-tooltip="{ value: $t('menu.showMenu'), showDelay: 300 }"
icon="pi pi-bars" variant="muted-textonly"
severity="secondary" size="lg"
text
size="large"
:aria-label="$t('menu.showMenu')" :aria-label="$t('menu.showMenu')"
aria-live="assertive" aria-live="assertive"
@click="exitFocusMode" @click="exitFocusMode"
@contextmenu="showNativeSystemMenu" @contextmenu="showNativeSystemMenu"
/> >
<i class="pi pi-bars" />
</Button>
<div class="window-actions-spacer" /> <div class="window-actions-spacer" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { watchEffect } from 'vue' import { watchEffect } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'
import { app } from '@/scripts/app' import { app } from '@/scripts/app'
import { useWorkspaceStore } from '@/stores/workspaceStore' import { useWorkspaceStore } from '@/stores/workspaceStore'

View File

@@ -22,12 +22,13 @@
value: item.tooltip, value: item.tooltip,
showDelay: 600 showDelay: 600
}" }"
:label="String(item.label ?? '')" :variant="item.key === queueMode ? 'primary' : 'secondary'"
:icon="item.icon" size="sm"
:severity="item.key === queueMode ? 'primary' : 'secondary'" class="w-full justify-start"
size="small" >
text <i v-if="item.icon" :class="item.icon" />
/> {{ String(item.label ?? '') }}
</Button>
</template> </template>
</SplitButton> </SplitButton>
<BatchCountEdit /> <BatchCountEdit />
@@ -36,12 +37,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import Button from 'primevue/button'
import type { MenuItem } from 'primevue/menuitem' import type { MenuItem } from 'primevue/menuitem'
import SplitButton from 'primevue/splitbutton' import SplitButton from 'primevue/splitbutton'
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { isCloud } from '@/platform/distribution/types' import { isCloud } from '@/platform/distribution/types'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import { app } from '@/scripts/app' import { app } from '@/scripts/app'

View File

@@ -46,21 +46,22 @@
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Button <Button
v-if="isShortcutsTabActive" v-if="isShortcutsTabActive"
:label="$t('shortcuts.manageShortcuts')" variant="muted-textonly"
icon="pi pi-cog" size="sm"
severity="secondary"
size="small"
text
@click="openKeybindingSettings" @click="openKeybindingSettings"
/> >
<i class="pi pi-cog" />
{{ $t('shortcuts.manageShortcuts') }}
</Button>
<Button <Button
class="justify-self-end" class="justify-self-end"
icon="pi pi-times" variant="muted-textonly"
severity="secondary" size="sm"
size="small" :aria-label="t('g.close')"
text
@click="closeBottomPanel" @click="closeBottomPanel"
/> >
<i class="pi pi-times" />
</Button>
</div> </div>
</div> </div>
</TabList> </TabList>
@@ -79,7 +80,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Tab from 'primevue/tab' import Tab from 'primevue/tab'
import type { TabPassThroughMethodOptions } from 'primevue/tab' import type { TabPassThroughMethodOptions } from 'primevue/tab'
import TabList from 'primevue/tablist' import TabList from 'primevue/tablist'
@@ -88,6 +88,7 @@ import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import ExtensionSlot from '@/components/common/ExtensionSlot.vue' import ExtensionSlot from '@/components/common/ExtensionSlot.vue'
import Button from '@/components/ui/button/Button.vue'
import { useDialogService } from '@/services/dialogService' import { useDialogService } from '@/services/dialogService'
import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore'
import type { BottomPanelExtension } from '@/types/extensionTypes' import type { BottomPanelExtension } from '@/types/extensionTypes'

View File

@@ -11,9 +11,8 @@
value: tooltipText, value: tooltipText,
showDelay: 300 showDelay: 300
}" }"
icon="pi pi-copy" variant="secondary"
severity="secondary" size="sm"
size="small"
:class=" :class="
cn('absolute top-2 right-8 transition-opacity', { cn('absolute top-2 right-8 transition-opacity', {
'opacity-0 pointer-events-none select-none': !isHovered 'opacity-0 pointer-events-none select-none': !isHovered
@@ -21,18 +20,20 @@
" "
:aria-label="tooltipText" :aria-label="tooltipText"
@click="handleCopy" @click="handleCopy"
/> >
<i class="pi pi-copy" />
</Button>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useElementHover, useEventListener } from '@vueuse/core' import { useElementHover, useEventListener } from '@vueuse/core'
import type { IDisposable } from '@xterm/xterm' import type { IDisposable } from '@xterm/xterm'
import Button from 'primevue/button'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal' import { useTerminal } from '@/composables/bottomPanelTabs/useTerminal'
import { electronAPI, isElectron } from '@/utils/envUtil' import { electronAPI, isElectron } from '@/utils/envUtil'
import { cn } from '@/utils/tailwindUtil' import { cn } from '@/utils/tailwindUtil'

View File

@@ -7,20 +7,24 @@
/> />
<Button <Button
v-tooltip="$t('g.upload')" v-tooltip="$t('g.upload')"
:icon="isUploading ? 'pi pi-spin pi-spinner' : 'pi pi-upload'" variant="secondary"
size="small" size="sm"
:aria-label="$t('g.upload')"
:disabled="isUploading" :disabled="isUploading"
@click="triggerFileInput" @click="triggerFileInput"
/> >
<i :class="isUploading ? 'pi pi-spin pi-spinner' : 'pi pi-upload'" />
</Button>
<Button <Button
v-tooltip="$t('g.clear')" v-tooltip="$t('g.clear')"
outlined variant="destructive"
icon="pi pi-trash" size="sm"
severity="danger" :aria-label="$t('g.clear')"
size="small"
:disabled="!modelValue" :disabled="!modelValue"
@click="clearImage" @click="clearImage"
/> >
<i class="pi pi-trash" />
</Button>
<input <input
ref="fileInput" ref="fileInput"
type="file" type="file"
@@ -32,10 +36,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useToastStore } from '@/platform/updates/common/toastStore' import { useToastStore } from '@/platform/updates/common/toastStore'
import { api } from '@/scripts/api' import { api } from '@/scripts/api'

View File

@@ -27,24 +27,19 @@
</div> </div>
</div> </div>
<template #footer> <template #footer>
<Button <Button variant="textonly" @click="resetCustomization">
:label="$t('g.reset')" <i class="pi pi-refresh" />
icon="pi pi-refresh" {{ $t('g.reset') }}
class="p-button-text" </Button>
@click="resetCustomization" <Button autofocus @click="confirmCustomization">
/> <i class="pi pi-check" />
<Button {{ $t('g.confirm') }}
:label="$t('g.confirm')" </Button>
icon="pi pi-check"
autofocus
@click="confirmCustomization"
/>
</template> </template>
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Dialog from 'primevue/dialog' import Dialog from 'primevue/dialog'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
import SelectButton from 'primevue/selectbutton' import SelectButton from 'primevue/selectbutton'
@@ -52,6 +47,7 @@ import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import ColorCustomizationSelector from '@/components/common/ColorCustomizationSelector.vue' import ColorCustomizationSelector from '@/components/common/ColorCustomizationSelector.vue'
import Button from '@/components/ui/button/Button.vue'
import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore' import { useNodeBookmarkStore } from '@/stores/nodeBookmarkStore'
const { t } = useI18n() const { t } = useI18n()

View File

@@ -16,20 +16,22 @@
<Button <Button
v-if="status === null || status === 'error'" v-if="status === null || status === 'error'"
class="file-action-button" class="file-action-button"
:label="$t('g.download') + ' (' + fileSize + ')'" variant="secondary"
size="small" size="sm"
outlined
:disabled="!!props.error" :disabled="!!props.error"
icon="pi pi-download"
@click="triggerDownload" @click="triggerDownload"
/> >
<i class="pi pi-download" />
{{ $t('g.download') + ' (' + fileSize + ')' }}
</Button>
<Button <Button
v-if="(status === null || status === 'error') && !!props.url" v-if="(status === null || status === 'error') && !!props.url"
:label="$t('g.copyURL')" variant="secondary"
size="small" size="sm"
outlined
@click="copyURL" @click="copyURL"
/> >
{{ $t('g.copyURL') }}
</Button>
</div> </div>
</div> </div>
<div <div
@@ -49,44 +51,48 @@
v-if="status === 'in_progress'" v-if="status === 'in_progress'"
v-tooltip.top="t('electronFileDownload.pause')" v-tooltip.top="t('electronFileDownload.pause')"
class="file-action-button" class="file-action-button"
size="small" variant="secondary"
outlined size="sm"
:disabled="!!props.error" :disabled="!!props.error"
icon="pi pi-pause-circle"
@click="triggerPauseDownload" @click="triggerPauseDownload"
/> >
<i class="pi pi-pause-circle" />
</Button>
<Button <Button
v-if="status === 'paused'" v-if="status === 'paused'"
v-tooltip.top="t('electronFileDownload.resume')" v-tooltip.top="t('electronFileDownload.resume')"
class="file-action-button" class="file-action-button"
size="small" variant="secondary"
outlined size="sm"
:aria-label="t('electronFileDownload.resume')"
:disabled="!!props.error" :disabled="!!props.error"
icon="pi pi-play-circle"
@click="triggerResumeDownload" @click="triggerResumeDownload"
/> >
<i class="pi pi-play-circle" />
</Button>
<Button <Button
v-tooltip.top="t('electronFileDownload.cancel')" v-tooltip.top="t('electronFileDownload.cancel')"
class="file-action-button" class="file-action-button"
size="small" variant="destructive"
outlined size="sm"
:aria-label="t('electronFileDownload.cancel')"
:disabled="!!props.error" :disabled="!!props.error"
icon="pi pi-times-circle"
severity="danger"
@click="triggerCancelDownload" @click="triggerCancelDownload"
/> >
<i class="pi pi-times-circle" />
</Button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import ProgressBar from 'primevue/progressbar' import ProgressBar from 'primevue/progressbar'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useCopyToClipboard } from '@/composables/useCopyToClipboard' import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
import { useDownload } from '@/composables/useDownload' import { useDownload } from '@/composables/useDownload'
import { useElectronDownloadStore } from '@/stores/electronDownloadStore' import { useElectronDownloadStore } from '@/stores/electronDownloadStore'

View File

@@ -22,31 +22,27 @@
</div> </div>
<div> <div>
<Button <Button
:label="$t('g.download') + ' (' + fileSize + ')'" variant="secondary"
size="small"
outlined
:disabled="!!props.error" :disabled="!!props.error"
:title="props.url" :title="props.url"
@click="download.triggerBrowserDownload" @click="download.triggerBrowserDownload"
/> >
{{ $t('g.download') + ' (' + fileSize + ')' }}
</Button>
</div> </div>
<div> <div>
<Button <Button variant="secondary" :disabled="!!props.error" @click="copyURL">
:label="$t('g.copyURL')" {{ $t('g.copyURL') }}
size="small" </Button>
outlined
:disabled="!!props.error"
@click="copyURL"
/>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Message from 'primevue/message' import Message from 'primevue/message'
import { computed } from 'vue' import { computed } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useCopyToClipboard } from '@/composables/useCopyToClipboard' import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
import { useDownload } from '@/composables/useDownload' import { useDownload } from '@/composables/useDownload'
import { formatSize } from '@/utils/formatUtil' import { formatSize } from '@/utils/formatUtil'

View File

@@ -14,21 +14,20 @@
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<Button <Button size="sm" @click="triggerFileInput">
icon="pi pi-upload" <i class="pi pi-upload" />
:label="$t('g.upload')" {{ $t('g.upload') }}
size="small" </Button>
@click="triggerFileInput"
/>
<Button <Button
v-if="modelValue" v-if="modelValue"
class="w-full" class="w-full"
outlined variant="destructive"
icon="pi pi-trash" size="sm"
severity="danger" :aria-label="$t('g.delete')"
size="small"
@click="clearImage" @click="clearImage"
/> >
<i class="pi pi-trash" />
</Button>
</div> </div>
</div> </div>
<input <input
@@ -42,9 +41,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
defineProps<{ defineProps<{
modelValue: string modelValue: string
}>() }>()

View File

@@ -10,10 +10,11 @@
</p> </p>
<Button <Button
v-if="buttonLabel" v-if="buttonLabel"
:label="buttonLabel" variant="textonly"
class="p-button-text"
@click="$emit('action')" @click="$emit('action')"
/> >
{{ buttonLabel }}
</Button>
</div> </div>
</template> </template>
</Card> </Card>
@@ -21,9 +22,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Card from 'primevue/card' import Card from 'primevue/card'
import Button from '@/components/ui/button/Button.vue'
const props = defineProps<{ const props = defineProps<{
class?: string class?: string
icon?: string icon?: string

View File

@@ -11,24 +11,25 @@
<ApiNodesList :node-names="apiNodeNames" /> <ApiNodesList :node-names="apiNodeNames" />
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<Button :label="t('g.learnMore')" link @click="handleLearnMoreClick" /> <Button variant="textonly" @click="handleLearnMoreClick">
{{ t('g.learnMore') }}
</Button>
<div class="flex gap-2"> <div class="flex gap-2">
<Button <Button variant="secondary" @click="onCancel?.()">
:label="t('g.cancel')" {{ t('g.cancel') }}
outlined </Button>
severity="secondary" <Button @click="onLogin?.()">
@click="onCancel?.()" {{ t('g.login') }}
/> </Button>
<Button :label="t('g.login')" @click="onLogin?.()" />
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useExternalLink } from '@/composables/useExternalLink' import { useExternalLink } from '@/composables/useExternalLink'
const { t } = useI18n() const { t } = useI18n()

View File

@@ -31,69 +31,64 @@
}}</label> }}</label>
</div> </div>
<Button <Button variant="secondary" autofocus @click="onCancel">
:label="$t('g.cancel')" <i class="pi pi-undo" />
icon="pi pi-undo" {{ $t('g.cancel') }}
severity="secondary" </Button>
autofocus <Button v-if="type === 'default'" variant="primary" @click="onConfirm">
@click="onCancel" <i class="pi pi-check" />
/> {{ $t('g.confirm') }}
<Button </Button>
v-if="type === 'default'"
:label="$t('g.confirm')"
severity="primary"
icon="pi pi-check"
@click="onConfirm"
/>
<Button <Button
v-else-if="type === 'delete'" v-else-if="type === 'delete'"
:label="$t('g.delete')" variant="destructive"
severity="danger"
icon="pi pi-trash"
@click="onConfirm" @click="onConfirm"
/> >
<i class="pi pi-trash" />
{{ $t('g.delete') }}
</Button>
<Button <Button
v-else-if="type === 'overwrite' || type === 'overwriteBlueprint'" v-else-if="type === 'overwrite' || type === 'overwriteBlueprint'"
:label="$t('g.overwrite')" variant="destructive"
severity="warn"
icon="pi pi-save"
@click="onConfirm" @click="onConfirm"
/> >
<i class="pi pi-save" />
{{ $t('g.overwrite') }}
</Button>
<template v-else-if="type === 'dirtyClose'"> <template v-else-if="type === 'dirtyClose'">
<Button <Button variant="secondary" @click="onDeny">
:label="$t('g.no')" <i class="pi pi-times" />
severity="secondary" {{ $t('g.no') }}
icon="pi pi-times" </Button>
@click="onDeny" <Button @click="onConfirm">
/> <i class="pi pi-save" />
<Button :label="$t('g.save')" icon="pi pi-save" @click="onConfirm" /> {{ $t('g.save') }}
</Button>
</template> </template>
<Button <Button
v-else-if="type === 'reinstall'" v-else-if="type === 'reinstall'"
:label="$t('desktopMenu.reinstall')" variant="destructive"
severity="warn"
icon="pi pi-eraser"
@click="onConfirm" @click="onConfirm"
/> >
<i class="pi pi-eraser" />
{{ $t('desktopMenu.reinstall') }}
</Button>
<!-- Invalid - just show a close button. --> <!-- Invalid - just show a close button. -->
<Button <Button v-else variant="primary" @click="onCancel">
v-else <i class="pi pi-times" />
:label="$t('g.close')" {{ $t('g.close') }}
severity="primary" </Button>
icon="pi pi-times"
@click="onCancel"
/>
</div> </div>
</section> </section>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Checkbox from 'primevue/checkbox' import Checkbox from 'primevue/checkbox'
import Message from 'primevue/message' import Message from 'primevue/message'
import { ref } from 'vue' import { ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'
import type { ConfirmationDialogType } from '@/services/dialogService' import type { ConfirmationDialogType } from '@/services/dialogService'
import { useDialogStore } from '@/stores/dialogStore' import { useDialogStore } from '@/stores/dialogStore'

View File

@@ -14,18 +14,16 @@
</template> </template>
<div class="flex justify-center gap-2"> <div class="flex justify-center gap-2">
<Button v-show="!reportOpen" variant="textonly" @click="showReport">
{{ $t('g.showReport') }}
</Button>
<Button <Button
v-show="!reportOpen" v-show="!reportOpen"
text variant="textonly"
:label="$t('g.showReport')"
@click="showReport"
/>
<Button
v-show="!reportOpen"
text
:label="$t('issueReport.helpFix')"
@click="showContactSupport" @click="showContactSupport"
/> >
{{ $t('issueReport.helpFix') }}
</Button>
</div> </div>
<template v-if="reportOpen"> <template v-if="reportOpen">
<Divider /> <Divider />
@@ -40,18 +38,15 @@
:repo-owner="repoOwner" :repo-owner="repoOwner"
:repo-name="repoName" :repo-name="repoName"
/> />
<Button <Button v-if="reportOpen" @click="copyReportToClipboard">
v-if="reportOpen" <i class="pi pi-copy" />
:label="$t('g.copyToClipboard')" {{ $t('g.copyToClipboard') }}
icon="pi pi-copy" </Button>
@click="copyReportToClipboard"
/>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
import ScrollPanel from 'primevue/scrollpanel' import ScrollPanel from 'primevue/scrollpanel'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
@@ -60,6 +55,7 @@ import { useI18n } from 'vue-i18n'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue' import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import FindIssueButton from '@/components/dialog/content/error/FindIssueButton.vue' import FindIssueButton from '@/components/dialog/content/error/FindIssueButton.vue'
import Button from '@/components/ui/button/Button.vue'
import { useCopyToClipboard } from '@/composables/useCopyToClipboard' import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import { api } from '@/scripts/api' import { api } from '@/scripts/api'

View File

@@ -18,11 +18,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import FloatLabel from 'primevue/floatlabel' import FloatLabel from 'primevue/floatlabel'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useDialogStore } from '@/stores/dialogStore' import { useDialogStore } from '@/stores/dialogStore'
const props = defineProps<{ const props = defineProps<{

View File

@@ -51,8 +51,7 @@
<Button <Button
type="button" type="button"
class="h-10" class="h-10"
severity="secondary" variant="secondary"
outlined
@click="signInWithGoogle" @click="signInWithGoogle"
> >
<i class="pi pi-google mr-2"></i> <i class="pi pi-google mr-2"></i>
@@ -66,8 +65,7 @@
<Button <Button
type="button" type="button"
class="h-10" class="h-10"
severity="secondary" variant="secondary"
outlined
@click="signInWithGithub" @click="signInWithGithub"
> >
<i class="pi pi-github mr-2"></i> <i class="pi pi-github mr-2"></i>
@@ -82,8 +80,7 @@
<Button <Button
type="button" type="button"
class="h-10" class="h-10"
severity="secondary" variant="secondary"
outlined
@click="showApiKeyForm = true" @click="showApiKeyForm = true"
> >
<img <img
@@ -142,12 +139,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
import Message from 'primevue/message' import Message from 'primevue/message'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { getComfyPlatformBaseUrl } from '@/config/comfyApi' import { getComfyPlatformBaseUrl } from '@/config/comfyApi'
import { import {

View File

@@ -58,26 +58,27 @@
<Button <Button
:disabled="!selectedCredits || loading" :disabled="!selectedCredits || loading"
:loading="loading" :loading="loading"
severity="primary" variant="primary"
:label="$t('credits.topUp.buy')" :class="cn('w-full', (!selectedCredits || loading) && 'opacity-30')"
:class="['w-full', { 'opacity-30': !selectedCredits || loading }]"
:pt="{ label: { class: 'text-primary-foreground' } }"
@click="handleBuy" @click="handleBuy"
/> >
{{ $t('credits.topUp.buy') }}
</Button>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { useToast } from 'primevue/usetoast' import { useToast } from 'primevue/usetoast'
import { ref } from 'vue' import { ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { creditsToUsd } from '@/base/credits/comfyCredits' import { creditsToUsd } from '@/base/credits/comfyCredits'
import UserCredit from '@/components/common/UserCredit.vue' import UserCredit from '@/components/common/UserCredit.vue'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription' import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import { cn } from '@/utils/tailwindUtil'
import CreditTopUpOption from './credit/CreditTopUpOption.vue' import CreditTopUpOption from './credit/CreditTopUpOption.vue'

View File

@@ -7,12 +7,9 @@
<PasswordFields /> <PasswordFields />
<!-- Submit Button --> <!-- Submit Button -->
<Button <Button type="submit" class="mt-4 h-10 font-medium" :loading="loading">
type="submit" {{ $t('userSettings.updatePassword') }}
:label="$t('userSettings.updatePassword')" </Button>
class="mt-4 h-10 font-medium"
:loading="loading"
/>
</Form> </Form>
</template> </template>
@@ -20,10 +17,10 @@
import type { FormSubmitEvent } from '@primevue/forms' import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms' import { Form } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod' import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import { ref } from 'vue' import { ref } from 'vue'
import PasswordFields from '@/components/dialog/content/signin/PasswordFields.vue' import PasswordFields from '@/components/dialog/content/signin/PasswordFields.vue'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { updatePasswordSchema } from '@/schemas/signInSchema' import { updatePasswordSchema } from '@/schemas/signInSchema'

View File

@@ -1,16 +1,14 @@
<template> <template>
<Button <Button variant="secondary" @click="openGitHubIssues">
:label="$t('g.findIssues')" <i class="pi pi-github" />
severity="secondary" {{ $t('g.findIssues') }}
icon="pi pi-github" </Button>
@click="openGitHubIssues"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed } from 'vue' import { computed } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
const props = defineProps<{ const props = defineProps<{

View File

@@ -10,15 +10,23 @@
<div> <div>
{{ $t('g.currentUser') }}: {{ userStore.currentUser?.username }} {{ $t('g.currentUser') }}: {{ userStore.currentUser?.username }}
</div> </div>
<Button icon="pi pi-sign-out" text @click="logout" /> <Button
class="text-inherit"
variant="textonly"
size="icon"
:aria-label="$t('menuLabels.Sign Out')"
@click="logout"
>
<i class="pi pi-sign-out" />
</Button>
</div> </div>
</Message> </Message>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Message from 'primevue/message' import Message from 'primevue/message'
import Button from '@/components/ui/button/Button.vue'
import { useUserStore } from '@/stores/userStore' import { useUserStore } from '@/stores/userStore'
const userStore = useUserStore() const userStore = useUserStore()

View File

@@ -23,24 +23,33 @@
<template #body="slotProps"> <template #body="slotProps">
<div class="actions invisible flex flex-row"> <div class="actions invisible flex flex-row">
<Button <Button
icon="pi pi-pencil" variant="textonly"
class="p-button-text" size="icon"
:aria-label="$t('g.edit')"
@click="editKeybinding(slotProps.data)" @click="editKeybinding(slotProps.data)"
/> >
<i class="pi pi-pencil" />
</Button>
<Button <Button
icon="pi pi-replay" variant="textonly"
class="p-button-text p-button-warn" size="icon"
:aria-label="$t('g.reset')"
:disabled=" :disabled="
!keybindingStore.isCommandKeybindingModified(slotProps.data.id) !keybindingStore.isCommandKeybindingModified(slotProps.data.id)
" "
@click="resetKeybinding(slotProps.data)" @click="resetKeybinding(slotProps.data)"
/> >
<i class="pi pi-replay" />
</Button>
<Button <Button
icon="pi pi-trash" variant="textonly"
class="p-button-text p-button-danger" size="icon"
:aria-label="$t('g.delete')"
:disabled="!slotProps.data.keybinding" :disabled="!slotProps.data.keybinding"
@click="removeKeybinding(slotProps.data)" @click="removeKeybinding(slotProps.data)"
/> >
<i class="pi pi-trash" />
</Button>
</div> </div>
</template> </template>
</Column> </Column>
@@ -104,30 +113,31 @@
</div> </div>
<template #footer> <template #footer>
<Button <Button
:label="existingKeybindingOnCombo ? 'Overwrite' : 'Save'" :variant="existingKeybindingOnCombo ? 'destructive' : 'primary'"
:icon="existingKeybindingOnCombo ? 'pi pi-pencil' : 'pi pi-check'"
:severity="existingKeybindingOnCombo ? 'warn' : undefined"
autofocus autofocus
@click="saveKeybinding" @click="saveKeybinding"
/> >
<i
:class="existingKeybindingOnCombo ? 'pi pi-pencil' : 'pi pi-check'"
/>
{{ existingKeybindingOnCombo ? $t('g.overwrite') : $t('g.save') }}
</Button>
</template> </template>
</Dialog> </Dialog>
<Button <Button
v-tooltip="$t('g.resetAllKeybindingsTooltip')" v-tooltip="$t('g.resetAllKeybindingsTooltip')"
class="mt-4" class="mt-4 w-full"
:label="$t('g.resetAll')" variant="destructive-textonly"
icon="pi pi-replay"
severity="danger"
fluid
text
@click="resetAllKeybindings" @click="resetAllKeybindings"
/> >
<i class="pi pi-replay" />
{{ $t('g.resetAll') }}
</Button>
</PanelTemplate> </PanelTemplate>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { FilterMatchMode } from '@primevue/core/api' import { FilterMatchMode } from '@primevue/core/api'
import Button from 'primevue/button'
import Column from 'primevue/column' import Column from 'primevue/column'
import DataTable from 'primevue/datatable' import DataTable from 'primevue/datatable'
import Dialog from 'primevue/dialog' import Dialog from 'primevue/dialog'
@@ -139,6 +149,7 @@ import { computed, ref, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import SearchBox from '@/components/common/SearchBox.vue' import SearchBox from '@/components/common/SearchBox.vue'
import Button from '@/components/ui/button/Button.vue'
import { useKeybindingService } from '@/services/keybindingService' import { useKeybindingService } from '@/services/keybindingService'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'
import { import {

View File

@@ -17,10 +17,11 @@
<Skeleton v-if="loading" width="2rem" height="2rem" /> <Skeleton v-if="loading" width="2rem" height="2rem" />
<Button <Button
v-else-if="isActiveSubscription" v-else-if="isActiveSubscription"
:label="$t('credits.purchaseCredits')"
:loading="loading" :loading="loading"
@click="handlePurchaseCreditsClick" @click="handlePurchaseCreditsClick"
/> >
{{ $t('credits.purchaseCredits') }}
</Button>
</div> </div>
<div class="flex flex-row items-center"> <div class="flex flex-row items-center">
<Skeleton <Skeleton
@@ -33,25 +34,26 @@
{{ $t('credits.lastUpdated') }}: {{ formattedLastUpdateTime }} {{ $t('credits.lastUpdated') }}: {{ formattedLastUpdateTime }}
</div> </div>
<Button <Button
icon="pi pi-refresh" variant="muted-textonly"
text size="icon-sm"
size="small" :aria-label="$t('g.refresh')"
severity="secondary"
@click="() => authActions.fetchBalance()" @click="() => authActions.fetchBalance()"
/> >
<i class="pi pi-refresh" />
</Button>
</div> </div>
</div> </div>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<h3>{{ $t('credits.activity') }}</h3> <h3>{{ $t('credits.activity') }}</h3>
<Button <Button
:label="$t('credits.invoiceHistory')" variant="muted-textonly"
text
severity="secondary"
icon="pi pi-arrow-up-right"
:loading="loading" :loading="loading"
@click="handleCreditsHistoryClick" @click="handleCreditsHistoryClick"
/> >
<i class="pi pi-arrow-up-right" />
{{ $t('credits.invoiceHistory') }}
</Button>
</div> </div>
<template v-if="creditHistory.length > 0"> <template v-if="creditHistory.length > 0">
@@ -86,34 +88,24 @@
<UsageLogsTable ref="usageLogsTableRef" /> <UsageLogsTable ref="usageLogsTableRef" />
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<Button <Button variant="muted-textonly" @click="handleFaqClick">
:label="$t('credits.faqs')" <i class="pi pi-question-circle" />
text {{ $t('credits.faqs') }}
severity="secondary" </Button>
icon="pi pi-question-circle" <Button variant="muted-textonly" @click="handleOpenPartnerNodesInfo">
@click="handleFaqClick" <i class="pi pi-question-circle" />
/> {{ $t('subscription.partnerNodesCredits') }}
<Button </Button>
:label="$t('subscription.partnerNodesCredits')" <Button variant="muted-textonly" @click="handleMessageSupport">
text <i class="pi pi-comments" />
severity="secondary" {{ $t('credits.messageSupport') }}
icon="pi pi-question-circle" </Button>
@click="handleOpenPartnerNodesInfo"
/>
<Button
:label="$t('credits.messageSupport')"
text
severity="secondary"
icon="pi pi-comments"
@click="handleMessageSupport"
/>
</div> </div>
</div> </div>
</TabPanel> </TabPanel>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Column from 'primevue/column' import Column from 'primevue/column'
import DataTable from 'primevue/datatable' import DataTable from 'primevue/datatable'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
@@ -123,6 +115,7 @@ import { computed, ref, watch } from 'vue'
import UserCredit from '@/components/common/UserCredit.vue' import UserCredit from '@/components/common/UserCredit.vue'
import UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue' import UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { useExternalLink } from '@/composables/useExternalLink' import { useExternalLink } from '@/composables/useExternalLink'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription' import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'

View File

@@ -1,7 +1,7 @@
import { createTestingPinia } from '@pinia/testing' import { createTestingPinia } from '@pinia/testing'
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import Badge from 'primevue/badge' import Badge from 'primevue/badge'
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import Column from 'primevue/column' import Column from 'primevue/column'
import PrimeVue from 'primevue/config' import PrimeVue from 'primevue/config'
import DataTable from 'primevue/datatable' import DataTable from 'primevue/datatable'

View File

@@ -78,9 +78,12 @@
} }
} }
}" }"
icon="pi pi-info-circle" variant="textonly"
class="p-button-text p-button-sm" size="icon-sm"
/> :aria-label="$t('credits.additionalInfo')"
>
<i class="pi pi-info-circle" />
</Button>
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@@ -89,13 +92,13 @@
<script setup lang="ts"> <script setup lang="ts">
import Badge from 'primevue/badge' import Badge from 'primevue/badge'
import Button from 'primevue/button'
import Column from 'primevue/column' import Column from 'primevue/column'
import DataTable from 'primevue/datatable' import DataTable from 'primevue/datatable'
import Message from 'primevue/message' import Message from 'primevue/message'
import ProgressSpinner from 'primevue/progressspinner' import ProgressSpinner from 'primevue/progressspinner'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import type { AuditLog } from '@/services/customerEventsService' import type { AuditLog } from '@/services/customerEventsService'
import { import {

View File

@@ -44,11 +44,12 @@
value: $t('userSettings.updatePassword'), value: $t('userSettings.updatePassword'),
showDelay: 300 showDelay: 300
}" }"
icon="pi pi-pen-to-square" variant="muted-textonly"
severity="secondary" size="icon-sm"
text
@click="dialogService.showUpdatePasswordDialog()" @click="dialogService.showUpdatePasswordDialog()"
/> >
<i class="pi pi-pen-to-square" />
</Button>
</div> </div>
</div> </div>
@@ -58,21 +59,18 @@
style="--pc-spinner-color: #000" style="--pc-spinner-color: #000"
/> />
<div v-else class="mt-4 flex flex-col gap-2"> <div v-else class="mt-4 flex flex-col gap-2">
<Button <Button class="w-32" variant="secondary" @click="handleSignOut">
class="w-32" <i class="pi pi-sign-out" />
severity="secondary" {{ $t('auth.signOut.signOut') }}
:label="$t('auth.signOut.signOut')" </Button>
icon="pi pi-sign-out"
@click="handleSignOut"
/>
<Button <Button
v-if="!isApiKeyLogin" v-if="!isApiKeyLogin"
class="w-fit" class="w-fit"
variant="text" variant="destructive-textonly"
severity="danger"
:label="$t('auth.deleteAccount.deleteAccount')"
@click="handleDeleteAccount" @click="handleDeleteAccount"
/> >
{{ $t('auth.deleteAccount.deleteAccount') }}
</Button>
</div> </div>
</div> </div>
@@ -84,24 +82,25 @@
<Button <Button
class="w-52" class="w-52"
severity="primary" variant="primary"
:loading="loading" :loading="loading"
:label="$t('auth.login.signInOrSignUp')"
icon="pi pi-user"
@click="handleSignIn" @click="handleSignIn"
/> >
<i class="pi pi-user" />
{{ $t('auth.login.signInOrSignUp') }}
</Button>
</div> </div>
</div> </div>
</TabPanel> </TabPanel>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Divider from 'primevue/divider' import Divider from 'primevue/divider'
import ProgressSpinner from 'primevue/progressspinner' import ProgressSpinner from 'primevue/progressspinner'
import TabPanel from 'primevue/tabpanel' import TabPanel from 'primevue/tabpanel'
import UserAvatar from '@/components/common/UserAvatar.vue' import UserAvatar from '@/components/common/UserAvatar.vue'
import Button from '@/components/ui/button/Button.vue'
import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { useDialogService } from '@/services/dialogService' import { useDialogService } from '@/services/dialogService'

View File

@@ -1,7 +1,7 @@
import { Form } from '@primevue/forms' import { Form } from '@primevue/forms'
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import PrimeVue from 'primevue/config' import PrimeVue from 'primevue/config'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import Message from 'primevue/message' import Message from 'primevue/message'
@@ -99,9 +99,10 @@ describe('ApiKeyForm', () => {
) )
await wrapper.find('form').trigger('submit') await wrapper.find('form').trigger('submit')
const submitButton = wrapper const buttons = wrapper.findAllComponents(Button)
.findAllComponents(Button) const submitButton = buttons.find(
.find((btn) => btn.text() === 'Save') (btn) => btn.attributes('type') === 'submit'
)
expect(submitButton?.props('loading')).toBe(true) expect(submitButton?.props('loading')).toBe(true)
}) })

View File

@@ -67,10 +67,15 @@
</div> </div>
<div class="mt-4 flex items-center justify-between"> <div class="mt-4 flex items-center justify-between">
<Button type="button" link @click="$emit('back')"> <Button type="button" variant="textonly" @click="$emit('back')">
{{ t('g.back') }} {{ t('g.back') }}
</Button> </Button>
<Button type="submit" :loading="loading" :disabled="loading"> <Button
type="submit"
variant="primary"
:loading="loading"
:disabled="loading"
>
{{ t('g.save') }} {{ t('g.save') }}
</Button> </Button>
</div> </div>
@@ -82,12 +87,12 @@
import type { FormSubmitEvent } from '@primevue/forms' import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms' import { Form } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod' import { zodResolver } from '@primevue/forms/resolvers/zod'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import Message from 'primevue/message' import Message from 'primevue/message'
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { getComfyPlatformBaseUrl } from '@/config/comfyApi' import { getComfyPlatformBaseUrl } from '@/config/comfyApi'
import { import {
configValueOrDefault, configValueOrDefault,

View File

@@ -1,7 +1,7 @@
import { Form } from '@primevue/forms' import { Form } from '@primevue/forms'
import type { VueWrapper } from '@vue/test-utils' import type { VueWrapper } from '@vue/test-utils'
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import PrimeVue from 'primevue/config' import PrimeVue from 'primevue/config'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import Password from 'primevue/password' import Password from 'primevue/password'

View File

@@ -64,10 +64,11 @@
<Button <Button
v-else v-else
type="submit" type="submit"
:label="t('auth.login.loginButton')"
class="mt-4 h-10 font-medium" class="mt-4 h-10 font-medium"
:disabled="!$form.valid" :disabled="!$form.valid"
/> >
{{ t('auth.login.loginButton') }}
</Button>
</Form> </Form>
</template> </template>
@@ -76,7 +77,6 @@ import type { FormSubmitEvent } from '@primevue/forms'
import { Form } from '@primevue/forms' import { Form } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod' import { zodResolver } from '@primevue/forms/resolvers/zod'
import { useThrottleFn } from '@vueuse/core' import { useThrottleFn } from '@vueuse/core'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import Password from 'primevue/password' import Password from 'primevue/password'
import ProgressSpinner from 'primevue/progressspinner' import ProgressSpinner from 'primevue/progressspinner'
@@ -84,6 +84,7 @@ import { useToast } from 'primevue/usetoast'
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions' import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { signInSchema } from '@/schemas/signInSchema' import { signInSchema } from '@/schemas/signInSchema'
import type { SignInData } from '@/schemas/signInSchema' import type { SignInData } from '@/schemas/signInSchema'

View File

@@ -33,10 +33,11 @@
<Button <Button
v-else v-else
type="submit" type="submit"
:label="t('auth.signup.signUpButton')"
class="mt-4 h-10 font-medium" class="mt-4 h-10 font-medium"
:disabled="!$form.valid" :disabled="!$form.valid"
/> >
{{ t('auth.signup.signUpButton') }}
</Button>
</Form> </Form>
</template> </template>
@@ -45,12 +46,12 @@ import type { FormSubmitEvent } from '@primevue/forms'
import { Form, FormField } from '@primevue/forms' import { Form, FormField } from '@primevue/forms'
import { zodResolver } from '@primevue/forms/resolvers/zod' import { zodResolver } from '@primevue/forms/resolvers/zod'
import { useThrottleFn } from '@vueuse/core' import { useThrottleFn } from '@vueuse/core'
import Button from 'primevue/button'
import InputText from 'primevue/inputtext' import InputText from 'primevue/inputtext'
import ProgressSpinner from 'primevue/progressspinner' import ProgressSpinner from 'primevue/progressspinner'
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { signUpSchema } from '@/schemas/signInSchema' import { signUpSchema } from '@/schemas/signInSchema'
import type { SignUpData } from '@/schemas/signInSchema' import type { SignUpData } from '@/schemas/signInSchema'
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore' import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'

View File

@@ -1,21 +1,19 @@
<template> <template>
<Button <Button
ref="buttonRef" ref="buttonRef"
severity="secondary" variant="secondary"
class="group h-8 rounded-none! bg-comfy-menu-bg p-0 transition-none! hover:rounded-lg! hover:bg-interface-button-hover-surface!" class="group h-8 rounded-none! bg-comfy-menu-bg p-0 transition-none! hover:rounded-lg! hover:bg-interface-button-hover-surface!"
:style="buttonStyles" :style="buttonStyles"
@click="toggle" @click="toggle"
> >
<template #default> <div class="flex items-center gap-1 pr-0.5">
<div class="flex items-center gap-1 pr-0.5"> <div
<div class="rounded-lg bg-interface-panel-selected-surface p-2 group-hover:bg-interface-button-hover-surface"
class="rounded-lg bg-interface-panel-selected-surface p-2 group-hover:bg-interface-button-hover-surface" >
> <i :class="currentModeIcon" class="block h-4 w-4" />
<i :class="currentModeIcon" class="block h-4 w-4" />
</div>
<i class="icon-[lucide--chevron-down] block h-4 w-4 pr-1.5" />
</div> </div>
</template> <i class="icon-[lucide--chevron-down] block h-4 w-4 pr-1.5" />
</div>
</Button> </Button>
<Popover <Popover
@@ -56,10 +54,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Popover from 'primevue/popover' import Popover from 'primevue/popover'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -24,22 +24,18 @@
<Button <Button
v-tooltip.top="fitViewTooltip" v-tooltip.top="fitViewTooltip"
severity="secondary" variant="secondary"
icon="pi pi-expand"
:aria-label="fitViewTooltip" :aria-label="fitViewTooltip"
:style="stringifiedMinimapStyles.buttonStyles" :style="stringifiedMinimapStyles.buttonStyles"
class="h-8 w-8 bg-comfy-menu-bg p-0 hover:bg-interface-button-hover-surface!" class="h-8 w-8 bg-comfy-menu-bg p-0 hover:bg-interface-button-hover-surface!"
@click="() => commandStore.execute('Comfy.Canvas.FitView')" @click="() => commandStore.execute('Comfy.Canvas.FitView')"
> >
<template #icon> <i class="icon-[lucide--focus] h-4 w-4" />
<i class="icon-[lucide--focus] h-4 w-4" />
</template>
</Button> </Button>
<Button <Button
v-tooltip.top="t('zoomControls.label')" v-tooltip.top="t('zoomControls.label')"
severity="secondary" variant="secondary"
:label="t('zoomControls.label')"
:class="zoomButtonClass" :class="zoomButtonClass"
:aria-label="t('zoomControls.label')" :aria-label="t('zoomControls.label')"
data-testid="zoom-controls-button" data-testid="zoom-controls-button"
@@ -56,16 +52,14 @@
<Button <Button
v-tooltip.top="minimapTooltip" v-tooltip.top="minimapTooltip"
severity="secondary" variant="secondary"
:aria-label="minimapTooltip" :aria-label="minimapTooltip"
data-testid="toggle-minimap-button" data-testid="toggle-minimap-button"
:style="stringifiedMinimapStyles.buttonStyles" :style="stringifiedMinimapStyles.buttonStyles"
:class="minimapButtonClass" :class="minimapButtonClass"
@click="onMinimapToggleClick" @click="onMinimapToggleClick"
> >
<template #icon> <i class="icon-[lucide--map] h-4 w-4" />
<i class="icon-[lucide--map] h-4 w-4" />
</template>
</Button> </Button>
<Button <Button
@@ -77,27 +71,25 @@
} }
} }
}" }"
severity="secondary" variant="secondary"
:class="linkVisibleClass" :class="linkVisibleClass"
:aria-label="linkVisibilityAriaLabel" :aria-label="linkVisibilityAriaLabel"
data-testid="toggle-link-visibility-button" data-testid="toggle-link-visibility-button"
:style="stringifiedMinimapStyles.buttonStyles" :style="stringifiedMinimapStyles.buttonStyles"
@click="onLinkVisibilityToggleClick" @click="onLinkVisibilityToggleClick"
> >
<template #icon> <i class="icon-[lucide--route-off] h-4 w-4" />
<i class="icon-[lucide--route-off] h-4 w-4" />
</template>
</Button> </Button>
</ButtonGroup> </ButtonGroup>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import ButtonGroup from 'primevue/buttongroup' import ButtonGroup from 'primevue/buttongroup'
import { computed, onBeforeUnmount, onMounted } from 'vue' import { computed, onBeforeUnmount, onMounted } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useZoomControls } from '@/composables/useZoomControls' import { useZoomControls } from '@/composables/useZoomControls'
import { LiteGraph } from '@/lib/litegraph/src/litegraph' import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'

View File

@@ -4,21 +4,18 @@
value: $t('commands.Comfy_Canvas_ToggleSelectedNodes_Bypass.label'), value: $t('commands.Comfy_Canvas_ToggleSelectedNodes_Bypass.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_Canvas_ToggleSelectedNodes_Bypass.label')"
data-testid="bypass-button" data-testid="bypass-button"
class="hover:bg-secondary-background" class="hover:bg-secondary-background"
@click="toggleBypass" @click="toggleBypass"
> >
<template #icon> <i class="icon-[lucide--redo-dot] size-4" />
<i class="icon-[lucide--redo-dot] h-4 w-4" />
</template>
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'
const commandStore = useCommandStore() const commandStore = useCommandStore()

View File

@@ -6,19 +6,13 @@
showDelay: 1000 showDelay: 1000
}" }"
data-testid="color-picker-button" data-testid="color-picker-button"
severity="secondary" variant="muted-textonly"
text :aria-label="t('g.color')"
@click="() => (showColorPicker = !showColorPicker)" @click="() => (showColorPicker = !showColorPicker)"
> >
<div class="flex items-center gap-1 px-0"> <div class="flex items-center gap-1 px-0">
<i <i class="pi pi-circle-fill" :style="{ color: currentColor ?? '' }" />
class="pi pi-circle-fill h-4 w-4" <i class="icon-[lucide--chevron-down]" />
:style="{ color: currentColor ?? '' }"
/>
<i
class="pi pi-chevron-down h-4 w-4 py-1"
:style="{ fontSize: '0.5rem' }"
/>
</div> </div>
</Button> </Button>
<div <div
@@ -48,12 +42,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import SelectButton from 'primevue/selectbutton' import SelectButton from 'primevue/selectbutton'
import type { Raw } from 'vue' import type { Raw } from 'vue'
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import type { import type {
ColorOption as CanvasColorOption, ColorOption as CanvasColorOption,
Positionable Positionable

View File

@@ -4,15 +4,15 @@
value: $t('commands.Comfy_Graph_EditSubgraphWidgets.label'), value: $t('commands.Comfy_Graph_EditSubgraphWidgets.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_Graph_EditSubgraphWidgets.label')"
icon="icon-[lucide--settings-2]"
@click="handleClick" @click="handleClick"
/> >
<i class="icon-[lucide--settings-2]" />
</Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore' import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
const rightSidePanelStore = useRightSidePanelStore() const rightSidePanelStore = useRightSidePanelStore()

View File

@@ -5,14 +5,12 @@
value: $t('commands.Comfy_Graph_UnpackSubgraph.label'), value: $t('commands.Comfy_Graph_UnpackSubgraph.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
:aria-label="$t('commands.Comfy_Graph_UnpackSubgraph.label')"
data-testid="convert-to-subgraph-button" data-testid="convert-to-subgraph-button"
text
@click="() => commandStore.execute('Comfy.Graph.UnpackSubgraph')" @click="() => commandStore.execute('Comfy.Graph.UnpackSubgraph')"
> >
<template #icon> <i class="icon-[lucide--expand] size-4" />
<i class="icon-[lucide--expand] h-4 w-4" />
</template>
</Button> </Button>
<Button <Button
v-else-if="isConvertVisible" v-else-if="isConvertVisible"
@@ -20,21 +18,20 @@
value: $t('commands.Comfy_Graph_ConvertToSubgraph.label'), value: $t('commands.Comfy_Graph_ConvertToSubgraph.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
size="icon"
:aria-label="$t('commands.Comfy_Graph_ConvertToSubgraph.label')"
data-testid="convert-to-subgraph-button" data-testid="convert-to-subgraph-button"
text
@click="() => commandStore.execute('Comfy.Graph.ConvertToSubgraph')" @click="() => commandStore.execute('Comfy.Graph.ConvertToSubgraph')"
> >
<template #icon> <i class="icon-[lucide--shrink] size-4" />
<i class="icon-[lucide--shrink]" />
</template>
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed } from 'vue' import { computed } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useSelectionState } from '@/composables/graph/useSelectionState' import { useSelectionState } from '@/composables/graph/useSelectionState'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -5,19 +5,19 @@
value: $t('commands.Comfy_Canvas_DeleteSelectedItems.label'), value: $t('commands.Comfy_Canvas_DeleteSelectedItems.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_Canvas_DeleteSelectedItems.label')"
icon-class="w-4 h-4"
icon="pi pi-trash"
data-testid="delete-button" data-testid="delete-button"
@click="() => commandStore.execute('Comfy.Canvas.DeleteSelectedItems')" @click="() => commandStore.execute('Comfy.Canvas.DeleteSelectedItems')"
/> >
<i class="icon-[lucide--trash-2]" />
</Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed } from 'vue' import { computed } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useSelectionState } from '@/composables/graph/useSelectionState' import { useSelectionState } from '@/composables/graph/useSelectionState'
import type { Positionable } from '@/lib/litegraph/src/interfaces' import type { Positionable } from '@/lib/litegraph/src/interfaces'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -4,21 +4,21 @@
value: t('selectionToolbox.executeButton.tooltip'), value: t('selectionToolbox.executeButton.tooltip'),
showDelay: 1000 showDelay: 1000
}" }"
class="size-8 bg-primary-background text-white p-0" variant="primary"
text :aria-label="t('selectionToolbox.executeButton.tooltip')"
@mouseenter="() => handleMouseEnter()" @mouseenter="() => handleMouseEnter()"
@mouseleave="() => handleMouseLeave()" @mouseleave="() => handleMouseLeave()"
@click="handleClick" @click="handleClick"
> >
<i class="icon-[lucide--play] size-4" /> <i class="icon-[lucide--play]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useSelectionState } from '@/composables/graph/useSelectionState' import { useSelectionState } from '@/composables/graph/useSelectionState'
import type { LGraphNode } from '@/lib/litegraph/src/litegraph' import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'

View File

@@ -5,17 +5,20 @@
st(`commands.${normalizeI18nKey(command.id)}.label`, '') || undefined, st(`commands.${normalizeI18nKey(command.id)}.label`, '') || undefined,
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="st(`commands.${normalizeI18nKey(command.id)}.label`, '')"
icon-class="w-4 h-4"
:icon="typeof command.icon === 'function' ? command.icon() : command.icon"
@click="() => commandStore.execute(command.id)" @click="() => commandStore.execute(command.id)"
/> >
<i
:class="[
typeof command.icon === 'function' ? command.icon() : command.icon
]"
/>
</Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { st } from '@/i18n' import { st } from '@/i18n'
import type { ComfyCommand } from '@/stores/commandStore' import type { ComfyCommand } from '@/stores/commandStore'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -4,18 +4,16 @@
value: $t('g.frameNodes'), value: $t('g.frameNodes'),
showDelay: 1000 showDelay: 1000
}" }"
class="frame-nodes-button" variant="muted-textonly"
text :aria-label="$t('g.frameNodes')"
severity="secondary"
@click="frameNodes" @click="frameNodes"
> >
<i class="icon-[lucide--frame] h-4 w-4" /> <i class="icon-[lucide--frame]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useFrameNodes } from '@/composables/graph/useFrameNodes' import { useFrameNodes } from '@/composables/graph/useFrameNodes'
const { frameNodes } = useFrameNodes() const { frameNodes } = useFrameNodes()

View File

@@ -5,17 +5,16 @@
showDelay: 1000 showDelay: 1000
}" }"
data-testid="info-button" data-testid="info-button"
text variant="muted-textonly"
severity="secondary" :aria-label="$t('g.info')"
@click="onInfoClick" @click="onInfoClick"
> >
<i class="icon-[lucide--info] size-4" /> <i class="icon-[lucide--info]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore' import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'

View File

@@ -4,17 +4,16 @@
value: $t('commands.Comfy_3DViewer_Open3DViewer.label'), value: $t('commands.Comfy_3DViewer_Open3DViewer.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_3DViewer_Open3DViewer.label')"
icon="pi pi-pencil"
icon-class="w-4 h-4"
@click="open3DViewer" @click="open3DViewer"
/> >
<i class="icon-[lucide--pencil]" />
</Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'
const commandStore = useCommandStore() const commandStore = useCommandStore()

View File

@@ -5,17 +5,16 @@
value: $t('commands.Comfy_MaskEditor_OpenMaskEditor.label'), value: $t('commands.Comfy_MaskEditor_OpenMaskEditor.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_MaskEditor_OpenMaskEditor.label')"
@click="openMaskEditor" @click="openMaskEditor"
> >
<i-comfy:mask class="!h-4 !w-4" /> <i class="icon-[comfy--mask]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { useSelectionState } from '@/composables/graph/useSelectionState' import { useSelectionState } from '@/composables/graph/useSelectionState'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -5,18 +5,16 @@
showDelay: 1000 showDelay: 1000
}" }"
data-testid="more-options-button" data-testid="more-options-button"
text variant="muted-textonly"
class="h-8 w-8 px-0" :aria-label="$t('g.moreOptions')"
severity="secondary"
@click="handleClick" @click="handleClick"
> >
<i class="icon-[lucide--more-vertical] h-4 w-4" /> <i class="icon-[lucide--more-vertical]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { toggleNodeOptions } from '@/composables/graph/useMoreOptionsMenu' import { toggleNodeOptions } from '@/composables/graph/useMoreOptionsMenu'
const handleClick = (event: Event) => { const handleClick = (event: Event) => {

View File

@@ -2,19 +2,19 @@
<Button <Button
v-show="isRefreshable" v-show="isRefreshable"
v-tooltip.top="t('g.refreshNode')" v-tooltip.top="t('g.refreshNode')"
severity="secondary" variant="muted-textonly"
text :aria-label="t('g.refreshNode')"
data-testid="refresh-button" data-testid="refresh-button"
@click="refreshSelected" @click="refreshSelected"
> >
<i class="icon-[lucide--refresh-cw] h-4 w-4" /> <i class="icon-[lucide--refresh-cw]" />
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '@/components/ui/button/Button.vue'
import { useRefreshableSelection } from '@/composables/useRefreshableSelection' import { useRefreshableSelection } from '@/composables/useRefreshableSelection'
const { t } = useI18n() const { t } = useI18n()

View File

@@ -5,20 +5,18 @@
value: $t('commands.Comfy_PublishSubgraph.label'), value: $t('commands.Comfy_PublishSubgraph.label'),
showDelay: 1000 showDelay: 1000
}" }"
severity="secondary" variant="muted-textonly"
text :aria-label="$t('commands.Comfy_PublishSubgraph.label')"
@click="() => commandStore.execute('Comfy.PublishSubgraph')" @click="() => commandStore.execute('Comfy.PublishSubgraph')"
> >
<template #icon> <i class="icon-[lucide--book-open]" />
<i class="icon-[lucide--book-open]" />
</template>
</Button> </Button>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed } from 'vue' import { computed } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { SubgraphNode } from '@/lib/litegraph/src/litegraph' import { SubgraphNode } from '@/lib/litegraph/src/litegraph'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useCommandStore } from '@/stores/commandStore' import { useCommandStore } from '@/stores/commandStore'

View File

@@ -7,7 +7,13 @@
@wheel.stop @wheel.stop
> >
<div class="show-menu relative"> <div class="show-menu relative">
<Button class="p-button-rounded p-button-text" @click="toggleMenu"> <Button
variant="textonly"
size="icon"
:aria-label="$t('menu.showMenu')"
class="rounded-full"
@click="toggleMenu"
>
<i class="pi pi-bars text-lg text-white" /> <i class="pi pi-bars text-lg text-white" />
</Button> </Button>
@@ -19,8 +25,13 @@
<Button <Button
v-for="category in availableCategories" v-for="category in availableCategories"
:key="category" :key="category"
class="p-button-text flex w-full items-center justify-start" variant="textonly"
:class="{ 'bg-smoke-600': activeCategory === category }" :class="
cn(
'flex w-full items-center justify-start',
activeCategory === category && 'bg-smoke-600'
)
"
@click="selectCategory(category)" @click="selectCategory(category)"
> >
<i :class="getCategoryIcon(category)" /> <i :class="getCategoryIcon(category)" />
@@ -72,7 +83,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import CameraControls from '@/components/load3d/controls/CameraControls.vue' import CameraControls from '@/components/load3d/controls/CameraControls.vue'
@@ -80,12 +90,14 @@ import ExportControls from '@/components/load3d/controls/ExportControls.vue'
import LightControls from '@/components/load3d/controls/LightControls.vue' import LightControls from '@/components/load3d/controls/LightControls.vue'
import ModelControls from '@/components/load3d/controls/ModelControls.vue' import ModelControls from '@/components/load3d/controls/ModelControls.vue'
import SceneControls from '@/components/load3d/controls/SceneControls.vue' import SceneControls from '@/components/load3d/controls/SceneControls.vue'
import Button from '@/components/ui/button/Button.vue'
import type { import type {
CameraConfig, CameraConfig,
LightConfig, LightConfig,
ModelConfig, ModelConfig,
SceneConfig SceneConfig
} from '@/extensions/core/load3d/interfaces' } from '@/extensions/core/load3d/interfaces'
import { cn } from '@/utils/tailwindUtil'
const { isSplatModel = false, isPlyModel = false } = defineProps<{ const { isSplatModel = false, isPlyModel = false } = defineProps<{
isSplatModel?: boolean isSplatModel?: boolean

View File

@@ -72,12 +72,10 @@
<div class="p-4"> <div class="p-4">
<div class="flex gap-2"> <div class="flex gap-2">
<Button <Button variant="secondary" @click="handleCancel">
icon="pi pi-times" <i class="pi pi-times" />
severity="secondary" {{ t('g.cancel') }}
:label="t('g.cancel')" </Button>
@click="handleCancel"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -85,7 +83,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { onBeforeUnmount, onMounted, ref, toRaw } from 'vue' import { onBeforeUnmount, onMounted, ref, toRaw } from 'vue'
import CameraControls from '@/components/load3d/controls/viewer/ViewerCameraControls.vue' import CameraControls from '@/components/load3d/controls/viewer/ViewerCameraControls.vue'
@@ -93,6 +90,7 @@ import ExportControls from '@/components/load3d/controls/viewer/ViewerExportCont
import LightControls from '@/components/load3d/controls/viewer/ViewerLightControls.vue' import LightControls from '@/components/load3d/controls/viewer/ViewerLightControls.vue'
import ModelControls from '@/components/load3d/controls/viewer/ViewerModelControls.vue' import ModelControls from '@/components/load3d/controls/viewer/ViewerModelControls.vue'
import SceneControls from '@/components/load3d/controls/viewer/ViewerSceneControls.vue' import SceneControls from '@/components/load3d/controls/viewer/ViewerSceneControls.vue'
import Button from '@/components/ui/button/Button.vue'
import { useLoad3dDrag } from '@/composables/useLoad3dDrag' import { useLoad3dDrag } from '@/composables/useLoad3dDrag'
import { useLoad3dViewer } from '@/composables/useLoad3dViewer' import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
import { t } from '@/i18n' import { t } from '@/i18n'

View File

@@ -3,7 +3,13 @@
v-if="animations && animations.length > 0" v-if="animations && animations.length > 0"
class="pointer-events-auto absolute top-0 left-0 z-10 flex w-full items-center justify-center gap-2 pt-2" class="pointer-events-auto absolute top-0 left-0 z-10 flex w-full items-center justify-center gap-2 pt-2"
> >
<Button class="p-button-rounded p-button-text" @click="togglePlay"> <Button
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="$t('g.playPause')"
@click="togglePlay"
>
<i <i
:class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-lg text-white']" :class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-lg text-white']"
/> />
@@ -28,9 +34,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Select from 'primevue/select' import Select from 'primevue/select'
import Button from '@/components/ui/button/Button.vue'
type Animation = { name: string; index: number } type Animation = { name: string; index: number }
const animations = defineModel<Animation[]>('animations') const animations = defineModel<Animation[]>('animations')

View File

@@ -1,13 +1,17 @@
<template> <template>
<div class="flex flex-col"> <div class="flex flex-col">
<Button class="p-button-rounded p-button-text" @click="switchCamera"> <Button
<i v-tooltip.right="{
v-tooltip.right="{ value: $t('load3d.switchCamera'),
value: $t('load3d.switchCamera'), showDelay: 300
showDelay: 300 }"
}" size="icon"
:class="['pi', 'pi-camera', 'text-lg text-white']" variant="textonly"
/> class="rounded-full"
:aria-label="$t('load3d.switchCamera')"
@click="switchCamera"
>
<i :class="['pi', 'pi-camera', 'text-lg text-white']" />
</Button> </Button>
<PopupSlider <PopupSlider
v-if="showFOVButton" v-if="showFOVButton"
@@ -18,10 +22,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed } from 'vue' import { computed } from 'vue'
import PopupSlider from '@/components/load3d/controls/PopupSlider.vue' import PopupSlider from '@/components/load3d/controls/PopupSlider.vue'
import Button from '@/components/ui/button/Button.vue'
import type { CameraType } from '@/extensions/core/load3d/interfaces' import type { CameraType } from '@/extensions/core/load3d/interfaces'
const cameraType = defineModel<CameraType>('cameraType') const cameraType = defineModel<CameraType>('cameraType')

View File

@@ -2,16 +2,17 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div class="show-export-formats relative"> <div class="show-export-formats relative">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
value: $t('load3d.exportModel'),
showDelay: 300
}"
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="$t('load3d.exportModel')"
@click="toggleExportFormats" @click="toggleExportFormats"
> >
<i <i class="pi pi-download text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.exportModel'),
showDelay: 300
}"
class="pi pi-download text-lg text-white"
/>
</Button> </Button>
<div <div
v-show="showExportFormats" v-show="showExportFormats"
@@ -21,7 +22,8 @@
<Button <Button
v-for="format in exportFormats" v-for="format in exportFormats"
:key="format.value" :key="format.value"
class="p-button-text text-white" variant="textonly"
class="text-white"
@click="exportModel(format.value)" @click="exportModel(format.value)"
> >
{{ format.label }} {{ format.label }}
@@ -33,9 +35,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { onMounted, onUnmounted, ref } from 'vue' import { onMounted, onUnmounted, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'exportModel', format: string): void (e: 'exportModel', format: string): void
}>() }>()
@@ -48,17 +51,17 @@ const exportFormats = [
{ label: 'STL', value: 'stl' } { label: 'STL', value: 'stl' }
] ]
const toggleExportFormats = () => { function toggleExportFormats() {
showExportFormats.value = !showExportFormats.value showExportFormats.value = !showExportFormats.value
} }
const exportModel = (format: string) => { function exportModel(format: string) {
emit('exportModel', format) emit('exportModel', format)
showExportFormats.value = false showExportFormats.value = false
} }
const closeExportFormatsList = (e: MouseEvent) => { function closeExportFormatsList(e: MouseEvent) {
const target = e.target as HTMLElement const target = e.target as HTMLElement
if (!target.closest('.show-export-formats')) { if (!target.closest('.show-export-formats')) {

View File

@@ -2,16 +2,17 @@
<div class="flex flex-col"> <div class="flex flex-col">
<div v-if="showLightIntensityButton" class="show-light-intensity relative"> <div v-if="showLightIntensityButton" class="show-light-intensity relative">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
value: $t('load3d.lightIntensity'),
showDelay: 300
}"
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="$t('load3d.lightIntensity')"
@click="toggleLightIntensity" @click="toggleLightIntensity"
> >
<i <i class="pi pi-sun text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.lightIntensity'),
showDelay: 300
}"
class="pi pi-sun text-lg text-white"
/>
</Button> </Button>
<div <div
v-show="showLightIntensity" v-show="showLightIntensity"
@@ -31,10 +32,10 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Slider from 'primevue/slider' import Slider from 'primevue/slider'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import type { MaterialMode } from '@/extensions/core/load3d/interfaces' import type { MaterialMode } from '@/extensions/core/load3d/interfaces'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'
@@ -56,11 +57,11 @@ const lightAdjustmentIncrement = useSettingStore().get(
'Comfy.Load3D.LightAdjustmentIncrement' 'Comfy.Load3D.LightAdjustmentIncrement'
) )
const toggleLightIntensity = () => { function toggleLightIntensity() {
showLightIntensity.value = !showLightIntensity.value showLightIntensity.value = !showLightIntensity.value
} }
const closeLightSlider = (e: MouseEvent) => { function closeLightSlider(e: MouseEvent) {
const target = e.target as HTMLElement const target = e.target as HTMLElement
if (!target.closest('.show-light-intensity')) { if (!target.closest('.show-light-intensity')) {

View File

@@ -1,14 +1,18 @@
<template> <template>
<div class="flex flex-col"> <div class="flex flex-col">
<div class="show-up-direction relative"> <div class="show-up-direction relative">
<Button class="p-button-rounded p-button-text" @click="toggleUpDirection"> <Button
<i v-tooltip.right="{
v-tooltip.right="{ value: t('load3d.upDirection'),
value: t('load3d.upDirection'), showDelay: 300
showDelay: 300 }"
}" size="icon"
class="pi pi-arrow-up text-lg text-white" variant="textonly"
/> class="rounded-full"
:aria-label="t('load3d.upDirection')"
@click="toggleUpDirection"
>
<i class="pi pi-arrow-up text-lg text-white" />
</Button> </Button>
<div <div
v-show="showUpDirection" v-show="showUpDirection"
@@ -18,8 +22,10 @@
<Button <Button
v-for="direction in upDirections" v-for="direction in upDirections"
:key="direction" :key="direction"
class="p-button-text text-white" variant="textonly"
:class="{ 'bg-blue-500': upDirection === direction }" :class="
cn('text-white', upDirection === direction && 'bg-blue-500')
"
@click="selectUpDirection(direction)" @click="selectUpDirection(direction)"
> >
{{ direction.toUpperCase() }} {{ direction.toUpperCase() }}
@@ -30,16 +36,17 @@
<div v-if="!hideMaterialMode" class="show-material-mode relative"> <div v-if="!hideMaterialMode" class="show-material-mode relative">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
value: t('load3d.materialMode'),
showDelay: 300
}"
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="t('load3d.materialMode')"
@click="toggleMaterialMode" @click="toggleMaterialMode"
> >
<i <i class="pi pi-box text-lg text-white" />
v-tooltip.right="{
value: t('load3d.materialMode'),
showDelay: 300
}"
class="pi pi-box text-lg text-white"
/>
</Button> </Button>
<div <div
v-show="showMaterialMode" v-show="showMaterialMode"
@@ -49,8 +56,13 @@
<Button <Button
v-for="mode in materialModes" v-for="mode in materialModes"
:key="mode" :key="mode"
class="p-button-text whitespace-nowrap text-white" variant="textonly"
:class="{ 'bg-blue-500': materialMode === mode }" :class="
cn(
'whitespace-nowrap text-white',
materialMode === mode && 'bg-blue-500'
)
"
@click="selectMaterialMode(mode)" @click="selectMaterialMode(mode)"
> >
{{ formatMaterialMode(mode) }} {{ formatMaterialMode(mode) }}
@@ -62,14 +74,15 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed, onMounted, onUnmounted, ref } from 'vue' import { computed, onMounted, onUnmounted, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import type { import type {
MaterialMode, MaterialMode,
UpDirection UpDirection
} from '@/extensions/core/load3d/interfaces' } from '@/extensions/core/load3d/interfaces'
import { t } from '@/i18n' import { t } from '@/i18n'
import { cn } from '@/utils/tailwindUtil'
const { hideMaterialMode = false, isPlyModel = false } = defineProps<{ const { hideMaterialMode = false, isPlyModel = false } = defineProps<{
hideMaterialMode?: boolean hideMaterialMode?: boolean
@@ -108,31 +121,31 @@ const materialModes = computed(() => {
return modes return modes
}) })
const toggleUpDirection = () => { function toggleUpDirection() {
showUpDirection.value = !showUpDirection.value showUpDirection.value = !showUpDirection.value
showMaterialMode.value = false showMaterialMode.value = false
} }
const selectUpDirection = (direction: UpDirection) => { function selectUpDirection(direction: UpDirection) {
upDirection.value = direction upDirection.value = direction
showUpDirection.value = false showUpDirection.value = false
} }
const toggleMaterialMode = () => { function toggleMaterialMode() {
showMaterialMode.value = !showMaterialMode.value showMaterialMode.value = !showMaterialMode.value
showUpDirection.value = false showUpDirection.value = false
} }
const selectMaterialMode = (mode: MaterialMode) => { function selectMaterialMode(mode: MaterialMode) {
materialMode.value = mode materialMode.value = mode
showMaterialMode.value = false showMaterialMode.value = false
} }
const formatMaterialMode = (mode: MaterialMode) => { function formatMaterialMode(mode: MaterialMode) {
return t(`load3d.materialModes.${mode}`) return t(`load3d.materialModes.${mode}`)
} }
const closeSceneSlider = (e: MouseEvent) => { function closeSceneSlider(e: MouseEvent) {
const target = e.target as HTMLElement const target = e.target as HTMLElement
if (!target.closest('.show-up-direction')) { if (!target.closest('.show-up-direction')) {

View File

@@ -1,10 +1,14 @@
<template> <template>
<div class="relative show-slider"> <div class="relative show-slider">
<Button class="p-button-rounded p-button-text" @click="toggleSlider"> <Button
<i v-tooltip.right="{ value: tooltipText, showDelay: 300 }"
v-tooltip.right="{ value: tooltipText, showDelay: 300 }" size="icon"
:class="['pi', icon, 'text-lg text-white']" variant="textonly"
/> class="rounded-full"
:aria-label="tooltipText"
@click="toggleSlider"
>
<i :class="['pi', icon, 'text-lg text-white']" />
</Button> </Button>
<div <div
v-show="showSlider" v-show="showSlider"
@@ -22,10 +26,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Slider from 'primevue/slider' import Slider from 'primevue/slider'
import { onMounted, onUnmounted, ref } from 'vue' import { onMounted, onUnmounted, ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
const { const {
icon = 'pi-expand', icon = 'pi-expand',
min = 10, min = 10,

View File

@@ -2,20 +2,26 @@
<div class="relative rounded-lg bg-smoke-700/30"> <div class="relative rounded-lg bg-smoke-700/30">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
:class="{ value: isRecording
'p-button-danger': isRecording, ? $t('load3d.stopRecording')
'recording-button-blink': isRecording : $t('load3d.startRecording'),
showDelay: 300
}" }"
size="icon"
variant="textonly"
:class="
cn(
'rounded-full',
isRecording && 'text-red-500 recording-button-blink'
)
"
:aria-label="
isRecording ? $t('load3d.stopRecording') : $t('load3d.startRecording')
"
@click="toggleRecording" @click="toggleRecording"
> >
<i <i
v-tooltip.right="{
value: isRecording
? $t('load3d.stopRecording')
: $t('load3d.startRecording'),
showDelay: 300
}"
:class="[ :class="[
'pi', 'pi',
isRecording ? 'pi-circle-fill' : 'pi-video', isRecording ? 'pi-circle-fill' : 'pi-video',
@@ -26,30 +32,32 @@
<Button <Button
v-if="hasRecording && !isRecording" v-if="hasRecording && !isRecording"
class="p-button-rounded p-button-text" v-tooltip.right="{
value: $t('load3d.exportRecording'),
showDelay: 300
}"
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="$t('load3d.exportRecording')"
@click="handleExportRecording" @click="handleExportRecording"
> >
<i <i class="pi pi-download text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.exportRecording'),
showDelay: 300
}"
class="pi pi-download text-lg text-white"
/>
</Button> </Button>
<Button <Button
v-if="hasRecording && !isRecording" v-if="hasRecording && !isRecording"
class="p-button-rounded p-button-text" v-tooltip.right="{
value: $t('load3d.clearRecording'),
showDelay: 300
}"
size="icon"
variant="textonly"
class="rounded-full"
:aria-label="$t('load3d.clearRecording')"
@click="handleClearRecording" @click="handleClearRecording"
> >
<i <i class="pi pi-trash text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.clearRecording'),
showDelay: 300
}"
class="pi pi-trash text-lg text-white"
/>
</Button> </Button>
<div <div
@@ -63,7 +71,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { cn } from '@/utils/tailwindUtil'
const hasRecording = defineModel<boolean>('hasRecording') const hasRecording = defineModel<boolean>('hasRecording')
const isRecording = defineModel<boolean>('isRecording') const isRecording = defineModel<boolean>('isRecording')
@@ -76,7 +85,7 @@ const emit = defineEmits<{
(e: 'clearRecording'): void (e: 'clearRecording'): void
}>() }>()
const toggleRecording = () => { function toggleRecording() {
if (isRecording.value) { if (isRecording.value) {
emit('stopRecording') emit('stopRecording')
} else { } else {
@@ -84,15 +93,15 @@ const toggleRecording = () => {
} }
} }
const handleExportRecording = () => { function handleExportRecording() {
emit('exportRecording') emit('exportRecording')
} }
const handleClearRecording = () => { function handleClearRecording() {
emit('clearRecording') emit('clearRecording')
} }
const formatDuration = (seconds: number): string => { function formatDuration(seconds: number): string {
const minutes = Math.floor(seconds / 60) const minutes = Math.floor(seconds / 60)
const remainingSeconds = Math.floor(seconds % 60) const remainingSeconds = Math.floor(seconds % 60)
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}` return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`

View File

@@ -1,25 +1,29 @@
<template> <template>
<div class="flex flex-col"> <div class="flex flex-col">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{ value: $t('load3d.showGrid'), showDelay: 300 }"
:class="{ 'p-button-outlined': showGrid }" variant="textonly"
size="icon"
:class="cn('rounded-full', showGrid && 'ring-2 ring-white/50')"
:aria-label="$t('load3d.showGrid')"
@click="toggleGrid" @click="toggleGrid"
> >
<i <i class="pi pi-table text-lg text-white" />
v-tooltip.right="{ value: $t('load3d.showGrid'), showDelay: 300 }"
class="pi pi-table text-lg text-white"
/>
</Button> </Button>
<div v-if="!hasBackgroundImage"> <div v-if="!hasBackgroundImage">
<Button class="p-button-rounded p-button-text" @click="openColorPicker"> <Button
<i v-tooltip.right="{
v-tooltip.right="{ value: $t('load3d.backgroundColor'),
value: $t('load3d.backgroundColor'), showDelay: 300
showDelay: 300 }"
}" variant="textonly"
class="pi pi-palette text-lg text-white" size="icon"
/> class="rounded-full"
:aria-label="$t('load3d.backgroundColor')"
@click="openColorPicker"
>
<i class="pi pi-palette text-lg text-white" />
<input <input
ref="colorPickerRef" ref="colorPickerRef"
type="color" type="color"
@@ -33,14 +37,18 @@
</div> </div>
<div v-if="!hasBackgroundImage"> <div v-if="!hasBackgroundImage">
<Button class="p-button-rounded p-button-text" @click="openImagePicker"> <Button
<i v-tooltip.right="{
v-tooltip.right="{ value: $t('load3d.uploadBackgroundImage'),
value: $t('load3d.uploadBackgroundImage'), showDelay: 300
showDelay: 300 }"
}" variant="textonly"
class="pi pi-image text-lg text-white" size="icon"
/> class="rounded-full"
:aria-label="$t('load3d.uploadBackgroundImage')"
@click="openImagePicker"
>
<i class="pi pi-image text-lg text-white" />
<input <input
ref="imagePickerRef" ref="imagePickerRef"
type="file" type="file"
@@ -53,17 +61,22 @@
<div v-if="hasBackgroundImage"> <div v-if="hasBackgroundImage">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
:class="{ 'p-button-outlined': backgroundRenderMode === 'panorama' }" value: $t('load3d.panoramaMode'),
showDelay: 300
}"
variant="textonly"
size="icon"
:class="
cn(
'rounded-full',
backgroundRenderMode === 'panorama' && 'ring-2 ring-white/50'
)
"
:aria-label="$t('load3d.panoramaMode')"
@click="toggleBackgroundRenderMode" @click="toggleBackgroundRenderMode"
> >
<i <i class="pi pi-globe text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.panoramaMode'),
showDelay: 300
}"
class="pi pi-globe text-lg text-white"
/>
</Button> </Button>
</div> </div>
@@ -75,27 +88,29 @@
<div v-if="hasBackgroundImage"> <div v-if="hasBackgroundImage">
<Button <Button
class="p-button-rounded p-button-text" v-tooltip.right="{
value: $t('load3d.removeBackgroundImage'),
showDelay: 300
}"
variant="textonly"
size="icon"
class="rounded-full"
:aria-label="$t('load3d.removeBackgroundImage')"
@click="removeBackgroundImage" @click="removeBackgroundImage"
> >
<i <i class="pi pi-times text-lg text-white" />
v-tooltip.right="{
value: $t('load3d.removeBackgroundImage'),
showDelay: 300
}"
class="pi pi-times text-lg text-white"
/>
</Button> </Button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import PopupSlider from '@/components/load3d/controls/PopupSlider.vue' import PopupSlider from '@/components/load3d/controls/PopupSlider.vue'
import Button from '@/components/ui/button/Button.vue'
import type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces' import type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces'
import { cn } from '@/utils/tailwindUtil'
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'updateBackgroundImage', file: File | null): void (e: 'updateBackgroundImage', file: File | null): void

View File

@@ -1,23 +1,26 @@
<template> <template>
<div class="relative rounded-lg bg-smoke-700/30"> <div class="relative rounded-lg bg-smoke-700/30">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<Button class="p-button-rounded p-button-text" @click="openIn3DViewer"> <Button
<i v-tooltip.right="{
v-tooltip.right="{ value: t('load3d.openIn3DViewer'),
value: t('load3d.openIn3DViewer'), showDelay: 300
showDelay: 300 }"
}" size="icon"
class="pi pi-expand text-lg text-white" variant="textonly"
/> class="rounded-full"
:aria-label="t('load3d.openIn3DViewer')"
@click="openIn3DViewer"
>
<i class="pi pi-expand text-lg text-white" />
</Button> </Button>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue' import Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'
import Button from '@/components/ui/button/Button.vue'
import { t } from '@/i18n' import { t } from '@/i18n'
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode' import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
import { useLoad3dService } from '@/services/load3dService' import { useLoad3dService } from '@/services/load3dService'

View File

@@ -9,9 +9,8 @@
</Select> </Select>
<Button <Button
severity="secondary" variant="muted-textonly"
text class="rounded-full"
rounded
@click="exportModel(exportFormat)" @click="exportModel(exportFormat)"
> >
{{ $t('load3d.export') }} {{ $t('load3d.export') }}
@@ -20,10 +19,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Select from 'primevue/select' import Select from 'primevue/select'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'exportModel', format: string): void (e: 'exportModel', format: string): void
}>() }>()

View File

@@ -15,13 +15,10 @@
</div> </div>
<div v-if="!hasBackgroundImage && !disableBackgroundUpload"> <div v-if="!hasBackgroundImage && !disableBackgroundUpload">
<Button <Button variant="secondary" class="w-full" @click="openImagePicker">
severity="secondary" <i class="pi pi-image" />
:label="$t('load3d.uploadBackgroundImage')" {{ $t('load3d.uploadBackgroundImage') }}
icon="pi pi-image" </Button>
class="w-full"
@click="openImagePicker"
/>
<input <input
ref="imagePickerRef" ref="imagePickerRef"
type="file" type="file"
@@ -34,38 +31,38 @@
<div v-if="hasBackgroundImage" class="space-y-2"> <div v-if="hasBackgroundImage" class="space-y-2">
<div class="flex gap-2"> <div class="flex gap-2">
<Button <Button
:severity="backgroundRenderMode === 'tiled' ? 'primary' : 'secondary'" :variant="backgroundRenderMode === 'tiled' ? 'primary' : 'secondary'"
:label="$t('load3d.tiledMode')"
icon="pi pi-th-large"
class="flex-1" class="flex-1"
@click="setBackgroundRenderMode('tiled')" @click="setBackgroundRenderMode('tiled')"
/> >
<i class="pi pi-th-large" />
{{ $t('load3d.tiledMode') }}
</Button>
<Button <Button
:severity=" :variant="
backgroundRenderMode === 'panorama' ? 'primary' : 'secondary' backgroundRenderMode === 'panorama' ? 'primary' : 'secondary'
" "
:label="$t('load3d.panoramaMode')"
icon="pi pi-globe"
class="flex-1" class="flex-1"
@click="setBackgroundRenderMode('panorama')" @click="setBackgroundRenderMode('panorama')"
/> >
<i class="pi pi-globe" />
{{ $t('load3d.panoramaMode') }}
</Button>
</div> </div>
<Button <Button variant="secondary" class="w-full" @click="removeBackgroundImage">
severity="secondary" <i class="pi pi-times" />
:label="$t('load3d.removeBackgroundImage')" {{ $t('load3d.removeBackgroundImage') }}
icon="pi pi-times" </Button>
class="w-full"
@click="removeBackgroundImage"
/>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import Checkbox from 'primevue/checkbox' import Checkbox from 'primevue/checkbox'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
const backgroundColor = defineModel<string>('backgroundColor') const backgroundColor = defineModel<string>('backgroundColor')
const showGrid = defineModel<boolean>('showGrid') const showGrid = defineModel<boolean>('showGrid')
const backgroundRenderMode = defineModel<'tiled' | 'panorama'>( const backgroundRenderMode = defineModel<'tiled' | 'panorama'>(

View File

@@ -46,28 +46,22 @@
</div> </div>
<div class="flex gap-3"> <div class="flex gap-3">
<Button <Button variant="primary" :disabled="!saveEnabled" @click="handleSave">
:label="saveButtonText" <i class="pi pi-check" />
icon="pi pi-check" {{ saveButtonText }}
size="small" </Button>
:disabled="!saveEnabled" <Button variant="secondary" @click="handleCancel">
@click="handleSave" <i class="pi pi-times" />
/> {{ t('g.cancel') }}
<Button </Button>
:label="t('g.cancel')"
icon="pi pi-times"
size="small"
severity="secondary"
@click="handleCancel"
/>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button'
import { ref } from 'vue' import { ref } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { useCanvasTools } from '@/composables/maskeditor/useCanvasTools' import { useCanvasTools } from '@/composables/maskeditor/useCanvasTools'
import { useMaskEditorSaver } from '@/composables/maskeditor/useMaskEditorSaver' import { useMaskEditorSaver } from '@/composables/maskeditor/useMaskEditorSaver'
import { t } from '@/i18n' import { t } from '@/i18n'

View File

@@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { watchDebounced } from '@vueuse/core' import { watchDebounced } from '@vueuse/core'
import Button from 'primevue/button'
import { import {
computed, computed,
customRef, customRef,
@@ -10,6 +9,7 @@ import {
triggerRef triggerRef
} from 'vue' } from 'vue'
import Button from '@/components/ui/button/Button.vue'
import { import {
demoteWidget, demoteWidget,
isRecommendedWidget, isRecommendedWidget,
@@ -315,7 +315,7 @@ onBeforeUnmount(() => {
class="flex justify-center border-t border-interface-stroke py-4" class="flex justify-center border-t border-interface-stroke py-4"
> >
<Button <Button
size="small" size="sm"
class="rounded border-none px-3 py-0.5" class="rounded border-none px-3 py-0.5"
@click.stop="showRecommended" @click.stop="showRecommended"
> >

View File

@@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import Button from 'primevue/button' import Button from '@/components/ui/button/Button.vue'
import { cn } from '@/utils/tailwindUtil' import { cn } from '@/utils/tailwindUtil'
import type { ClassValue } from '@/utils/tailwindUtil' import type { ClassValue } from '@/utils/tailwindUtil'
@@ -43,13 +42,13 @@ function getIcon() {
<div class="text-sm line-clamp-1 leading-8">{{ widgetName }}</div> <div class="text-sm line-clamp-1 leading-8">{{ widgetName }}</div>
</div> </div>
<Button <Button
size="small" variant="muted-textonly"
text size="sm"
:icon="getIcon()"
:disabled="isPhysical" :disabled="isPhysical"
severity="secondary"
@click.stop="$emit('toggleVisibility')" @click.stop="$emit('toggleVisibility')"
/> >
<i :class="getIcon()" />
</Button>
<div <div
v-if="isDraggable" v-if="isDraggable"
class="size-4 pointer-events-none icon-[lucide--grip-vertical]" class="size-4 pointer-events-none icon-[lucide--grip-vertical]"

View File

@@ -14,11 +14,13 @@
</div> </div>
<Button <Button
icon="pi pi-filter" variant="secondary"
severity="secondary" :aria-label="$t('g.addNodeFilterCondition')"
class="filter-button z-10" class="filter-button z-10"
@click="nodeSearchFilterVisible = true" @click="nodeSearchFilterVisible = true"
/> >
<i class="pi pi-filter" />
</Button>
<Dialog <Dialog
v-model:visible="nodeSearchFilterVisible" v-model:visible="nodeSearchFilterVisible"
class="min-w-96" class="min-w-96"
@@ -79,7 +81,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { debounce } from 'es-toolkit/compat' import { debounce } from 'es-toolkit/compat'
import Button from 'primevue/button'
import Dialog from 'primevue/dialog' import Dialog from 'primevue/dialog'
import { computed, nextTick, onMounted, ref } from 'vue' import { computed, nextTick, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@@ -88,6 +89,7 @@ import NodePreview from '@/components/node/NodePreview.vue'
import AutoCompletePlus from '@/components/primevueOverride/AutoCompletePlus.vue' import AutoCompletePlus from '@/components/primevueOverride/AutoCompletePlus.vue'
import NodeSearchFilter from '@/components/searchbox/NodeSearchFilter.vue' import NodeSearchFilter from '@/components/searchbox/NodeSearchFilter.vue'
import NodeSearchItem from '@/components/searchbox/NodeSearchItem.vue' import NodeSearchItem from '@/components/searchbox/NodeSearchItem.vue'
import Button from '@/components/ui/button/Button.vue'
import { useSettingStore } from '@/platform/settings/settingStore' import { useSettingStore } from '@/platform/settings/settingStore'
import { useTelemetry } from '@/platform/telemetry' import { useTelemetry } from '@/platform/telemetry'
import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore' import type { ComfyNodeDefImpl } from '@/stores/nodeDefStore'

Some files were not shown because too many files have changed in this diff Show More