Repository: harness/canary
Pull request #1499: Migrate Label component to New design system
Author: login: ankormoreankor
Created: 2025-04-18T15:53:21Z | Merged: 2025-04-25T17:21:50Z

##### Label component migrated to the new design system.

- styles are adjusted to [the design](https://www.figma.com/design/AIgjIyUzcuZzuVnuoOyhQE/Harness-Design-System--3.0-?node-id=1639-76160&t=I5DRVNpOgjLHWvti-0)
- `Informer` component (v0) is added
- reviewed usage of the Label component across the app


Diff:
diff --git a/apps/portal/src/content/docs/components/label.mdx b/apps/portal/src/content/docs/components/label.mdx
index 74d5f1b9d4..ed21b38d49 100644
--- a/apps/portal/src/content/docs/components/label.mdx
+++ b/apps/portal/src/content/docs/components/label.mdx
@@ -27,8 +27,8 @@ import { DocsPage } from "../../../components/docs-page";
     <hr />
 
     <div className="flex flex-col gap-4">
-        <h5>With color</h5>
-        <Label htmlFor="password" color="disabled">Password</Label>
+        <h5>Primary variant</h5>
+        <Label variant="primary" htmlFor="password">Password</Label>
         <input id="password" type="password" />
     </div>
 
@@ -58,7 +58,6 @@ The `Label` component provides a styled label for form elements with customizabl
 <Label
   htmlFor="inputId" // [OPTIONAL] ID of the form control this label is associated with
   optional          // [OPTIONAL] Indicate if the associated form field is optional
-  color="primary"   // [OPTIONAL] Color variant of the label
 >
   Label Text
 </Label>
@@ -66,6 +65,13 @@ The `Label` component provides a styled label for form elements with customizabl
 
 <DocsPage.PropsTable
   props={[
+    {
+      name: "variant",
+      description: "The color variant of the label",
+      defaultValue: "default",
+      required: false,
+      value: "'default' | 'primary'",
+    },
     {
       name: "htmlFor",
       description: "The id of the form control this label is associated with",
@@ -75,15 +81,10 @@ The `Label` component provides a styled label for form elements with customizabl
     {
       name: "optional",
       description: "Indicates if the associated form field is optional",
+      defaultValue: "false",
       required: false,
       value: "boolean",
     },
-    {
-      name: "color",
-      description: "The color variant of the label",
-      required: false,
-      value: "'primary' | 'secondary' | 'disabled' | 'disabled-dark'",
-    },
     {
       name: "className",
       description: "Additional CSS classes to apply to the label",
diff --git a/packages/ui/locales/en/views.json b/packages/ui/locales/en/views.json
index 7fcb0dd413..690faee31f 100644
--- a/packages/ui/locales/en/views.json
+++ b/packages/ui/locales/en/views.json
@@ -352,7 +352,7 @@
       "mainTitle": "General settings",
       "projectNamePlaceholder": "Enter project name",
       "projectNameLabel": "Project name",
-      "projectDescriptionPlaceholder": "Enter description (optional)",
+      "projectDescriptionPlaceholder": "Enter description",
       "projectDescriptionLabel": "Description",
       "formSubmitButton": {
         "savingState": "Saving...",
diff --git a/packages/ui/src/components/form-primitives/label.tsx b/packages/ui/src/components/form-primitives/label.tsx
index e3a79b7368..67f919cdd8 100644
--- a/packages/ui/src/components/form-primitives/label.tsx
+++ b/packages/ui/src/components/form-primitives/label.tsx
@@ -1,60 +1,54 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
+import { Informer, InformerProps } from '@/components'
+import { NonEmptyReactNode } from '@/types'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+const labelVariants = cva('label', {
   variants: {
     variant: {
-      default: 'text-sm font-normal leading-none'
-    },
-    color: {
-      primary: 'text-cn-foreground-1',
-      secondary: 'text-cn-foreground-2',
-      disabled: 'text-cn-foreground-3',
-      'disabled-dark': 'text-cn-foreground-disabled'
+      default: 'label-default',
+      primary: 'label-primary'
     }
   },
   defaultVariants: {
-    variant: 'default',
-    color: 'primary'
+    variant: 'default'
   }
 })
 
-const LabelRoot = forwardRef<
-  ElementRef<typeof LabelPrimitive.Root>,
-  Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> & VariantProps<typeof labelVariants>
->(({ className, variant, color, ...props }, ref) => (
-  <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant, color }), className)} {...props} />
-))
-LabelRoot.displayName = LabelPrimitive.Root.displayName
-
-interface LabelProps
-  extends VariantProps<typeof labelVariants>,
-    PropsWithChildren<Omit<HTMLAttributes<HTMLLabelElement>, 'color'>> {
-  htmlFor?: string
-  optional?: boolean
-  className?: string
-}
-
-/**
- * A Label component that wraps the Radix UI LabelPrimitive.Root component.
- * It supports variant and color styling through class-variance-authority.
- * @example
- * <Label htmlFor="label" optional>Label</Label>
- */
+export type LabelProps = Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> &
+  VariantProps<typeof labelVariants> & {
+    disabled?: boolean
+    optional?: boolean
+    informerProps?: InformerProps
+    informerContent?: NonEmptyReactNode
+  }
+
 const Label = forwardRef<ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
-  ({ htmlFor, optional, color, variant, children, className }: LabelProps, ref) => {
-    return (
-      <LabelRoot htmlFor={htmlFor} variant={variant} color={color} className={className} ref={ref}>
-        {children} {optional && <span className="align-top text-cn-foreground-3">(optional)</span>}
-      </LabelRoot>
+  ({ className, children, variant = 'default', optional, disabled, informerContent, ...props }, ref) => {
+    const LabelComponent = ({ className }: { className?: string }) => (
+      <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant }), className)} {...props}>
+        {children} {optional && <span className="label-optional">(optional)</span>}
+      </LabelPrimitive.Root>
     )
+
+    if (informerContent) {
+      return (
+        <span className={cn('flex items-center gap-1', className)}>
+          <LabelComponent />
+
+          <Informer className="label-informer" disabled={disabled}>
+            {informerContent}
+          </Informer>
+        </span>
+      )
+    }
+
+    return <LabelComponent className={className} />
   }
 )
-Label.displayName = 'Label'
+Label.displayName = LabelPrimitive.Root.displayName
 
 export { Label }
diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts
index 47d445f4c4..38435d9b37 100644
--- a/packages/ui/src/components/index.ts
+++ b/packages/ui/src/components/index.ts
@@ -77,6 +77,7 @@ export * from './logo'
 export * from './resizable'
 export * from './harness-logo'
 export * from './time-ago-hover-card'
+export * from './informer'
 
 export * as NodeGroup from './node-group'
 export * as ShaBadge from './sha-badge'
