system-select-input

add system variant
This commit is contained in:
gofnnp 2025-10-07 22:45:48 +04:00
parent 63fe674d83
commit 8ccd559e7c
4 changed files with 110 additions and 13 deletions

View File

@ -10,6 +10,7 @@ import {
buildTemplateBottomActionButtonProps, buildTemplateBottomActionButtonProps,
} from "@/lib/funnel/mappers"; } from "@/lib/funnel/mappers";
import type { ScreenDefinition } from "@/lib/funnel/types"; import type { ScreenDefinition } from "@/lib/funnel/types";
import { cn } from "@/lib/utils";
interface TemplateLayoutProps { interface TemplateLayoutProps {
screen: ScreenDefinition; screen: ScreenDefinition;
@ -132,7 +133,7 @@ export function TemplateLayout({
const autoPrivacyTermsConsent = shouldShowPrivacyTermsConsent ? ( const autoPrivacyTermsConsent = shouldShowPrivacyTermsConsent ? (
<PrivacyTermsConsent <PrivacyTermsConsent
className="mt-5" className="mt-2"
privacyPolicy={{ privacyPolicy={{
href: "/privacy", href: "/privacy",
children: "Privacy Policy", children: "Privacy Policy",
@ -170,6 +171,13 @@ export function TemplateLayout({
ref={bottomActionButtonRef} ref={bottomActionButtonRef}
childrenAboveButton={childrenAboveButton} childrenAboveButton={childrenAboveButton}
childrenUnderButton={finalChildrenUnderButton} childrenUnderButton={finalChildrenUnderButton}
gradientBlurProps={
shouldShowPrivacyTermsConsent
? {
className: cn(shouldShowPrivacyTermsConsent && "pb-1"),
}
: undefined
}
/> />
)} )}
</div> </div>

View File

@ -0,0 +1,84 @@
"use client";
import { cn } from "@/lib/utils";
import { useId } from "react";
import Typography from "../Typography/Typography";
type Option = {
value: string | number;
label: string;
};
export interface SelectInputProps extends React.ComponentProps<"select"> {
error?: boolean;
options: Option[];
placeholder?: string;
label?: string;
labelProps?: React.ComponentProps<"label">;
errorProps?: React.ComponentProps<typeof Typography>;
}
export default function SelectInput({
error,
options,
placeholder,
label,
labelProps,
errorProps,
...props
}: SelectInputProps) {
const id = useId();
return (
<div className={cn("w-full flex flex-col gap-2")}>
{label && (
<label
htmlFor={id}
className={cn(
"text-muted-foreground font-inter font-medium text-base",
labelProps?.className
)}
{...labelProps}
>
{label}
</label>
)}
<select
id={id}
className={cn(
"cursor-pointer",
"appearance-none",
"w-full min-w-[106px] h-fit! min-h-14",
"px-4 py-3.5",
"font-inter text-[18px]/[28px] font-medium text-placeholder-foreground",
"rounded-2xl outline-2 outline-primary/30",
"duration-200",
"disabled:opacity-50 disabled:cursor-not-allowed",
error &&
"outline-destructive focus-visible:shadow-destructive focus-visible:ring-destructive/30"
)}
{...props}
>
{placeholder && (
<option value="" hidden>
{placeholder}
</option>
)}
{options.map((option) => (
<option
key={option.value}
value={option.value}
className="text-foreground"
>
{option.label}
</option>
))}
</select>
{error && (
<Typography size="xs" color="destructive" {...errorProps}>
{errorProps?.children}
</Typography>
)}
</div>
);
}

View File

@ -21,6 +21,8 @@ export interface BottomActionButtonProps extends React.ComponentProps<"div"> {
showGradientBlur?: boolean; showGradientBlur?: boolean;
/** Синхронизировать CSS-переменную --bottom-action-button-height на <html> */ /** Синхронизировать CSS-переменную --bottom-action-button-height на <html> */
syncCssVar?: boolean; syncCssVar?: boolean;
gradientBlurProps?: React.ComponentProps<typeof GradientBlur>;
} }
const BottomActionButton = forwardRef<HTMLDivElement, BottomActionButtonProps>( const BottomActionButton = forwardRef<HTMLDivElement, BottomActionButtonProps>(
@ -32,6 +34,7 @@ const BottomActionButton = forwardRef<HTMLDivElement, BottomActionButtonProps>(
showGradientBlur = true, showGradientBlur = true,
className, className,
syncCssVar = true, syncCssVar = true,
gradientBlurProps,
...props ...props
}, },
ref ref
@ -81,7 +84,11 @@ const BottomActionButton = forwardRef<HTMLDivElement, BottomActionButtonProps>(
)} )}
{...props} {...props}
> >
<GradientBlur className="p-6 pt-11" isActiveBlur={showGradientBlur}> <GradientBlur
isActiveBlur={showGradientBlur}
{...gradientBlurProps}
className={cn("p-6 pt-11", gradientBlurProps?.className)}
>
{childrenAboveButton && ( {childrenAboveButton && (
<div className="w-full flex justify-center"> <div className="w-full flex justify-center">
{childrenAboveButton} {childrenAboveButton}

View File

@ -1,15 +1,13 @@
"use client"; "use client";
import SelectInput, { import SystemSelectInput from "@/components/ui/SystemSelectInput/SystemSelectInput";
SelectInputProps,
} from "@/components/ui/SelectInput/SelectInput";
import Typography from "@/components/ui/Typography/Typography"; import Typography from "@/components/ui/Typography/Typography";
import { useDateInput } from "@/hooks/useDateInput"; import { useDateInput } from "@/hooks/useDateInput";
type LocalSelectInputProps = Omit< type LocalSelectInputProps = Omit<
SelectInputProps, React.ComponentProps<typeof SystemSelectInput>,
"value" | "onValueChange" | "options" "value" | "onChange" | "options"
>; >;
export interface DateInputProps { export interface DateInputProps {
@ -58,30 +56,30 @@ export default function DateInput({
const inputs = { const inputs = {
d: ( d: (
<SelectInput <SystemSelectInput
key="d" key="d"
value={day} value={day}
onValueChange={handleDayChange} onChange={(e) => handleDayChange(e.target.value)}
options={dayOptions} options={dayOptions}
placeholder="DD" placeholder="DD"
{...daySelectProps} {...daySelectProps}
/> />
), ),
m: ( m: (
<SelectInput <SystemSelectInput
key="m" key="m"
value={month} value={month}
onValueChange={handleMonthChange} onChange={(e) => handleMonthChange(e.target.value)}
options={monthOptions} options={monthOptions}
placeholder="MM" placeholder="MM"
{...monthSelectProps} {...monthSelectProps}
/> />
), ),
y: ( y: (
<SelectInput <SystemSelectInput
key="y" key="y"
value={year} value={year}
onValueChange={handleYearChange} onChange={(e) => handleYearChange(e.target.value)}
options={yearOptions} options={yearOptions}
placeholder="YYYY" placeholder="YYYY"
{...yearSelectProps} {...yearSelectProps}