diff --git a/web/app/components/base/checkbox/index.tsx b/web/app/components/base/checkbox/index.tsx
index 7abe54ee38..99a31234f7 100644
--- a/web/app/components/base/checkbox/index.tsx
+++ b/web/app/components/base/checkbox/index.tsx
@@ -11,45 +11,38 @@ type CheckboxProps = {
indeterminate?: boolean
}
-const Checkbox = ({ id, checked, onCheck, className, disabled, indeterminate }: CheckboxProps) => {
- if (!checked) {
- return (
-
{
- if (disabled)
- return
- onCheck?.()
- }}
- >
- {indeterminate && (
-
- )}
-
- )
- }
+const Checkbox = ({
+ id,
+ checked,
+ onCheck,
+ className,
+ disabled,
+ indeterminate,
+}: CheckboxProps) => {
+ const checkClassName = (checked || indeterminate)
+ ? 'bg-components-checkbox-bg text-components-checkbox-icon hover:bg-components-checkbox-bg-hover'
+ : 'border border-components-checkbox-border bg-components-checkbox-bg-unchecked hover:bg-components-checkbox-bg-unchecked-hover hover:border-components-checkbox-border-hover'
+ const disabledClassName = (checked || indeterminate)
+ ? 'cursor-not-allowed bg-components-checkbox-bg-disabled-checked text-components-checkbox-icon-disabled hover:bg-components-checkbox-bg-disabled-checked'
+ : 'cursor-not-allowed border-components-checkbox-border-disabled bg-components-checkbox-bg-disabled hover:border-components-checkbox-border-disabled hover:bg-components-checkbox-bg-disabled'
+
return (
{
if (disabled)
return
-
onCheck?.()
}}
>
-
+ {!checked && indeterminate && }
+ {checked && }
)
}
diff --git a/web/app/components/base/form/components/checkbox-field.tsx b/web/app/components/base/form/components/checkbox-field.tsx
new file mode 100644
index 0000000000..ec0cb5d76f
--- /dev/null
+++ b/web/app/components/base/form/components/checkbox-field.tsx
@@ -0,0 +1,43 @@
+import cn from '@/utils/classnames'
+import { useFieldContext } from '..'
+import Checkbox from '../../checkbox'
+
+type CheckboxFieldProps = {
+ label: string;
+ labelClassName?: string;
+}
+
+const CheckboxField = ({
+ label,
+ labelClassName,
+}: CheckboxFieldProps) => {
+ const field = useFieldContext()
+
+ return (
+
+
+ {
+ field.handleChange(!field.state.value)
+ }}
+ />
+
+
+
+ )
+}
+
+export default CheckboxField
diff --git a/web/app/components/base/form/components/label.tsx b/web/app/components/base/form/components/label.tsx
new file mode 100644
index 0000000000..1e06d256e7
--- /dev/null
+++ b/web/app/components/base/form/components/label.tsx
@@ -0,0 +1,44 @@
+import cn from '@/utils/classnames'
+import Tooltip from '../../tooltip'
+
+type LabelProps = {
+ htmlFor: string
+ label: string
+ isRequired?: boolean
+ showOptional?: boolean
+ tooltip?: string
+ className?: string
+ labelClassName?: string
+}
+
+const Label = ({
+ htmlFor,
+ label,
+ isRequired,
+ showOptional,
+ tooltip,
+ labelClassName,
+}: LabelProps) => {
+ return (
+
+
+ {showOptional &&
(Optional)
}
+ {isRequired &&
*
}
+ {tooltip && (
+
{tooltip}
+ }
+ triggerClassName='ml-0.5 w-4 h-4'
+ />
+ )}
+
+ )
+}
+
+export default Label
diff --git a/web/app/components/base/form/components/select-filed.tsx b/web/app/components/base/form/components/select-filed.tsx
new file mode 100644
index 0000000000..eab9a79b2b
--- /dev/null
+++ b/web/app/components/base/form/components/select-filed.tsx
@@ -0,0 +1,42 @@
+import cn from '@/utils/classnames'
+import { useFieldContext } from '..'
+import PureSelect from '../../select/pure'
+import Label from './label'
+
+type SelectOption = {
+ value: string
+ label: string
+}
+
+type SelectFieldProps = {
+ label: string
+ options: SelectOption[]
+ className?: string
+ labelClassName?: string
+}
+
+const SelectField = ({
+ label,
+ options,
+ className,
+ labelClassName,
+}: SelectFieldProps) => {
+ const field = useFieldContext()
+
+ return (
+
+
+
field.handleChange(value)}
+ />
+
+ )
+}
+
+export default SelectField
diff --git a/web/app/components/base/form/components/submit-button.tsx b/web/app/components/base/form/components/submit-button.tsx
new file mode 100644
index 0000000000..f5b891f22f
--- /dev/null
+++ b/web/app/components/base/form/components/submit-button.tsx
@@ -0,0 +1,25 @@
+import { useStore } from '@tanstack/react-form'
+import { useFormContext } from '..'
+import Button, { type ButtonProps } from '../../button'
+
+type SubmitButtonProps = Omit
+
+const SubmitButton = ({ ...buttonProps }: SubmitButtonProps) => {
+ const form = useFormContext()
+
+ const [isSubmitting, canSubmit] = useStore(form.store, state => [
+ state.isSubmitting,
+ state.canSubmit,
+ ])
+
+ return (
+