Update props in components

This commit is contained in:
adilallo
2026-02-06 17:36:12 -07:00
parent 85ff3b8f01
commit 1ca11a2229
11 changed files with 405 additions and 44 deletions
@@ -22,10 +22,18 @@ const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
(
{
id,
label,
label: labelProp,
labelText,
showLabel,
labelVariant: labelVariantProp,
size: sizeProp,
state: externalStateProp = "default",
asterisk = false,
iconHelp = true,
textOptional = false,
textData = true,
iconRight = true,
textHint = false,
disabled = false,
error = false,
placeholder = "Choose an option",
@@ -38,6 +46,17 @@ const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
},
ref,
) => {
// Handle backward compatibility: if label is string, use it as labelText
const actualLabelText = labelText || labelProp;
const shouldShowLabel = showLabel !== undefined ? showLabel : (actualLabelText !== undefined);
// Normalize state - handle "state5" as disabled
let normalizedState = externalStateProp;
if (normalizedState === "state5" || normalizedState === "State5") {
normalizedState = "default"; // Map to default, disabled prop handles the disabled state
}
const externalState = normalizeState(normalizedState);
// Normalize props to handle both PascalCase (Figma) and lowercase (codebase)
// Note: labelVariant and size are normalized for future use but not yet implemented in the view
const _labelVariant = labelVariantProp ? normalizeLabelVariant(labelVariantProp) : undefined;
@@ -45,7 +64,6 @@ const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
// Mark as intentionally unused for future implementation
void _labelVariant;
void _size;
const externalState = normalizeState(externalStateProp);
const generatedId = useId();
const selectId = id || `select-input-${generatedId}`;
@@ -193,7 +211,7 @@ const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
return (
<SelectInputView
label={label}
label={shouldShowLabel ? actualLabelText : undefined}
placeholder={placeholder}
state={actualState}
disabled={disabled}
@@ -214,8 +232,14 @@ const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
onOptionClick={handleOptionSelect}
selectRef={selectRef}
menuRef={menuRef}
ariaLabelledby={label ? labelId : undefined}
ariaLabelledby={shouldShowLabel ? labelId : undefined}
ariaInvalid={error}
asterisk={asterisk}
iconHelp={iconHelp}
textOptional={textOptional}
textData={textData}
iconRight={iconRight}
textHint={textHint}
{...props}
/>
);
@@ -12,7 +12,21 @@ export type SelectInputSizeValue = "small" | "medium" | "large" | "Small" | "Med
export interface SelectInputProps {
id?: string;
/**
* Label text (backward compatibility - if provided, label is shown).
* For Figma alignment, use `labelText` prop instead.
*/
label?: string;
/**
* Label text (Figma prop - use this for new code).
*/
labelText?: string;
/**
* Whether to show label above input (Figma prop).
* If `label` or `labelText` is provided, defaults to true.
* @default true
*/
showLabel?: boolean;
/**
* Label variant. Accepts both lowercase and PascalCase (case-insensitive).
* Figma uses PascalCase, codebase uses lowercase - both are supported.
@@ -24,10 +38,40 @@ export interface SelectInputProps {
*/
size?: SelectInputSizeValue;
/**
* Visual state. Accepts "default"/"Default", "hover"/"Hover", "focus"/"Focus" (case-insensitive).
* Visual state. Accepts "default"/"Default", "active"/"Active", "focus"/"Focus", "error"/"Error", "state5"/"State5" (State5 = Disabled).
* Figma uses PascalCase, codebase uses lowercase - both are supported.
*/
state?: StateValue;
state?: StateValue | "state5" | "State5";
/**
* Whether to show asterisk (*) in label (Figma prop).
* @default false
*/
asterisk?: boolean;
/**
* Whether to show help icon in label (Figma prop).
* @default true
*/
iconHelp?: boolean;
/**
* Whether to show "Optional" text in label (Figma prop).
* @default false
*/
textOptional?: boolean;
/**
* Whether to show data text (placeholder/entered text) - internal, always true (Figma prop).
* @default true
*/
textData?: boolean;
/**
* Whether to show dropdown icon on the right (Figma prop).
* @default true
*/
iconRight?: boolean;
/**
* Whether to show hint text below input (Figma prop).
* @default false
*/
textHint?: boolean;
disabled?: boolean;
error?: boolean;
placeholder?: string;
@@ -33,6 +33,13 @@ export interface SelectInputViewProps {
// Additional props
ariaLabelledby?: string;
ariaInvalid?: boolean;
// Figma props
asterisk?: boolean;
iconHelp?: boolean;
textOptional?: boolean;
textData?: boolean;
iconRight?: boolean;
textHint?: boolean;
}
export function SelectInputView({
@@ -59,6 +66,12 @@ export function SelectInputView({
menuRef,
ariaLabelledby,
ariaInvalid,
asterisk = false,
iconHelp = true,
textOptional = false,
textData = true,
iconRight = true,
textHint = false,
}: SelectInputViewProps) {
// Styles based on Figma design
const containerClasses = "flex flex-col gap-[8px]";
@@ -135,14 +148,26 @@ export function SelectInputView({
>
{label}
</label>
<div className="relative shrink-0 size-[12px]">
<img
src={getAssetPath(ASSETS.ICON_HELP)}
alt="Help"
className="block max-w-none size-full"
/>
</div>
{asterisk && (
<span className="text-[var(--color-content-default-negative-primary,#ea4845)] text-[10px] leading-[12px] font-medium">
*
</span>
)}
{iconHelp && (
<div className="relative shrink-0 size-[12px]">
<img
src={getAssetPath(ASSETS.ICON_HELP)}
alt="Help"
className="block max-w-none size-full"
/>
</div>
)}
</div>
{textOptional && (
<span className="text-[var(--color-content-default-tertiary,#b4b4b4)] text-[10px] leading-[14px] font-normal">
Optional text
</span>
)}
</div>
)}
<div className="relative">
@@ -161,24 +186,26 @@ export function SelectInputView({
onFocus={onButtonFocus}
onBlur={onButtonBlur}
>
<span className={`flex-1 text-left pr-[32px] ${textColorClass}`}>
{displayText}
<span className={`flex-1 text-left ${iconRight ? "pr-[32px]" : ""} ${textColorClass}`}>
{textData ? displayText : placeholder}
</span>
<div className="flex items-center justify-center shrink-0">
<svg
className={chevronClasses}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
{iconRight && (
<div className="flex items-center justify-center shrink-0">
<svg
className={chevronClasses}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</div>
)}
</button>
{state === "focus" && (
<div
@@ -235,6 +262,13 @@ export function SelectInputView({
</div>
)}
</div>
{textHint && (
<div className="flex items-start relative shrink-0 w-full">
<p className="flex-[1_0_0] font-inter font-normal leading-[16px] min-h-px min-w-px relative text-[color:var(--color-content-default-tertiary,#b4b4b4)] text-[length:var(--sizing-300,12px)]">
Hint text here
</p>
</div>
)}
</div>
);
}