diff --git a/packages/ui/src/components/informer.tsx b/packages/ui/src/components/informer.tsx
new file mode 100644
index 0000000000..f0ec844357
--- /dev/null
+++ b/packages/ui/src/components/informer.tsx
@@ -0,0 +1,22 @@
+import { Icon, IconProps, Tooltip, TooltipProps } from '@/components'
+import { cn } from '@/utils'
+
+export interface InformerProps extends TooltipProps {
+  className?: string
+  /**
+   * If disabled, the tooltip will not be shown
+   */
+  disabled?: boolean
+  iconProps?: Omit<IconProps, 'name'> & { name?: IconProps['name'] }
+}
+
+// TODO(@andrew.koreikin): Temporary solution. The Informer component isn't finished in the design system.
+export const Informer = ({ children, className, disabled, iconProps, ...props }: InformerProps) => (
+  <Tooltip.Root {...props}>
+    <Tooltip.Trigger className={cn({ 'pointer-events-none': disabled }, className)} disabled={disabled}>
+      <Icon name="info-circle" {...iconProps} />
+    </Tooltip.Trigger>
+
+    {!!children && <Tooltip.Content>{children}</Tooltip.Content>}
+  </Tooltip.Root>
+)
diff --git a/packages/ui/src/components/input.tsx b/packages/ui/src/components/input.tsx
index 63b95d28d1..7c0dab6ba6 100644
--- a/packages/ui/src/components/input.tsx
+++ b/packages/ui/src/components/input.tsx
@@ -9,12 +9,12 @@ export interface BaseInputProps
     VariantProps<typeof inputVariants> {}
 
 const inputVariants = cva(
-  'bg-cn-background-2 px-3 py-1 text-cn-foreground-1 disabled:cursor-not-allowed disabled:bg-cn-background-3 disabled:text-cn-foreground-3',
+  'bg-cn-background-2 text-cn-foreground-1 disabled:bg-cn-background-3 disabled:text-cn-foreground-3 px-3 py-1 disabled:cursor-not-allowed',
   {
     variants: {
       variant: {
         default:
-          'flex w-full rounded border text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-cn-foreground-3 focus-visible:rounded focus-visible:outline-none',
+          'placeholder:text-cn-foreground-3 flex w-full rounded border text-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:rounded focus-visible:outline-none',
         extended: 'grow border-none focus-visible:outline-none'
       },
       size: {
@@ -27,7 +27,7 @@ const inputVariants = cva(
         danger: 'border-cn-borders-danger',
         clean: 'bg-transparent outline-none focus:outline-none',
         sidebar:
-          'border-cn-borders-2 bg-transparent text-sidebar-foreground-1 placeholder:text-sidebar-foreground-4 focus-within:border-sidebar-border-4 focus-visible:border-sidebar-border-4'
+          'border-cn-borders-2 text-sidebar-foreground-1 placeholder:text-sidebar-foreground-4 focus-within:border-sidebar-border-4 focus-visible:border-sidebar-border-4 bg-transparent'
       }
     },
     defaultVariants: {
@@ -152,7 +152,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
 
       return inputIconName ? (
         <span className="relative">
-          <Icon className="absolute left-3 top-1/2 -translate-y-1/2 text-icons-9" name={inputIconName} size={14} />
+          <Icon className="text-icons-9 absolute left-3 top-1/2 -translate-y-1/2" name={inputIconName} size={14} />
           {baseInputComp}
         </span>
       ) : (
@@ -163,7 +163,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
     return (
       <ControlGroup className={wrapperClassName}>
         {!!label && (
-          <Label className="mb-2.5" color={disabled ? 'disabled-dark' : 'secondary'} optional={optional} htmlFor={id}>
+          <Label className="mb-2" disabled={disabled} optional={optional} htmlFor={id}>
             {label}
           </Label>
         )}
diff --git a/packages/ui/src/components/multi-select.tsx b/packages/ui/src/components/multi-select.tsx
index 50fc59a91f..1d219f9245 100644
--- a/packages/ui/src/components/multi-select.tsx
+++ b/packages/ui/src/components/multi-select.tsx
@@ -55,12 +55,12 @@ export const MultiSelect = <T = unknown,>({
   return (
     <ControlGroup className={className}>
       {!!label && (
-        <Label className="mb-2.5" color="secondary" htmlFor={''}>
+        <Label className="mb-2" htmlFor={''}>
           {label}
         </Label>
       )}
       <DropdownMenu.Root>
-        <DropdownMenu.Trigger className="flex h-9 w-full items-center justify-between rounded border border-cn-borders-2 bg-cn-background-2 px-3 transition-colors data-[state=open]:border-cn-borders-8">
+        <DropdownMenu.Trigger className="border-cn-borders-2 bg-cn-background-2 data-[state=open]:border-cn-borders-8 flex h-9 w-full items-center justify-between rounded border px-3 transition-colors">
           {placeholder}
           <Icon name="chevron-down" className="chevron-down ml-auto" size={12} />
         </DropdownMenu.Trigger>
@@ -95,7 +95,7 @@ export const MultiSelect = <T = unknown,>({
                     }}
                   >
                     <div className="flex items-center gap-x-2">
-                      {isSelected && <Icon className="min-w-3 text-icons-2" name="tick" size={12} />}
+                      {isSelected && <Icon className="text-icons-2 min-w-3" name="tick" size={12} />}
                       {customOptionElem ? (
                         customOptionElem(option)
                       ) : (
@@ -108,7 +108,7 @@ export const MultiSelect = <T = unknown,>({
             </ScrollArea>
           ) : (
             <div className="px-5 py-4 text-center">
-              <span className="leading-tight text-cn-foreground-2">
+              <span className="text-cn-foreground-2 leading-tight">
                 {t('views:noData.noResults', 'No search results')}
               </span>
             </div>
diff --git a/packages/ui/src/components/option.tsx b/packages/ui/src/components/option.tsx
index d11fea49e2..dc4da72f51 100644
--- a/packages/ui/src/components/option.tsx
+++ b/packages/ui/src/components/option.tsx
@@ -32,14 +32,14 @@ export const Option: FC<OptionProps> = ({ control, id, label, description, ariaS
       aria-labelledby={`${id}-label`}
       aria-selected={ariaSelected}
     >
-      {control}
+      <div className="mt-0.5">{control}</div>
       <div className="flex flex-col gap-0">
-        <Label htmlFor={id} className="cursor-pointer pl-2.5 leading-tight">
+        <Label htmlFor={id} className="mb-1 cursor-pointer pl-2.5" variant="primary">
           {label}
         </Label>
         {description && (
           <Text
-            className="ml-2.5 mt-1.5 leading-snug tracking-tight"
+            className="ml-2.5 leading-snug tracking-tight"
             as="p"
             size={2}
             color="foreground-4"
diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx
index aa1b014204..86c8df8cb0 100644
--- a/packages/ui/src/components/select.tsx
+++ b/packages/ui/src/components/select.tsx
@@ -49,7 +49,7 @@ const SelectRoot: FC<SelectRootProps> = ({
 }) => (
   <SelectPrimitive.Root {...props}>
     {label && (
-      <Label className="mb-2.5" color={disabled ? 'disabled-dark' : 'secondary'} htmlFor={name}>
+      <Label className="mb-2" disabled={disabled} htmlFor={name}>
         {label}
       </Label>
     )}
@@ -154,7 +154,7 @@ const SelectContent = forwardRef<
           )}
         >
           {!!withSearch && (
-            <div className="sticky -top-1 z-[1] -mx-1 -mt-1 mb-1 border-b bg-cn-background-2 px-3 py-2.5">
+            <div className="bg-cn-background-2 sticky -top-1 z-[1] -mx-1 -mt-1 mb-1 border-b px-3 py-2.5">
               <SearchBox.Root
                 className="w-full"
                 placeholder={searchProps?.placeholder || ''}
@@ -168,7 +168,7 @@ const SelectContent = forwardRef<
             children
           ) : (
             <div className="px-5 py-4 text-center">
-              <span className="leading-tight text-cn-foreground-2">Nothing to select</span>
+              <span className="text-cn-foreground-2 leading-tight">Nothing to select</span>
             </div>
           )}
         </SelectPrimitive.Viewport>
diff --git a/packages/ui/src/components/textarea.tsx b/packages/ui/src/components/textarea.tsx
index 2a8acf7e47..0c60612b7b 100644
--- a/packages/ui/src/components/textarea.tsx
+++ b/packages/ui/src/components/textarea.tsx
@@ -21,7 +21,7 @@ const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(
     return (
       <ControlGroup>
         {label && (
-          <Label className="mb-2.5" color={disabled ? 'disabled-dark' : 'secondary'} optional={optional} htmlFor={id}>
+          <Label className="mb-2" disabled={disabled} optional={optional} htmlFor={id}>
             {label}
           </Label>
         )}
diff --git a/packages/ui/src/components/tooltip.tsx b/packages/ui/src/components/tooltip.tsx
index 00a0015520..f0e2fdb368 100644
--- a/packages/ui/src/components/tooltip.tsx
+++ b/packages/ui/src/components/tooltip.tsx
@@ -1,6 +1,6 @@
 import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
-import { Arrow, Content, Provider, Root, Trigger } from '@radix-ui/react-tooltip'
+import { Arrow, Content, Provider, Root, Trigger, type TooltipProps } from '@radix-ui/react-tooltip'
 import { cn } from '@utils/cn'
 
 const TooltipContent = forwardRef<ElementRef<typeof Content>, ComponentPropsWithoutRef<typeof Content>>(
@@ -33,4 +33,4 @@ const Tooltip = {
   Arrow: TooltipArrow
 }
 
-export { Tooltip }
+export { Tooltip, type TooltipProps }
diff --git a/packages/ui/src/types/index.ts b/packages/ui/src/types/index.ts
index cb5033fbd7..3ac7f4d832 100644
--- a/packages/ui/src/types/index.ts
+++ b/packages/ui/src/types/index.ts
@@ -1,3 +1,5 @@
+import { ReactNode } from 'react'
+
 import { z } from 'zod'
 
 export interface TypesUser {
@@ -52,3 +54,5 @@ export interface PrincipalType {
   // TODO: need to add avatar
   avatar_url?: string
 }
+
+export type NonEmptyReactNode = Exclude<ReactNode, boolean | null | undefined>
diff --git a/packages/ui/src/utils/utils.ts b/packages/ui/src/utils/utils.ts
index 6843908812..533938c90a 100644
--- a/packages/ui/src/utils/utils.ts
+++ b/packages/ui/src/utils/utils.ts
@@ -114,7 +114,7 @@ export interface Violation {
 /**
  * Helps to construct conditional objects like this: {a: b, ...(some ? c : {}), z: x}
  */
-export const wrapConditionalObjectElement = <T extends Record<string, unknown>>(element: T, isPassing: boolean) => {
+export const wrapConditionalObjectElement = <T>(element: T, isPassing: boolean) => {
   if (!element || !isPassing) {
     return {} as T
   }
diff --git a/packages/ui/src/views/labels/label-form-page.tsx b/packages/ui/src/views/labels/label-form-page.tsx
index 92a7af16b0..2fca029586 100644
--- a/packages/ui/src/views/labels/label-form-page.tsx
+++ b/packages/ui/src/views/labels/label-form-page.tsx
@@ -151,7 +151,7 @@ export const LabelFormPage: FC<LabelFormPageProps> = ({
 
   return (
     <SandboxLayout.Content className={cn('!flex-none w-[610px]', className)}>
-      <h1 className="mb-10 text-2xl font-medium text-cn-foreground-1">
+      <h1 className="text-cn-foreground-1 mb-10 text-2xl font-medium">
         {labelId
           ? t('views:labelData.form.editTitle', 'Label details')
           : t('views:labelData.form.createTitle', 'Create a label')}
@@ -163,7 +163,7 @@ export const LabelFormPage: FC<LabelFormPageProps> = ({
         <FormWrapper className="gap-y-10" onSubmit={handleSubmit(onSubmit)}>
           <Fieldset>
             <ControlGroup>
-              <Label className="mb-2.5" color="secondary" htmlFor="label-name">
+              <Label className="mb-2" htmlFor="label-name">
                 {t('views:labelData.form.labelName', 'Label name')}
               </Label>
 
@@ -196,16 +196,13 @@ export const LabelFormPage: FC<LabelFormPageProps> = ({
             />
 
             <ControlGroup>
-              <Label className="mb-2.5" color="secondary" optional>
+              <Label className="mb-2" optional>
                 {t('views:labelData.form.valueName', 'Label value')}
               </Label>
               {values.map((value, idx) => (
                 <LabelFormColorAndNameGroup
                   isValue
                   key={idx}
-                  /**
-                   * It is important to keep the margin-top 20px to allow room for error messages.
-                   */
                   className="mt-5 first-of-type:mt-0"
                   useTranslationStore={useTranslationStore}
                   handleDeleteValue={() => handleDeleteValue(idx)}
@@ -236,7 +233,7 @@ export const LabelFormPage: FC<LabelFormPageProps> = ({
           </Fieldset>
 
           <section className="mt-1 flex flex-col gap-y-5">
-            <h3 className="text-sm leading-none text-cn-foreground-2">
+            <h3 className="text-cn-foreground-2 text-sm leading-none">
               {t('views:labelData.form.previewLabel', 'Label preview')}
             </h3>
 
diff --git a/packages/ui/src/views/platform/input-reference-component.tsx b/packages/ui/src/views/platform/input-reference-component.tsx
index dfaa16150f..083d80f750 100644
--- a/packages/ui/src/views/platform/input-reference-component.tsx
+++ b/packages/ui/src/views/platform/input-reference-component.tsx
@@ -5,12 +5,12 @@ import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
 const inputReferenceVariants = cva(
-  'flex h-9 min-h-9 cursor-pointer items-center justify-between rounded bg-cn-background-2 px-3 py-2 text-cn-foreground-1 transition-colors',
+  'bg-cn-background-2 text-cn-foreground-1 flex h-9 min-h-9 cursor-pointer items-center justify-between rounded px-3 py-2 transition-colors',
   {
     variants: {
       state: {
-        default: 'border border-cn-borders-2',
-        disabled: 'cursor-not-allowed border border-cn-borders-1 bg-cn-background-3 text-cn-foreground-3'
+        default: 'border-cn-borders-2 border',
+        disabled: 'border-cn-borders-1 bg-cn-background-3 text-cn-foreground-3 cursor-not-allowed border'
       }
     },
     defaultVariants: {
@@ -124,7 +124,7 @@ export const InputReference = <T,>({
   return (
     <ControlGroup>
       {!!label && (
-        <Label className="mb-2.5" color={disabled ? 'disabled-dark' : 'secondary'} optional={optional}>
+        <Label className="mb-2" disabled={disabled} optional={optional}>
           {label}
         </Label>
       )}
diff --git a/packages/ui/src/views/project/project-general/project-general-page.tsx b/packages/ui/src/views/project/project-general/project-general-page.tsx
index 43173680e8..6e27b85907 100644
--- a/packages/ui/src/views/project/project-general/project-general-page.tsx
+++ b/packages/ui/src/views/project/project-general/project-general-page.tsx
@@ -107,7 +107,7 @@ export const ProjectSettingsGeneralPage = ({
   return (
     <SandboxLayout.Main>
       <SandboxLayout.Content className="mx-auto max-w-[38.125rem] pt-[3.25rem]">
-        <h2 className="mb-10 text-2xl font-medium text-cn-foreground-1">
+        <h2 className="text-cn-foreground-1 mb-10 text-2xl font-medium">
           {t('views:projectSettings.general.mainTitle', 'Project Settings')}
         </h2>
 
@@ -135,10 +135,8 @@ export const ProjectSettingsGeneralPage = ({
                   <Textarea
                     id="description"
                     {...register('description')}
-                    placeholder={t(
-                      'views:projectSettings.general.projectDescriptionPlaceholder',
-                      'Enter description (optional)'
-                    )}
+                    placeholder={t('views:projectSettings.general.projectDescriptionPlaceholder', 'Enter description')}
+                    optional
                     label={t('views:projectSettings.general.projectDescriptionLabel', 'Description')}
                     error={errors?.description?.message?.toString()}
                   />
diff --git a/packages/ui/src/views/repo/repo-branch-rules/components/repo-branch-rules-fields.tsx b/packages/ui/src/views/repo/repo-branch-rules/components/repo-branch-rules-fields.tsx
index 253a51186e..7b0654cc27 100644
--- a/packages/ui/src/views/repo/repo-branch-rules/components/repo-branch-rules-fields.tsx
+++ b/packages/ui/src/views/repo/repo-branch-rules/components/repo-branch-rules-fields.tsx
@@ -104,7 +104,7 @@ export const BranchSettingsRuleTargetPatternsField: FC<FieldProps> = ({ setValue
   return (
     <Fieldset className="gap-y-4">
       <ControlGroup>
-        <Label htmlFor="target-patterns" className="mb-2.5" color="secondary">
+        <Label htmlFor="target-patterns" className="mb-2">
           {t('views:repos.targetPatterns', 'Target patterns')}
         </Label>
         <div className="grid grid-cols-[1fr_112px] items-start gap-x-3.5">
@@ -247,7 +247,7 @@ export const BranchSettingsRuleBypassListField: FC<
   return (
     <Fieldset className="gap-y-4">
       <ControlGroup>
-        <Label className="mb-2.5" htmlFor="bypassValue" color="secondary">
+        <Label className="mb-2" htmlFor="bypassValue">
           {t('views:repos.bypassList', 'Bypass list')}
         </Label>
 
@@ -308,9 +308,7 @@ export const BranchSettingsRuleListField: FC<{
 
   return (
     <ControlGroup className="max-w-[476px]">
-      <Label className="mb-6" color="secondary">
-        {t('views:repos.rulesTitle', 'Rules: select all that apply')}
-      </Label>
+      <Label className="mb-6">{t('views:repos.rulesTitle', 'Rules: select all that apply')}</Label>
       <Fieldset className="gap-y-5">
         {branchRules.map((rule, index) => {
           const isChecked = rules[index]?.checked ?? false
diff --git a/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx b/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx
index ff5f50b327..495e016c2e 100644
--- a/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx
+++ b/packages/ui/src/views/repo/repo-branch/components/create-branch-dialog.tsx
@@ -101,7 +101,7 @@ export function CreateBranchDialog({
 
           <Fieldset>
             <ControlGroup>
-              <Label htmlFor="target" className="mb-2" color="secondary">
+              <Label htmlFor="target" className="mb-2">
                 {t('views:forms.basedOn', 'Based on')}
               </Label>
               {BranchSelectorContainer()}
diff --git a/packages/ui/src/views/repo/repo-settings/components/repo-settings-general-form.tsx b/packages/ui/src/views/repo/repo-settings/components/repo-settings-general-form.tsx
index ff450bb023..909b082abe 100644
--- a/packages/ui/src/views/repo/repo-settings/components/repo-settings-general-form.tsx
+++ b/packages/ui/src/views/repo/repo-settings/components/repo-settings-general-form.tsx
@@ -154,9 +154,7 @@ export const RepoSettingsGeneralForm: FC<{
           {/* BRANCH */}
           <Fieldset className="w-[298px]">
             <ControlGroup>
-              <Label className="mb-2.5" color="secondary">
-                {t('views:repos.defaultBranch', 'Default Branch')}
-              </Label>
+              <Label className="mb-2">{t('views:repos.defaultBranch', 'Default Branch')}</Label>
               <BranchSelector
                 useTranslationStore={useTranslationStore}
                 useRepoBranchesStore={useRepoBranchesStore}
@@ -173,9 +171,7 @@ export const RepoSettingsGeneralForm: FC<{
 
           <Fieldset className="mt-4">
             <ControlGroup>
-              <Label className="mb-6" color="secondary">
-                {t('views:repos.visibility', 'Visibility')}
-              </Label>
+              <Label className="mb-6">{t('views:repos.visibility', 'Visibility')}</Label>
               <RadioGroup value={accessValue} onValueChange={handleAccessChange} id="visibility">
                 <Option
                   control={<RadioButton value="1" id="access-public" />}
diff --git a/packages/ui/src/views/repo/repo-tags/components/create-tags-dialog.tsx b/packages/ui/src/views/repo/repo-tags/components/create-tags-dialog.tsx
index 4c599b2fe3..a0a8cfcbad 100644
--- a/packages/ui/src/views/repo/repo-tags/components/create-tags-dialog.tsx
+++ b/packages/ui/src/views/repo/repo-tags/components/create-tags-dialog.tsx
@@ -89,7 +89,7 @@ export function CreateTagDialog({
 
   return (
     <Dialog.Root open={open} onOpenChange={handleClose}>
-      <Dialog.Content className="max-w-[460px] border-cn-borders-2 bg-cn-background-1" aria-describedby={undefined}>
+      <Dialog.Content className="border-cn-borders-2 bg-cn-background-1 max-w-[460px]" aria-describedby={undefined}>
         <Dialog.Header>
           <Dialog.Title>{t('views:repos.createTagTitle', 'Create a tag')}</Dialog.Title>
         </Dialog.Header>
@@ -109,7 +109,7 @@ export function CreateTagDialog({
 
           <Fieldset>
             <ControlGroup>
-              <Label htmlFor="target" className="mb-2.5">
+              <Label htmlFor="target" className="mb-2">
                 Based on
               </Label>
               <BranchSelector
diff --git a/packages/ui/src/views/repo/webhooks/webhook-create/components/create-webhooks-form-fields.tsx b/packages/ui/src/views/repo/webhooks/webhook-create/components/create-webhooks-form-fields.tsx
index ac05fdc4a2..8e11021fa3 100644
--- a/packages/ui/src/views/repo/webhooks/webhook-create/components/create-webhooks-form-fields.tsx
+++ b/packages/ui/src/views/repo/webhooks/webhook-create/components/create-webhooks-form-fields.tsx
@@ -106,7 +106,7 @@ export const WebhookSSLVerificationField: FC<WebhookFormFieldProps> = ({ watch,
 
   return (
     <ControlGroup className="mt-4">
-      <Label htmlFor="insecure" className="mb-6" color="secondary">
+      <Label htmlFor="insecure" className="mb-6">
         {t('views:repos.sslVerification', 'SSL Verification')}
       </Label>
       <RadioGroup value={sslVerificationValue} onValueChange={handleAccessChange} id="insecure">
@@ -137,7 +137,7 @@ export const WebhookTriggerField: FC<WebhookFormFieldProps> = ({ watch, setValue
 
   return (
     <ControlGroup className="mt-4">
-      <Label htmlFor="trigger" className="mb-6" color="secondary">
+      <Label htmlFor="trigger" className="mb-6">
         {t('views:repos.evenTriggerLabel', 'Which events would you like to use to trigger this webhook?')}
       </Label>
       <RadioGroup value={sslVerificationValue} onValueChange={handleTriggerChange} id="trigger">
diff --git a/packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx b/packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx
index 7ec857aeb7..d7b3a0dec5 100644
--- a/packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx
+++ b/packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx
@@ -15,7 +15,7 @@ function InputLabel(props: InputLabelProps): JSX.Element | null {
 
   const labelText = required && label ? `${label} *` : label
 
-  return <Label className={cn('mb-2.5 block', className)}>{labelText}</Label>
+  return <Label className={cn('mb-2', className)}>{labelText}</Label>
 }
 
 export { InputLabel }
diff --git a/packages/ui/tailwind-design-system.ts b/packages/ui/tailwind-design-system.ts
index cf270dd8fd..405dc8c6ec 100644
--- a/packages/ui/tailwind-design-system.ts
+++ b/packages/ui/tailwind-design-system.ts
@@ -3,7 +3,7 @@ import tailwindcssAnimate from 'tailwindcss-animate'
 import plugin from 'tailwindcss/plugin'
 import type { PluginAPI, Config as TailwindConfig } from 'tailwindcss/types/config'
 
-import { badgeStyles, buttonStyles, dialogStyles, switchStyles } from './tailwind-utils-config/components'
+import { badgeStyles, buttonStyles, dialogStyles, labelStyles, switchStyles } from './tailwind-utils-config/components'
 import { typography as typographyStyles } from './tailwind-utils-config/utilities'
 
 export default {
@@ -406,6 +406,7 @@ export default {
       addComponents(buttonStyles)
       addComponents(dialogStyles)
       addComponents(switchStyles)
+      addComponents(labelStyles)
     }),
     tailwindcssAnimate,
     typography,
@@ -491,6 +492,7 @@ export default {
     { pattern: /^border-tag-border-/ },
     // label classes
     { pattern: /^bg-label-background-/ },
+    { pattern: /^bg-label-foreground-/ }, // this is essential for the color select in the LabelFormColorAndNameGroup component
     { pattern: /^text-label-foreground-/ },
     // sidebar classes
     { pattern: /^bg-sidebar-background-/ },
diff --git a/packages/ui/tailwind-utils-config/components/index.ts b/packages/ui/tailwind-utils-config/components/index.ts
index 3039a91719..04d3a4c5fc 100644
--- a/packages/ui/tailwind-utils-config/components/index.ts
+++ b/packages/ui/tailwind-utils-config/components/index.ts
@@ -2,3 +2,4 @@ export { default as badgeStyles } from './badge'
 export { default as buttonStyles } from './button'
 export { default as dialogStyles } from './dialog'
 export { default as switchStyles } from './switch'
+export { default as labelStyles } from './label'
diff --git a/packages/ui/tailwind-utils-config/components/label.ts b/packages/ui/tailwind-utils-config/components/label.ts
new file mode 100644
index 0000000000..b3b0023524
--- /dev/null
+++ b/packages/ui/tailwind-utils-config/components/label.ts
@@ -0,0 +1,26 @@
+export default {
+  '.label': {
+    '@apply font-body-tight-strong': '',
+
+    '&:where(.label-default)': {
+      color: 'var(--cn-text-2)',
+
+      '+ .label-informer': {
+        color: 'var(--cn-text-2)'
+      }
+    },
+
+    '&:where(.label-primary)': {
+      color: 'var(--cn-text-1)',
+
+      '+ .label-informer': {
+        color: 'var(--cn-text-1)'
+      }
+    },
+
+    '> .label-optional': {
+      '@apply font-body-normal': '',
+      color: 'var(--cn-text-3)'
+    }
+  }
+}


Reviews:
user: login: 3em
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T11:55:06Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T13:38:33Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:38:47Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:47:07Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:48:28Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:51:51Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:53:59Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T14:57:52Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T15:00:03Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T15:02:28Z
user: login: praneshg239
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T15:03:30Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T16:07:57Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-23T16:11:45Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-24T13:51:09Z
user: login: ankormoreankor
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-24T13:51:23Z
user: login: vardanbansal-harness
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-25T15:47:51Z

Review comments:
diff_hunk: @@ -1,60 +1,60 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef, ReactNode } from 'react'
 
+import { Informer, InformerProps } from '@/components'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+type NonEmptyReactNode = Exclude<ReactNode, boolean | null | undefined>
path: packages/ui/src/components/form-primitives/label.tsx
user: login: 3em
body: let's move this type to `canary/packages/ui/src/types/index.ts`
created_at: 2025-04-23T11:55:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,60 +1,60 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef, ReactNode } from 'react'
 
+import { Informer, InformerProps } from '@/components'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+type NonEmptyReactNode = Exclude<ReactNode, boolean | null | undefined>
path: packages/ui/src/components/form-primitives/label.tsx
user: login: ankormoreankor
body: Moved
created_at: 2025-04-23T13:38:33Z
author_association: COLLABORATOR
diff_hunk: @@ -1,60 +1,59 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
+import { Informer, InformerProps } from '@/components'
+import { NonEmptyReactNode } from '@/types'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+const labelVariants = cva('label', {
   variants: {
     variant: {
-      default: 'text-sm font-normal leading-none'
-    },
-    color: {
-      primary: 'text-cn-foreground-1',
-      secondary: 'text-cn-foreground-2',
-      disabled: 'text-cn-foreground-3',
-      'disabled-dark': 'text-cn-foreground-disabled'
+      default: 'label-default',
+      primary: 'label-primary'
     }
   },
   defaultVariants: {
-    variant: 'default',
-    color: 'primary'
+    variant: 'default'
   }
 })
 
-const LabelRoot = forwardRef<
-  ElementRef<typeof LabelPrimitive.Root>,
-  Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> & VariantProps<typeof labelVariants>
->(({ className, variant, color, ...props }, ref) => (
-  <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant, color }), className)} {...props} />
-))
-LabelRoot.displayName = LabelPrimitive.Root.displayName
-
-interface LabelProps
-  extends VariantProps<typeof labelVariants>,
-    PropsWithChildren<Omit<HTMLAttributes<HTMLLabelElement>, 'color'>> {
-  htmlFor?: string
-  optional?: boolean
-  className?: string
-}
-
-/**
- * A Label component that wraps the Radix UI LabelPrimitive.Root component.
- * It supports variant and color styling through class-variance-authority.
- * @example
- * <Label htmlFor="label" optional>Label</Label>
- */
+type BaseLabelProps = Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> &
+  VariantProps<typeof labelVariants> & {
+    disabled?: boolean
+    optional?: boolean
+    informerProps?: InformerProps
+  }
+
+export type LabelProps = BaseLabelProps &
+  (
+    | { withInformer: true; informerContent: NonEmptyReactNode }
+    | { withInformer?: false | undefined; informerContent?: never }
+  )
+
 const Label = forwardRef<ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
-  ({ htmlFor, optional, color, variant, children, className }: LabelProps, ref) => {
-    return (
-      <LabelRoot htmlFor={htmlFor} variant={variant} color={color} className={className} ref={ref}>
-        {children} {optional && <span className="align-top text-cn-foreground-3">(optional)</span>}
-      </LabelRoot>
+  ({ className, children, variant = 'default', optional, disabled, withInformer, informerContent, ...props }, ref) => {
+    const LabelComponent = ({ className }: { className?: string }) => (
+      <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant }), className)} {...props}>
+        {children} {optional && <span className="label-optional">(optional)</span>}
+      </LabelPrimitive.Root>
     )
+
+    if (withInformer) {
path: packages/ui/src/components/form-primitives/label.tsx
user: login: praneshg239
body: do we need this `withInformer` prop? Can we check if `informerContent` is present, we can show the informer UI?
created_at: 2025-04-23T14:38:47Z
author_association: COLLABORATOR
diff_hunk: @@ -1,60 +1,59 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
+import { Informer, InformerProps } from '@/components'
+import { NonEmptyReactNode } from '@/types'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+const labelVariants = cva('label', {
   variants: {
     variant: {
-      default: 'text-sm font-normal leading-none'
-    },
-    color: {
-      primary: 'text-cn-foreground-1',
-      secondary: 'text-cn-foreground-2',
-      disabled: 'text-cn-foreground-3',
-      'disabled-dark': 'text-cn-foreground-disabled'
+      default: 'label-default',
+      primary: 'label-primary'
     }
   },
   defaultVariants: {
-    variant: 'default',
-    color: 'primary'
+    variant: 'default'
   }
 })
 
-const LabelRoot = forwardRef<
-  ElementRef<typeof LabelPrimitive.Root>,
-  Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> & VariantProps<typeof labelVariants>
->(({ className, variant, color, ...props }, ref) => (
-  <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant, color }), className)} {...props} />
-))
-LabelRoot.displayName = LabelPrimitive.Root.displayName
-
-interface LabelProps
-  extends VariantProps<typeof labelVariants>,
-    PropsWithChildren<Omit<HTMLAttributes<HTMLLabelElement>, 'color'>> {
-  htmlFor?: string
-  optional?: boolean
-  className?: string
-}
-
-/**
- * A Label component that wraps the Radix UI LabelPrimitive.Root component.
- * It supports variant and color styling through class-variance-authority.
- * @example
- * <Label htmlFor="label" optional>Label</Label>
- */
+type BaseLabelProps = Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> &
+  VariantProps<typeof labelVariants> & {
+    disabled?: boolean
+    optional?: boolean
+    informerProps?: InformerProps
+  }
+
+export type LabelProps = BaseLabelProps &
+  (
+    | { withInformer: true; informerContent: NonEmptyReactNode }
+    | { withInformer?: false | undefined; informerContent?: never }
+  )
+
 const Label = forwardRef<ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
-  ({ htmlFor, optional, color, variant, children, className }: LabelProps, ref) => {
-    return (
-      <LabelRoot htmlFor={htmlFor} variant={variant} color={color} className={className} ref={ref}>
-        {children} {optional && <span className="align-top text-cn-foreground-3">(optional)</span>}
-      </LabelRoot>
+  ({ className, children, variant = 'default', optional, disabled, withInformer, informerContent, ...props }, ref) => {
+    const LabelComponent = ({ className }: { className?: string }) => (
+      <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant }), className)} {...props}>
+        {children} {optional && <span className="label-optional">(optional)</span>}
+      </LabelPrimitive.Root>
     )
+
+    if (withInformer) {
path: packages/ui/src/components/form-primitives/label.tsx
user: login: ankormoreankor
body: Definitely
The only problem with this approach is what I faced a few weeks ago during a different task. When you pass your content as an initialized component, which returns null, the check `!!informerContent` will give you true, and the emptiness will be rendered🫠

Here's an example:
```js
<Label informerContent={<ReusableInformerContentComponent />} />
```
If `ReusableInformerContentComponent` returns null (by some condition), the informer will show an empty tooltip.
created_at: 2025-04-23T14:47:07Z
author_association: COLLABORATOR
diff_hunk: @@ -1,60 +1,59 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
+import { Informer, InformerProps } from '@/components'
+import { NonEmptyReactNode } from '@/types'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+const labelVariants = cva('label', {
   variants: {
     variant: {
-      default: 'text-sm font-normal leading-none'
-    },
-    color: {
-      primary: 'text-cn-foreground-1',
-      secondary: 'text-cn-foreground-2',
-      disabled: 'text-cn-foreground-3',
-      'disabled-dark': 'text-cn-foreground-disabled'
+      default: 'label-default',
+      primary: 'label-primary'
     }
   },
   defaultVariants: {
-    variant: 'default',
-    color: 'primary'
+    variant: 'default'
   }
 })
 
-const LabelRoot = forwardRef<
-  ElementRef<typeof LabelPrimitive.Root>,
-  Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> & VariantProps<typeof labelVariants>
->(({ className, variant, color, ...props }, ref) => (
-  <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant, color }), className)} {...props} />
-))
-LabelRoot.displayName = LabelPrimitive.Root.displayName
-
-interface LabelProps
-  extends VariantProps<typeof labelVariants>,
-    PropsWithChildren<Omit<HTMLAttributes<HTMLLabelElement>, 'color'>> {
-  htmlFor?: string
-  optional?: boolean
-  className?: string
-}
-
-/**
- * A Label component that wraps the Radix UI LabelPrimitive.Root component.
- * It supports variant and color styling through class-variance-authority.
- * @example
- * <Label htmlFor="label" optional>Label</Label>
- */
+type BaseLabelProps = Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> &
+  VariantProps<typeof labelVariants> & {
+    disabled?: boolean
+    optional?: boolean
+    informerProps?: InformerProps
+  }
+
+export type LabelProps = BaseLabelProps &
+  (
+    | { withInformer: true; informerContent: NonEmptyReactNode }
+    | { withInformer?: false | undefined; informerContent?: never }
+  )
+
 const Label = forwardRef<ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
-  ({ htmlFor, optional, color, variant, children, className }: LabelProps, ref) => {
-    return (
-      <LabelRoot htmlFor={htmlFor} variant={variant} color={color} className={className} ref={ref}>
-        {children} {optional && <span className="align-top text-cn-foreground-3">(optional)</span>}
-      </LabelRoot>
+  ({ className, children, variant = 'default', optional, disabled, withInformer, informerContent, ...props }, ref) => {
+    const LabelComponent = ({ className }: { className?: string }) => (
+      <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant }), className)} {...props}>
+        {children} {optional && <span className="label-optional">(optional)</span>}
+      </LabelPrimitive.Root>
     )
+
+    if (withInformer) {
path: packages/ui/src/components/form-primitives/label.tsx
user: login: ankormoreankor
body: But `Informer` is a new component, and we don't know yet if there is any case like I mentioned. So, yes, it can make sense to get rid of `withInformer`
created_at: 2025-04-23T14:48:28Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,27 @@
+export default {
+  '.label': {
+    font: 'var(--cn-body-strong)',
path: packages/ui/tailwind-utils-config/components/label.ts
user: login: praneshg239
body: Please refer the font from `typography.ts`. You can check `badge.ts` for reference.
created_at: 2025-04-23T14:51:51Z
author_association: COLLABORATOR
diff_hunk: @@ -490,6 +491,7 @@ export default {
     { pattern: /^border-tag-border-/ },
     // label classes
     { pattern: /^bg-label-background-/ },
+    { pattern: /^bg-label-foreground-/ }, // this is essential for the color select in the LabelFormColorAndNameGroup component
path: packages/ui/tailwind-design-system.ts
user: login: praneshg239
body: 👍 
created_at: 2025-04-23T14:53:59Z
author_association: COLLABORATOR
diff_hunk: @@ -15,7 +15,7 @@ function InputLabel(props: InputLabelProps): JSX.Element | null {
 
   const labelText = required && label ? `${label} *` : label
 
-  return <Label className={cn('mb-2.5 block', className)}>{labelText}</Label>
+  return <Label className={cn('mb-2', className)}>{labelText}</Label>
path: packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx
user: login: praneshg239
body: Thinking out loud: Can we add `mb-2` as the default margin to the `Label` component? We're adding this in most places where the `Label` is used, and setting it by default could help reduce redundancy. 

cc: @abhinavrastogi-harness 
created_at: 2025-04-23T14:57:51Z
author_association: COLLABORATOR
diff_hunk: @@ -28,7 +28,7 @@ import { DocsPage } from "../../../components/docs-page";
 
     <div className="flex flex-col gap-4">
         <h5>With color</h5>
-        <Label htmlFor="password" color="disabled">Password</Label>
+        <Label htmlFor="password">Password</Label>
         <input id="password" type="password" />
     </div>
 
path: apps/portal/src/content/docs/components/label.mdx
user: login: praneshg239
body: Please add an example for `primary` variant of `Label`.
created_at: 2025-04-23T15:00:03Z
author_association: COLLABORATOR
diff_hunk: @@ -32,14 +32,14 @@ export const Option: FC<OptionProps> = ({ control, id, label, description, ariaS
       aria-labelledby={`${id}-label`}
       aria-selected={ariaSelected}
     >
-      {control}
+      <div className="mt-0.5">{control}</div>
       <div className="flex flex-col gap-0">
-        <Label htmlFor={id} className="cursor-pointer pl-2.5 leading-tight">
+        <Label htmlFor={id} className="mb-1 cursor-pointer pl-2.5" variant="primary">
path: packages/ui/src/components/option.tsx
user: login: praneshg239
body: If we are not adding default margin to `Label`, can we remove `mb-1` and add `gap-1` to its parent? Also can we add `pl-2.5` to its parent and remove it from here and `ml-2.5` from the `Text` below?
created_at: 2025-04-23T15:02:28Z
author_association: COLLABORATOR
diff_hunk: @@ -32,14 +32,14 @@ export const Option: FC<OptionProps> = ({ control, id, label, description, ariaS
       aria-labelledby={`${id}-label`}
       aria-selected={ariaSelected}
     >
-      {control}
+      <div className="mt-0.5">{control}</div>
       <div className="flex flex-col gap-0">
-        <Label htmlFor={id} className="cursor-pointer pl-2.5 leading-tight">
+        <Label htmlFor={id} className="mb-1 cursor-pointer pl-2.5" variant="primary">
path: packages/ui/src/components/option.tsx
user: login: praneshg239
body: Idea is to avoid adding `className` to design system component as much as possible. This will help is to maintain  and align to our design system. 
created_at: 2025-04-23T15:03:30Z
author_association: COLLABORATOR
diff_hunk: @@ -15,7 +15,7 @@ function InputLabel(props: InputLabelProps): JSX.Element | null {
 
   const labelText = required && label ? `${label} *` : label
 
-  return <Label className={cn('mb-2.5 block', className)}>{labelText}</Label>
+  return <Label className={cn('mb-2', className)}>{labelText}</Label>
path: packages/ui/src/views/unified-pipeline-studio/components/form-inputs/common/InputLabel.tsx
user: login: ankormoreankor
body: I think this should be solved in a different way. In [this discussion](https://pixelpointworkspace.slack.com/archives/C07QA52CWKH/p1745336557082299?thread_ts=1745335032.313199&cid=C07QA52CWKH) @bradrydzewski suggested having a wrapper component that will be responsible for the layout in fields.

Having environmental styles hardcoded in the component can lead to reusability issues.
created_at: 2025-04-23T16:07:57Z
author_association: COLLABORATOR
diff_hunk: @@ -32,14 +32,14 @@ export const Option: FC<OptionProps> = ({ control, id, label, description, ariaS
       aria-labelledby={`${id}-label`}
       aria-selected={ariaSelected}
     >
-      {control}
+      <div className="mt-0.5">{control}</div>
       <div className="flex flex-col gap-0">
-        <Label htmlFor={id} className="cursor-pointer pl-2.5 leading-tight">
+        <Label htmlFor={id} className="mb-1 cursor-pointer pl-2.5" variant="primary">
path: packages/ui/src/components/option.tsx
user: login: ankormoreankor
body: The `Option` component is kinda deprecated and seems not worth optimizing. It [will most likely be removed](https://pixelpointworkspace.slack.com/archives/C07QA52CWKH/p1745393422502649?thread_ts=1745335032.313199&cid=C07QA52CWKH) when we migrate and refactor `Checkbox` and `Radio` components
created_at: 2025-04-23T16:11:44Z
author_association: COLLABORATOR
diff_hunk: @@ -1,60 +1,59 @@
-// ToDo: Need to be reviewed by the XD team
-
-import { ComponentPropsWithoutRef, ElementRef, forwardRef, HTMLAttributes, PropsWithChildren } from 'react'
+import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react'
 
+import { Informer, InformerProps } from '@/components'
+import { NonEmptyReactNode } from '@/types'
 import * as LabelPrimitive from '@radix-ui/react-label'
 import { cn } from '@utils/cn'
 import { cva, type VariantProps } from 'class-variance-authority'
 
-const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', {
+const labelVariants = cva('label', {
   variants: {
     variant: {
-      default: 'text-sm font-normal leading-none'
-    },
-    color: {
-      primary: 'text-cn-foreground-1',
-      secondary: 'text-cn-foreground-2',
-      disabled: 'text-cn-foreground-3',
-      'disabled-dark': 'text-cn-foreground-disabled'
+      default: 'label-default',
+      primary: 'label-primary'
     }
   },
   defaultVariants: {
-    variant: 'default',
-    color: 'primary'
+    variant: 'default'
   }
 })
 
-const LabelRoot = forwardRef<
-  ElementRef<typeof LabelPrimitive.Root>,
-  Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> & VariantProps<typeof labelVariants>
->(({ className, variant, color, ...props }, ref) => (
-  <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant, color }), className)} {...props} />
-))
-LabelRoot.displayName = LabelPrimitive.Root.displayName
-
-interface LabelProps
-  extends VariantProps<typeof labelVariants>,
-    PropsWithChildren<Omit<HTMLAttributes<HTMLLabelElement>, 'color'>> {
-  htmlFor?: string
-  optional?: boolean
-  className?: string
-}
-
-/**
- * A Label component that wraps the Radix UI LabelPrimitive.Root component.
- * It supports variant and color styling through class-variance-authority.
- * @example
- * <Label htmlFor="label" optional>Label</Label>
- */
+type BaseLabelProps = Omit<ComponentPropsWithoutRef<typeof LabelPrimitive.Root>, 'color'> &
+  VariantProps<typeof labelVariants> & {
+    disabled?: boolean
+    optional?: boolean
+    informerProps?: InformerProps
+  }
+
+export type LabelProps = BaseLabelProps &
+  (
+    | { withInformer: true; informerContent: NonEmptyReactNode }
+    | { withInformer?: false | undefined; informerContent?: never }
+  )
+
 const Label = forwardRef<ElementRef<typeof LabelPrimitive.Root>, LabelProps>(
-  ({ htmlFor, optional, color, variant, children, className }: LabelProps, ref) => {
-    return (
-      <LabelRoot htmlFor={htmlFor} variant={variant} color={color} className={className} ref={ref}>
-        {children} {optional && <span className="align-top text-cn-foreground-3">(optional)</span>}
-      </LabelRoot>
+  ({ className, children, variant = 'default', optional, disabled, withInformer, informerContent, ...props }, ref) => {
+    const LabelComponent = ({ className }: { className?: string }) => (
+      <LabelPrimitive.Root ref={ref} className={cn(labelVariants({ variant }), className)} {...props}>
+        {children} {optional && <span className="label-optional">(optional)</span>}
+      </LabelPrimitive.Root>
     )
+
+    if (withInformer) {
path: packages/ui/src/components/form-primitives/label.tsx
user: login: ankormoreankor
body: Fixed
created_at: 2025-04-24T13:51:08Z
author_association: COLLABORATOR
diff_hunk: @@ -28,7 +28,7 @@ import { DocsPage } from "../../../components/docs-page";
 
     <div className="flex flex-col gap-4">
         <h5>With color</h5>
-        <Label htmlFor="password" color="disabled">Password</Label>
+        <Label htmlFor="password">Password</Label>
         <input id="password" type="password" />
     </div>
 
path: apps/portal/src/content/docs/components/label.mdx
user: login: ankormoreankor
body: Added
created_at: 2025-04-24T13:51:23Z
author_association: COLLABORATOR

PR comments:
user: login: CLAassistant
created_at: 2025-04-18T15:53:28Z
body: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/harness/canary?pullRequest=1499) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/harness/canary?pullRequest=1499) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/harness/canary?pullRequest=1499) it.</sub>
author_association: NONE
user: login: netlify[bot]
created_at: 2025-04-18T15:53:40Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *harness-design* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 844c42851f68018356f57e382b8580046b09dfcc |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/harness-design/deploys/680a4083684ce20008dda684 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-1499--harness-design.netlify.app](https://deploy-preview-1499--harness-design.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTE0OTktLWhhcm5lc3MtZGVzaWduLm5ldGxpZnkuYXBwIn0.pw1jN9SLhZxYBXNDTdqNVo-5Ey6VRLVJWiqWpRENrVc)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [harness-design Preview](https://deploy-preview-1499--harness-design.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/harness-design/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: netlify[bot]
created_at: 2025-04-18T15:53:45Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *harness-xd-review* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 844c42851f68018356f57e382b8580046b09dfcc |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/harness-xd-review/deploys/680a408336542e00085f1c2f |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-1499--harness-xd-review.netlify.app](https://deploy-preview-1499--harness-xd-review.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTE0OTktLWhhcm5lc3MteGQtcmV2aWV3Lm5ldGxpZnkuYXBwIn0._Z2XChacRP-FLgWAHLsNMUhBYHLn40a2JNzVZzDtsys)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [harness-xd-review Preview](https://deploy-preview-1499--harness-xd-review.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/harness-xd-review/configuration/notifications#deploy-webhooks)._
author_association: NONE