mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 10:42:44 +00:00
Lint: Add tailwind linter (#5984)
## Summary Adds the [tailwind lint plugin](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#eslint-plugin-tailwindcss) and fixes the currently fixable rules ([v4 is still in beta](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#about-tailwind-css-4-support)). ## Changes - **What**: Enforces things like consistent class order, and eventually can prohibit extra classes that could be utilities instead - **Dependencies**: The plugin and its types ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5984-Lint-Add-tailwind-linter-2866d73d365081d89db0d998232533bb) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex flex-col gap-1">
|
||||
<div
|
||||
class="p-4 border border-gray-300 dark-theme:border-gray-600 rounded max-h-[48rem]"
|
||||
class="max-h-[48rem] rounded border border-gray-300 p-4 dark-theme:border-gray-600"
|
||||
>
|
||||
<Chart :type="chartType" :data="chartData" :options="chartOptions" />
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<ColorPicker
|
||||
v-model="localValue"
|
||||
v-bind="filteredProps"
|
||||
class="w-8 h-4 !rounded-full overflow-hidden border-none"
|
||||
class="h-4 w-8 overflow-hidden !rounded-full border-none"
|
||||
:pt="{
|
||||
preview: '!w-full !h-full !border-none'
|
||||
}"
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
style="width: calc(100% + 1rem)"
|
||||
>
|
||||
<!-- Select section above image -->
|
||||
<div class="flex items-center justify-between gap-4 mb-2 px-2">
|
||||
<div class="mb-2 flex items-center justify-between gap-4 px-2">
|
||||
<label
|
||||
v-if="widget.name"
|
||||
class="text-xs opacity-80 min-w-[4em] truncate"
|
||||
class="min-w-[4em] truncate text-xs opacity-80"
|
||||
>{{ widget.name }}</label
|
||||
>
|
||||
<!-- Group select and folder button together on the right -->
|
||||
@@ -21,7 +21,7 @@
|
||||
:options="[selectedFile?.name || '']"
|
||||
:disabled="true"
|
||||
v-bind="transformCompatProps"
|
||||
class="min-w-[8em] max-w-[20em] text-xs"
|
||||
class="max-w-[20em] min-w-[8em] text-xs"
|
||||
size="small"
|
||||
:pt="{
|
||||
option: 'text-xs'
|
||||
@@ -30,7 +30,7 @@
|
||||
<Button
|
||||
icon="pi pi-folder"
|
||||
size="small"
|
||||
class="!w-8 !h-8"
|
||||
class="!h-8 !w-8"
|
||||
@click="triggerFileInput"
|
||||
/>
|
||||
</div>
|
||||
@@ -38,31 +38,31 @@
|
||||
|
||||
<!-- Image preview -->
|
||||
<!-- TODO: change hardcoded colors when design system incorporated -->
|
||||
<div class="relative group">
|
||||
<img :src="imageUrl" :alt="selectedFile?.name" class="w-full h-auto" />
|
||||
<div class="group relative">
|
||||
<img :src="imageUrl" :alt="selectedFile?.name" class="h-auto w-full" />
|
||||
<!-- Darkening overlay on hover -->
|
||||
<div
|
||||
class="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-20 transition-all duration-200 pointer-events-none"
|
||||
class="bg-opacity-0 group-hover:bg-opacity-20 pointer-events-none absolute inset-0 bg-black transition-all duration-200"
|
||||
/>
|
||||
<!-- Control buttons in top right on hover -->
|
||||
<div
|
||||
class="absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
|
||||
class="absolute top-2 right-2 flex gap-1 opacity-0 transition-opacity duration-200 group-hover:opacity-100"
|
||||
>
|
||||
<!-- Edit button -->
|
||||
<button
|
||||
class="w-6 h-6 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none"
|
||||
class="flex h-6 w-6 items-center justify-center rounded border-none transition-all duration-150 focus:outline-none"
|
||||
style="background-color: #262729"
|
||||
@click="handleEdit"
|
||||
>
|
||||
<i class="pi pi-pencil text-white text-xs"></i>
|
||||
<i class="pi pi-pencil text-xs text-white"></i>
|
||||
</button>
|
||||
<!-- Delete button -->
|
||||
<button
|
||||
class="w-6 h-6 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none"
|
||||
class="flex h-6 w-6 items-center justify-center rounded border-none transition-all duration-150 focus:outline-none"
|
||||
style="background-color: #262729"
|
||||
@click="clearFile"
|
||||
>
|
||||
<i class="pi pi-times text-white text-xs"></i>
|
||||
<i class="pi pi-times text-xs text-white"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,10 +75,10 @@
|
||||
style="width: calc(100% + 1rem)"
|
||||
>
|
||||
<!-- Select section above audio player -->
|
||||
<div class="flex items-center justify-between gap-4 mb-2 px-2">
|
||||
<div class="mb-2 flex items-center justify-between gap-4 px-2">
|
||||
<label
|
||||
v-if="widget.name"
|
||||
class="text-xs opacity-80 min-w-[4em] truncate"
|
||||
class="min-w-[4em] truncate text-xs opacity-80"
|
||||
>{{ widget.name }}</label
|
||||
>
|
||||
<!-- Group select and folder button together on the right -->
|
||||
@@ -88,7 +88,7 @@
|
||||
:options="[selectedFile?.name || '']"
|
||||
:disabled="true"
|
||||
v-bind="transformCompatProps"
|
||||
class="min-w-[8em] max-w-[20em] text-xs"
|
||||
class="max-w-[20em] min-w-[8em] text-xs"
|
||||
size="small"
|
||||
:pt="{
|
||||
option: 'text-xs'
|
||||
@@ -97,16 +97,16 @@
|
||||
<Button
|
||||
icon="pi pi-folder"
|
||||
size="small"
|
||||
class="!w-8 !h-8"
|
||||
class="!h-8 !w-8"
|
||||
@click="triggerFileInput"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Audio player -->
|
||||
<div class="relative group px-2">
|
||||
<div class="group relative px-2">
|
||||
<div
|
||||
class="bg-[#1a1b1e] rounded-lg p-4 flex items-center gap-4"
|
||||
class="flex items-center gap-4 rounded-lg bg-[#1a1b1e] p-4"
|
||||
style="border: 1px solid #262729"
|
||||
>
|
||||
<!-- Audio icon -->
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
<!-- File info and controls -->
|
||||
<div class="flex-1">
|
||||
<div class="text-sm font-medium mb-1">{{ selectedFile?.name }}</div>
|
||||
<div class="mb-1 text-sm font-medium">{{ selectedFile?.name }}</div>
|
||||
<div class="text-xs opacity-60">
|
||||
{{
|
||||
selectedFile ? (selectedFile.size / 1024).toFixed(1) + ' KB' : ''
|
||||
@@ -128,10 +128,10 @@
|
||||
<div class="flex gap-1">
|
||||
<!-- Delete button -->
|
||||
<button
|
||||
class="w-8 h-8 rounded flex items-center justify-center transition-all duration-150 focus:outline-none border-none hover:bg-[#262729]"
|
||||
class="flex h-8 w-8 items-center justify-center rounded border-none transition-all duration-150 hover:bg-[#262729] focus:outline-none"
|
||||
@click="clearFile"
|
||||
>
|
||||
<i class="pi pi-times text-white text-sm"></i>
|
||||
<i class="pi pi-times text-sm text-white"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,14 +141,14 @@
|
||||
<!-- Show normal file upload UI when no image or audio is loaded -->
|
||||
<div
|
||||
v-else
|
||||
class="flex flex-col gap-1 w-full border border-solid p-1 rounded-lg"
|
||||
class="flex w-full flex-col gap-1 rounded-lg border border-solid p-1"
|
||||
:style="{ borderColor: '#262729' }"
|
||||
>
|
||||
<div
|
||||
class="border border-dashed p-1 rounded-md transition-colors duration-200 hover:border-slate-300"
|
||||
class="rounded-md border border-dashed p-1 transition-colors duration-200 hover:border-slate-300"
|
||||
:style="{ borderColor: '#262729' }"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-2 w-full py-4">
|
||||
<div class="flex w-full flex-col items-center gap-2 py-4">
|
||||
<span class="text-xs opacity-60"> {{ $t('Drop your file or') }} </span>
|
||||
<div>
|
||||
<Button
|
||||
|
||||
@@ -29,18 +29,18 @@
|
||||
item?.alt ||
|
||||
`${t('g.galleryImage')} ${activeIndex + 1} of ${galleryImages.length}`
|
||||
"
|
||||
class="w-full h-auto max-h-64 object-contain"
|
||||
class="h-auto max-h-64 w-full object-contain"
|
||||
/>
|
||||
</template>
|
||||
<template #thumbnail="{ item }">
|
||||
<div class="p-1 w-full h-full">
|
||||
<div class="h-full w-full p-1">
|
||||
<img
|
||||
:src="item?.thumbnailImageSrc || item?.src || ''"
|
||||
:alt="
|
||||
item?.alt ||
|
||||
`${t('g.galleryThumbnail')} ${galleryImages.findIndex((img) => img === item) + 1} of ${galleryImages.length}`
|
||||
"
|
||||
class="w-full h-full object-cover rounded-lg"
|
||||
class="h-full w-full rounded-lg object-cover"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
<img
|
||||
:src="beforeImage"
|
||||
:alt="beforeAlt"
|
||||
class="w-full h-full object-cover"
|
||||
class="h-full w-full object-cover"
|
||||
/>
|
||||
</template>
|
||||
<template #right>
|
||||
<img
|
||||
:src="afterImage"
|
||||
:alt="afterAlt"
|
||||
class="w-full h-full object-cover"
|
||||
class="h-full w-full object-cover"
|
||||
/>
|
||||
</template>
|
||||
</ImageCompare>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
>
|
||||
<!-- Display mode: Rendered markdown -->
|
||||
<div
|
||||
class="comfy-markdown-content hover:bg-[var(--p-content-hover-background)] text-sm min-h-[60px] w-full rounded-lg px-4 py-2 overflow-y-auto lod-toggle"
|
||||
class="comfy-markdown-content lod-toggle min-h-[60px] w-full overflow-y-auto rounded-lg px-4 py-2 text-sm hover:bg-[var(--p-content-hover-background)]"
|
||||
:class="isEditing === false ? 'visible' : 'invisible'"
|
||||
v-html="renderedHtml"
|
||||
/>
|
||||
@@ -15,7 +15,7 @@
|
||||
v-show="isEditing"
|
||||
ref="textareaRef"
|
||||
v-model="localValue"
|
||||
class="w-full min-h-[60px] absolute inset-0 resize-none"
|
||||
class="absolute inset-0 min-h-[60px] w-full resize-none"
|
||||
:pt="{
|
||||
root: {
|
||||
class: 'text-sm w-full h-full',
|
||||
|
||||
@@ -65,7 +65,7 @@ const theButtonStyle = computed(() =>
|
||||
"
|
||||
@click="emit('select-click', $event)"
|
||||
>
|
||||
<span class="px-4 py-2 min-w-0 text-left">
|
||||
<span class="min-w-0 px-4 py-2 text-left">
|
||||
<span v-if="!selectedItems.length" class="min-w-0">
|
||||
{{ props.placeholder }}
|
||||
</span>
|
||||
@@ -89,7 +89,7 @@ const theButtonStyle = computed(() =>
|
||||
<i class="icon-[lucide--folder-search] size-4" />
|
||||
<input
|
||||
type="file"
|
||||
class="opacity-0 absolute inset-0 -z-1"
|
||||
class="absolute inset-0 -z-1 opacity-0"
|
||||
:multiple="maxSelectable > 1"
|
||||
:disabled="disabled"
|
||||
:accept="accept"
|
||||
|
||||
@@ -36,7 +36,7 @@ const searchQuery = defineModel<string>('searchQuery')
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="w-103 max-h-[640px] pt-4 bg-node-component-surface rounded-lg outline outline-offset-[-1px] outline-node-component-border flex flex-col"
|
||||
class="flex max-h-[640px] w-103 flex-col rounded-lg bg-node-component-surface pt-4 outline outline-offset-[-1px] outline-node-component-border"
|
||||
>
|
||||
<!-- Filter -->
|
||||
<FormDropdownMenuFilter
|
||||
@@ -53,7 +53,7 @@ const searchQuery = defineModel<string>('searchQuery')
|
||||
:is-querying="isQuerying"
|
||||
/>
|
||||
<!-- List -->
|
||||
<div class="flex overflow-hidden relative h-full">
|
||||
<div class="relative flex h-full overflow-hidden">
|
||||
<div
|
||||
:class="
|
||||
cn(
|
||||
@@ -67,11 +67,11 @@ const searchQuery = defineModel<string>('searchQuery')
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="absolute top-0 inset-x-3 h-5 bg-gradient-to-b from-backdrop to-transparent pointer-events-none z-10"
|
||||
class="pointer-events-none absolute inset-x-3 top-0 z-10 h-5 bg-gradient-to-b from-backdrop to-transparent"
|
||||
/>
|
||||
<div
|
||||
v-if="items.length === 0"
|
||||
class="flex justify-center items-center absolute inset-0"
|
||||
class="absolute inset-0 flex items-center justify-center"
|
||||
>
|
||||
<i
|
||||
title="No items"
|
||||
|
||||
@@ -44,7 +44,7 @@ function handleSortSelected(item: SortOption) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex gap-2 text-zinc-400 px-4">
|
||||
<div class="flex gap-2 px-4 text-zinc-400">
|
||||
<label
|
||||
:class="
|
||||
cn(
|
||||
@@ -58,9 +58,9 @@ function handleSortSelected(item: SortOption) {
|
||||
>
|
||||
<i
|
||||
v-if="isQuerying"
|
||||
class="icon-[lucide--loader-circle] mr-2 size-4 animate-spin"
|
||||
class="mr-2 icon-[lucide--loader-circle] size-4 animate-spin"
|
||||
/>
|
||||
<i v-else class="icon-[lucide--search] mr-2 size-4" />
|
||||
<i v-else class="mr-2 icon-[lucide--search] size-4" />
|
||||
<input
|
||||
v-model="searchQuery"
|
||||
type="text"
|
||||
@@ -85,7 +85,7 @@ function handleSortSelected(item: SortOption) {
|
||||
>
|
||||
<div
|
||||
v-if="sortSelected !== 'default'"
|
||||
class="size-2 absolute top-[-2px] left-[-2px] bg-blue-500 rounded-full"
|
||||
class="absolute top-[-2px] left-[-2px] size-2 rounded-full bg-blue-500"
|
||||
/>
|
||||
<i class="icon-[lucide--arrow-up-down] size-4" />
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@ const filterSelected = defineModel<OptionId>('filterSelected')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex gap-1 text-zinc-400 px-4 mb-4">
|
||||
<div class="mb-4 flex gap-1 px-4 text-zinc-400">
|
||||
<div
|
||||
v-for="option in filterOptions"
|
||||
:key="option.id"
|
||||
|
||||
@@ -92,10 +92,10 @@ function handleVideoLoad(event: Event) {
|
||||
<!-- Selected Icon -->
|
||||
<div
|
||||
v-if="selected"
|
||||
class="rounded-full bg-blue-500 border-1 border-white size-4 absolute top-1 left-1"
|
||||
class="absolute top-1 left-1 size-4 rounded-full border-1 border-white bg-blue-500"
|
||||
>
|
||||
<i
|
||||
class="icon-[lucide--check] size-3 text-white -translate-y-[0.5px]"
|
||||
class="icon-[lucide--check] size-3 translate-y-[-0.5px] text-white"
|
||||
/>
|
||||
</div>
|
||||
<video
|
||||
|
||||
@@ -12,12 +12,12 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex items-center justify-between gap-2 h-[30px] overscroll-contain"
|
||||
class="flex h-[30px] items-center justify-between gap-2 overscroll-contain"
|
||||
>
|
||||
<div class="relative h-6 flex items-center mr-4">
|
||||
<div class="relative mr-4 flex h-6 items-center">
|
||||
<p
|
||||
v-if="widget.name"
|
||||
class="text-sm text-node-component-slot-text font-normal flex-1 truncate w-20 lod-toggle"
|
||||
class="lod-toggle w-20 flex-1 truncate text-sm font-normal text-node-component-slot-text"
|
||||
>
|
||||
{{ widget.label || widget.name }}
|
||||
</p>
|
||||
@@ -25,7 +25,7 @@ defineProps<{
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div
|
||||
class="w-75 cursor-default lod-toggle"
|
||||
class="lod-toggle w-75 cursor-default"
|
||||
@pointerdown.stop="noop"
|
||||
@pointermove.stop="noop"
|
||||
@pointerup.stop="noop"
|
||||
|
||||
Reference in New Issue
Block a user