mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
feat(V3 UI style): color picker + file upload + input text + multi select + select + select button + slider + textarea + tree select
This commit is contained in:
@@ -1,17 +1,24 @@
|
|||||||
<!-- Needs custom color picker for alpha support -->
|
<!-- Needs custom color picker for alpha support -->
|
||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col gap-1">
|
<WidgetLayoutField :widget="widget">
|
||||||
<label v-if="widget.name" class="text-sm opacity-80">{{
|
<label
|
||||||
widget.name
|
:class="
|
||||||
}}</label>
|
cn(WidgetInputBaseClass, 'flex items-center gap-2 w-full px-4 py-2')
|
||||||
<ColorPicker
|
"
|
||||||
v-model="localValue"
|
>
|
||||||
v-bind="filteredProps"
|
<ColorPicker
|
||||||
:disabled="readonly"
|
v-model="localValue"
|
||||||
inline
|
v-bind="filteredProps"
|
||||||
@update:model-value="onChange"
|
:disabled="readonly"
|
||||||
/>
|
class="w-8 h-4 !rounded-full overflow-hidden border-none"
|
||||||
</div>
|
:pt="{
|
||||||
|
preview: '!w-full !h-full !border-none'
|
||||||
|
}"
|
||||||
|
@update:model-value="onChange"
|
||||||
|
/>
|
||||||
|
<span class="text-xs">#{{ localValue }}</span>
|
||||||
|
</label>
|
||||||
|
</WidgetLayoutField>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -20,11 +27,15 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
PANEL_EXCLUDED_PROPS,
|
PANEL_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
widget: SimplifiedWidget<string>
|
widget: SimplifiedWidget<string>
|
||||||
modelValue: string
|
modelValue: string
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
<Button
|
<Button
|
||||||
label="Browse Files"
|
label="Browse Files"
|
||||||
size="small"
|
size="small"
|
||||||
|
severity="secondary"
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
@click="triggerFileInput"
|
@click="triggerFileInput"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
v-model="localValue"
|
v-model="localValue"
|
||||||
v-bind="filteredProps"
|
v-bind="filteredProps"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
class="w-full text-xs py-2 px-4 bg-zinc-500/10 border-none outline outline-1 outline-offset-[-1px] outline-zinc-300/10 !rounded-lg hover:outline-blue-500/80"
|
:class="cn(WidgetInputBaseClass, 'w-full text-xs py-2 px-4')"
|
||||||
size="small"
|
size="small"
|
||||||
@update:model-value="onChange"
|
@update:model-value="onChange"
|
||||||
/>
|
/>
|
||||||
@@ -17,11 +17,13 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { useStringWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useStringWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
INPUT_EXCLUDED_PROPS,
|
INPUT_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
<WidgetLayoutField :widget="widget">
|
<WidgetLayoutField :widget="widget">
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
v-model="localValue"
|
v-model="localValue"
|
||||||
v-bind="filteredProps"
|
:options="widget.options?.values || []"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
class="w-full text-xs"
|
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
|
||||||
size="small"
|
size="small"
|
||||||
|
display="chip"
|
||||||
:pt="{
|
:pt="{
|
||||||
option: 'text-xs'
|
option: 'text-xs'
|
||||||
}"
|
}"
|
||||||
@@ -16,15 +17,12 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import MultiSelect from 'primevue/multiselect'
|
import MultiSelect from 'primevue/multiselect'
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
import {
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
PANEL_EXCLUDED_PROPS,
|
|
||||||
filterWidgetProps
|
|
||||||
} from '@/utils/widgetPropFilter'
|
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -44,14 +42,4 @@ const { localValue, onChange } = useWidgetValue({
|
|||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
emit
|
emit
|
||||||
})
|
})
|
||||||
|
|
||||||
// MultiSelect specific excluded props include overlay styles
|
|
||||||
const MULTISELECT_EXCLUDED_PROPS = [
|
|
||||||
...PANEL_EXCLUDED_PROPS,
|
|
||||||
'overlayStyle'
|
|
||||||
] as const
|
|
||||||
|
|
||||||
const filteredProps = computed(() =>
|
|
||||||
filterWidgetProps(props.widget.options, MULTISELECT_EXCLUDED_PROPS)
|
|
||||||
)
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
:options="selectOptions"
|
:options="selectOptions"
|
||||||
v-bind="filteredProps"
|
v-bind="filteredProps"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
class="w-full text-xs bg-[#F9F8F4] dark-theme:bg-[#0E0E12] border-[#E1DED5] dark-theme:border-[#15161C] !rounded-lg"
|
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
|
||||||
size="small"
|
size="small"
|
||||||
:pt="{
|
:pt="{
|
||||||
option: 'text-xs'
|
option: 'text-xs'
|
||||||
@@ -21,11 +21,13 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
PANEL_EXCLUDED_PROPS,
|
PANEL_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<WidgetLayoutField :widget="widget">
|
<WidgetLayoutField :widget="widget">
|
||||||
<div
|
<div
|
||||||
class="flex items-center gap-2 w-full rounded-lg pl-4 pr-2 bg-[#F9F8F4] dark-theme:bg-[#0E0E12] border-[#E1DED5] dark-theme:border-[#15161C] border-solid border"
|
:class="
|
||||||
|
cn(WidgetInputBaseClass, 'flex items-center gap-2 w-full pl-4 pr-2')
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<Slider
|
<Slider
|
||||||
v-model="localValue"
|
v-model="localValue"
|
||||||
@@ -33,11 +35,13 @@ import { computed, ref, watch } from 'vue'
|
|||||||
|
|
||||||
import { useNumberWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useNumberWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
STANDARD_EXCLUDED_PROPS,
|
STANDARD_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
v-model="localValue"
|
v-model="localValue"
|
||||||
v-bind="filteredProps"
|
v-bind="filteredProps"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
class="w-full text-xs"
|
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
|
||||||
|
:placeholder="widget.name || ''"
|
||||||
size="small"
|
size="small"
|
||||||
rows="3"
|
rows="3"
|
||||||
@update:model-value="onChange"
|
@update:model-value="onChange"
|
||||||
@@ -16,11 +17,14 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { useStringWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useStringWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
INPUT_EXCLUDED_PROPS,
|
INPUT_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
widget: SimplifiedWidget<string>
|
widget: SimplifiedWidget<string>
|
||||||
modelValue: string
|
modelValue: string
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
v-model="localValue"
|
v-model="localValue"
|
||||||
v-bind="filteredProps"
|
v-bind="filteredProps"
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
class="w-full text-xs"
|
:class="cn(WidgetInputBaseClass, 'w-full text-xs')"
|
||||||
size="small"
|
size="small"
|
||||||
@update:model-value="onChange"
|
@update:model-value="onChange"
|
||||||
/>
|
/>
|
||||||
@@ -17,11 +17,13 @@ import { computed } from 'vue'
|
|||||||
|
|
||||||
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
import { useWidgetValue } from '@/composables/graph/useWidgetValue'
|
||||||
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
|
||||||
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
import {
|
import {
|
||||||
PANEL_EXCLUDED_PROPS,
|
PANEL_EXCLUDED_PROPS,
|
||||||
filterWidgetProps
|
filterWidgetProps
|
||||||
} from '@/utils/widgetPropFilter'
|
} from '@/utils/widgetPropFilter'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from './layout'
|
||||||
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
import WidgetLayoutField from './layout/WidgetLayoutField.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="p-1 bg-zinc-500/10 rounded-lg outline outline-1 outline-offset-[-1px] outline-zinc-300/10 inline-flex justify-center items-center gap-1 hover:outline-blue-500/80"
|
:class="
|
||||||
|
cn(
|
||||||
|
WidgetInputBaseClass,
|
||||||
|
'p-1 inline-flex justify-center items-center gap-1'
|
||||||
|
)
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-for="(option, index) in options"
|
v-for="(option, index) in options"
|
||||||
@@ -33,6 +38,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cn } from '@/utils/tailwindUtil'
|
import { cn } from '@/utils/tailwindUtil'
|
||||||
|
|
||||||
|
import { WidgetInputBaseClass } from '../layout'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue: string | null | undefined
|
modelValue: string | null | undefined
|
||||||
options: any[]
|
options: any[]
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
export const WidgetInputBaseClass = [
|
||||||
|
// Background
|
||||||
|
'bg-zinc-500/10',
|
||||||
|
// Outline
|
||||||
|
'border-none',
|
||||||
|
'outline',
|
||||||
|
'outline-1',
|
||||||
|
'outline-offset-[-1px]',
|
||||||
|
'outline-zinc-300/10',
|
||||||
|
// Rounded
|
||||||
|
'!rounded-lg',
|
||||||
|
// Hover
|
||||||
|
'hover:outline-blue-500/80'
|
||||||
|
].join(' ')
|
||||||
@@ -25,6 +25,10 @@ const TYPE_TO_ENUM_MAP: Record<string, string> = {
|
|||||||
COMBO: WidgetType.COMBO,
|
COMBO: WidgetType.COMBO,
|
||||||
selectbutton: WidgetType.SELECTBUTTON,
|
selectbutton: WidgetType.SELECTBUTTON,
|
||||||
SELECTBUTTON: WidgetType.SELECTBUTTON,
|
SELECTBUTTON: WidgetType.SELECTBUTTON,
|
||||||
|
multiselect: WidgetType.MULTISELECT,
|
||||||
|
MULTISELECT: WidgetType.MULTISELECT,
|
||||||
|
treeselect: WidgetType.TREESELECT,
|
||||||
|
TREESELECT: WidgetType.TREESELECT,
|
||||||
|
|
||||||
// Boolean
|
// Boolean
|
||||||
toggle: WidgetType.TOGGLESWITCH,
|
toggle: WidgetType.TOGGLESWITCH,
|
||||||
@@ -34,6 +38,7 @@ const TYPE_TO_ENUM_MAP: Record<string, string> = {
|
|||||||
// Multiline text
|
// Multiline text
|
||||||
multiline: WidgetType.TEXTAREA,
|
multiline: WidgetType.TEXTAREA,
|
||||||
textarea: WidgetType.TEXTAREA,
|
textarea: WidgetType.TEXTAREA,
|
||||||
|
TEXTAREA: WidgetType.TEXTAREA,
|
||||||
customtext: WidgetType.TEXTAREA,
|
customtext: WidgetType.TEXTAREA,
|
||||||
MARKDOWN: WidgetType.MARKDOWN,
|
MARKDOWN: WidgetType.MARKDOWN,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user