Pagination

This commit is contained in:
2025-01-17 12:00:05 +05:30
parent 50a56cfe6b
commit b0fc202313
12 changed files with 831 additions and 394 deletions

View File

@@ -6,6 +6,7 @@ import Login from "./Pages/Login";
import { RouteLink } from "./Routes/Routes";
import LoginOtp from "./Pages/OnBoarding/LoginOtp";
import CreatePass from "./Pages/OnBoarding/CreatePass";
import LoginWithPass from "./Pages/OnBoarding/LoginWithPass";
function App() {
const context = useContext(GlobalStateContext);
@@ -16,9 +17,10 @@ function App() {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/login/login-otp" element={<LoginOtp />} />
<Route path="/login/create-password" element={<CreatePass/>}/>
<Route path="/login" element={<LoginWithPass/>} />
<Route path="/forgotPassword" element={<Login />} />
<Route path="/login-otp" element={<LoginOtp />} />
<Route path="/create-password" element={<CreatePass/>}/>
<Route
path="/*"
element={
@@ -31,11 +33,11 @@ function App() {
</Routes>
</DefaultLayout>
) : (
<Login />
<LoginWithPass />
)
}
/>
<Route path="*" element={<Login />} />
<Route path="*" element={<LoginWithPass />} />
</Routes>
</Router>
);

View File

@@ -5,7 +5,7 @@ import GlobalStateContext from './GlobalStateContext';
const GlobalStateProvider = ({ children }:{children:ReactNode}) => {
const [isAuthenticate, setIsAuthenticate] = useState<boolean>(false);
const [isAuthenticate, setIsAuthenticate] = useState<boolean>(true);
return (
<GlobalStateContext.Provider value={{ isAuthenticate, setIsAuthenticate }}>

View File

@@ -6,18 +6,21 @@ import logo from "../assets/logo.svg";
import { Button } from "../components/ui/button";
import { Field } from "../components/ui/field";
import { Toaster, toaster } from "../components/ui/toaster";
import { LuUser } from "react-icons/lu";
import { useNavigate } from "react-router-dom";
interface FormValues {
mobileNumber: number;
mobileNumber: string;
}
const Login = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const context = useContext(GlobalStateContext);
const navigate = useNavigate();
if (!context) {
throw new Error("App must be used within a GlobalStateProvider");
}
const { setIsAuthenticate } = context;
const {
register,
@@ -27,11 +30,13 @@ const Login = () => {
const onSubmit = handleSubmit((data) => {
setIsLoading(true);
if (data?.mobileNumber === 1234567890) {
if (data.mobileNumber === "1234567890") {
setTimeout(() => {
setIsAuthenticate(true);
setIsAuthenticate(true);
setIsLoading(false);
}, 3000); // 3-second delay
navigate("/login-otp");
}, 3000);
} else {
toaster.create({
title: `Invalid Credentials`,
@@ -93,14 +98,16 @@ const Login = () => {
<Input
ps={3}
{...register("mobileNumber", {
required: "Mobile Number address is required",
required: "Mobile Number is required",
pattern: {
value: /^[0-9]{10}$/,
message: "Invalid mobile number",
},
})}
placeholder="Mobile Number Address"
placeholder="Mobile Number"
/>
<Text cursor="pointer" as={'span'} w={'100%'} fontSize={'xs'} fontWeight={'normal'} color={'#686677'}>Forget password</Text>
</Field>
<Button
loading={isLoading}
mt={4}
@@ -114,7 +121,9 @@ const Login = () => {
Send OTP
</Button>
<Text>Forgot password</Text>
<Text cursor="pointer" color="#02A0A0" fontSize="sm">
Forgot password?
</Text>
</VStack>
</VStack>
</Center>

View File

@@ -1,8 +1,27 @@
import { Box, HStack, Input, Stack, Table, Text } from "@chakra-ui/react";
import {
Box,
HStack,
Input,
Stack,
Table,
Text,
VStack,
} from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame";
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import { Button } from "../../../components/ui/button";
import { FaRegEye } from "react-icons/fa";
import { CiEdit } from "react-icons/ci";
import { RiDeleteBin5Line } from "react-icons/ri";
import {
PaginationItems,
PaginationNextTrigger,
PaginationPrevTrigger,
PaginationRoot,
} from "../../../components/ui/pagination";
// Table setup
const tableHeadRow = [
@@ -13,7 +32,7 @@ const tableHeadRow = [
"DOB",
"Type of User",
"Language",
"Status",
"Activate/Deactivate",
"Action",
];
@@ -26,180 +45,119 @@ const usersData: any[] = [
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "English",
Status: "Active",
Action: "Edit/Delete",
"Activate/Deactivate": (
<HStack>
<Text>Yes</Text>
<Switch size="sm" colorPalette="teal" />
<Text>No</Text>
</HStack>
),
Action: (
<HStack gap={2}>
<FaRegEye cursor="pointer" size="18px" />
<CiEdit cursor="pointer" size="18px" />
<RiDeleteBin5Line cursor="pointer" size="18px" />
</HStack>
),
},
{
"Sr. No": 2,
"First Name": "Anjali",
"Mobile number": "9123456789",
Gender: "Female",
DOB: "21-06-1995",
"Type of User": "Customer",
Language: "Hindi",
Status: "Inactive",
Action: "Edit/Delete",
"First Name": "Ritesh",
"Mobile number": "9876543210",
Gender: "Male",
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "English",
"Activate/Deactivate": (
<HStack>
<Text>Yes</Text>
<Switch size="sm" colorPalette="teal" />
<Text>No</Text>
</HStack>
),
Action: (
<HStack gap={2}>
<FaRegEye cursor="pointer" size="18px" />
<CiEdit cursor="pointer" size="18px" />
<RiDeleteBin5Line cursor="pointer" size="18px" />
</HStack>
),
},
{
"Sr. No": 3,
"First Name": "Rajesh",
"Mobile number": "9871234560",
"First Name": "Ritesh",
"Mobile number": "9876543210",
Gender: "Male",
DOB: "12-12-1985",
"Type of User": "Vendor",
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "English",
Status: "Active",
Action: "Edit/Delete",
"Activate/Deactivate": (
<HStack>
<Text>Yes</Text>
<Switch size="sm" colorPalette="teal" />
<Text>No</Text>
</HStack>
),
Action: (
<HStack gap={2}>
<FaRegEye cursor="pointer" size="18px" />
<CiEdit cursor="pointer" size="18px" />
<RiDeleteBin5Line cursor="pointer" size="18px" />
</HStack>
),
},
{
"Sr. No": 4,
"First Name": "Priya",
"Mobile number": "9988776655",
Gender: "Female",
DOB: "05-05-1998",
"Type of User": "Customer",
Language: "Tamil",
Status: "Active",
Action: "Edit/Delete",
"First Name": "Ritesh",
"Mobile number": "9876543210",
Gender: "Male",
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "English",
"Activate/Deactivate": (
<HStack>
<Text>Yes</Text>
<Switch size="sm" colorPalette="teal" />
<Text>No</Text>
</HStack>
),
Action: (
<HStack gap={2}>
<FaRegEye cursor="pointer" size="18px" />
<CiEdit cursor="pointer" size="18px" />
<RiDeleteBin5Line cursor="pointer" size="18px" />
</HStack>
),
},
{
"Sr. No": 5,
"First Name": "Amit",
"Mobile number": "8899665544",
"First Name": "Ritesh",
"Mobile number": "9876543210",
Gender: "Male",
DOB: "03-03-1992",
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 6,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 7,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 5,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 6,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 7,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 8,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 9,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 10,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 11,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 12,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 13,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
Language: "English",
"Activate/Deactivate": (
<HStack>
<Text>Yes</Text>
<Switch size="sm" colorPalette="teal" />
<Text>No</Text>
</HStack>
),
Action: (
<HStack gap={2}>
<FaRegEye cursor="pointer" size="18px" />
<CiEdit cursor="pointer" size="18px" />
<RiDeleteBin5Line cursor="pointer" size="18px" />
</HStack>
),
},
];
const RegisterUsers = () => {
return (
<MainFrame>
<HStack w={"100%"} justifyContent={"space-between"} p={3}>
<HStack w={"100%"} justifyContent={"space-between"} p={3}>
<Text as={"span"} fontSize={"sm"} fontWeight={"bolder"} color={"#000"}>
Register User
</Text>
@@ -226,6 +184,20 @@ const RegisterUsers = () => {
</HStack>
<DataTable tableHeadRow={tableHeadRow} data={usersData} />
<PaginationRoot
p={4}
mt={8}
count={usersData.length}
pageSize={2}
defaultPage={1}
>
<HStack>
{/* <PaginationPrevTrigger /> */}
<PaginationItems />
<PaginationNextTrigger />
</HStack>
</PaginationRoot>
</MainFrame>
);
};

View File

@@ -8,6 +8,7 @@ import { Button } from "../../components/ui/button";
import { Field } from "../../components/ui/field";
import { Toaster, toaster } from "../../components/ui/toaster";
import { PinInput } from "../../components/ui/pin-input";
import { useNavigate } from "react-router-dom";
interface FormValues {
mobileNumber: number;
@@ -16,6 +17,7 @@ interface FormValues {
const LoginOtp = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const context = useContext(GlobalStateContext);
const navigate = useNavigate();
if (!context) {
throw new Error("App must be used within a GlobalStateProvider");
}
@@ -117,7 +119,7 @@ const LoginOtp = () => {
Resend OTP
</Text>
<Button
loading={isLoading}
// loading={isLoading}
mt={4}
size={"sm"}
bg={"#02A0A0"}
@@ -125,6 +127,7 @@ const LoginOtp = () => {
w={"100%"}
color={"#ffffff"}
type="submit"
onClick={navigate("/create-password")}
>
Send OTP
</Button>

View File

@@ -0,0 +1,170 @@
import { Center, HStack, Image, Input, Text, VStack } from "@chakra-ui/react";
import { useContext, useState } from "react";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import logo from "../../assets/logo.svg";
import { Button } from "../../components/ui/button";
import { Toaster, toaster } from "../../components/ui/toaster";
import { NavLink, useNavigate } from "react-router-dom";
import { Field } from "../../components/ui/field";
const LoginWithPass = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [mobileNumber, setMobileNumber] = useState("");
const [password, setPassword] = useState("");
const context = useContext(GlobalStateContext);
const navigate = useNavigate();
if (!context) {
throw new Error("App must be used within a GlobalStateProvider");
}
const { setIsAuthenticate } = context;
// Validation functions
const validateMobileNumber = (mobile: string) => {
if (!mobile) {
return "Mobile Number is required";
}
if (mobile.length !== 10) {
return "Mobile Number must be 10 digits long";
}
return "";
};
const validatePassword = (password: string) => {
if (!password) {
return "Password is required";
}
if (password.length < 6) {
return "Password must be at least 6 characters long";
}
return "";
};
const onHandleSubmit = () => {
const mobileError = validateMobileNumber(mobileNumber);
const passwordError = validatePassword(password);
if (mobileError || passwordError) {
toaster.create({
title: mobileError || passwordError,
type: "error",
});
return;
}
setIsLoading(true);
if (mobileNumber === "1231239870" && password === " ") {
navigate("/");
} else {
setIsLoading(false);
toaster.create({
title: "Invalid Credentials",
type: "error",
});
}
};
return (
<VStack w={"100%"} h={"100vh"} bg={"#ffffff"}>
<HStack
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
w={"100%"}
ps={8}
h={"7%"}
justifyContent={"flex-start"}
>
<Image w={50} src={logo} />
</HStack>
<HStack w={"100%"} h={"93%"} p={8} gap={8}>
<Center
display={{ base: "none", md: "flex" }}
bg={"#02A0A033"}
w={"50%"}
h={"100%"}
rounded={"3xl"}
>
<Image w={250} src={logo} />
</Center>
<Center
as={"form"}
p={{ base: 4, md: 16 }}
w={{ base: "100%", md: "50%" }}
h={"100%"}
onSubmit={(e) => {
e.preventDefault();
onHandleSubmit();
}}
>
<VStack gap={2} w={"100%"} alignItems={"flex-start"}>
<Text
w={"100%"}
textAlign={"center"}
fontSize={"24px"}
fontWeight={"normal"}
color={"#313039"}
textTransform={"uppercase"}
>
LogIn
</Text>
<VStack mt={6} gap={4} w={"full"}>
<Field color={"#313039"} label={"Enter Mobile Number"} w={"100%"}>
<Input
ps={3}
type="text"
value={mobileNumber}
onChange={(e) => setMobileNumber(e.target.value)}
placeholder="Enter your mobile number"
/>
</Field>
<Field color={"#313039"} label={"Enter Password"} w={"100%"}>
<Input
ps={3}
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Enter your password"
/>
<NavLink to="/forgotPassword" >
<Text
cursor="pointer"
as={"span"}
w={"100%"}
fontSize={"xs"}
fontWeight={"normal"}
color={"#686677"}
>
Forget password
</Text>
</NavLink>
</Field>
<Button
loading={isLoading}
mt={4}
size={"sm"}
bg={"#02A0A0"}
rounded={"md"}
w={"100%"}
color={"#ffffff"}
type="submit"
textTransform="capitalize"
>
Confirm Password
</Button>
<Text>Forgot password</Text>
</VStack>
</VStack>
</Center>
<Toaster />
</HStack>
</VStack>
);
};
export default LoginWithPass;

View File

@@ -14,7 +14,7 @@ const DataTable: React.FC<TableProps> = ({ tableHeadRow, data }) => {
<Table.Root key={'line'} size="sm" variant={'line'}>
<Table.Header >
<Table.Row bg={'#02A0A0'} >
{tableHeadRow.map((item, index)=><Table.ColumnHeader fontSize={'xs'} fontWeight={700} key={index} border={'none'}>{item}</Table.ColumnHeader>)}
{tableHeadRow.map((item, index)=><Table.ColumnHeader fontSize={'xs'} fontWeight={700} key={index} border={'none'}>{item}</Table.ColumnHeader>)}
</Table.Row>
</Table.Header>

View File

@@ -0,0 +1,12 @@
"use client"
import type { HTMLChakraProps, RecipeProps } from "@chakra-ui/react"
import { createRecipeContext } from "@chakra-ui/react"
export interface LinkButtonProps
extends HTMLChakraProps<"a", RecipeProps<"button">> {}
const { withContext } = createRecipeContext({ key: "button" })
// Replace "a" with your framework's link component
export const LinkButton = withContext<HTMLAnchorElement, LinkButtonProps>("a")

View File

@@ -0,0 +1,215 @@
"use client";
import type { ButtonProps, TextProps } from "@chakra-ui/react";
import {
Button,
Pagination as ChakraPagination,
IconButton,
Text,
createContext,
usePaginationContext,
} from "@chakra-ui/react";
import * as React from "react";
import {
HiChevronLeft,
HiChevronRight,
HiMiniEllipsisHorizontal,
} from "react-icons/hi2";
import { LinkButton } from "./link-button";
interface ButtonVariantMap {
current: ButtonProps["variant"];
default: ButtonProps["variant"];
ellipsis: ButtonProps["variant"];
}
type PaginationVariant = "outline" | "solid" | "subtle";
interface ButtonVariantContext {
size: ButtonProps["size"];
variantMap: ButtonVariantMap;
getHref?: (page: number) => string;
}
const [RootPropsProvider, useRootProps] = createContext<ButtonVariantContext>({
name: "RootPropsProvider",
});
export interface PaginationRootProps
extends Omit<ChakraPagination.RootProps, "type"> {
size?: ButtonProps["size"];
variant?: PaginationVariant;
getHref?: (page: number) => string;
}
const variantMap: Record<PaginationVariant, ButtonVariantMap> = {
outline: { default: "ghost", ellipsis: "plain", current: "outline" },
solid: { default: "outline", ellipsis: "outline", current: "solid" },
subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
};
export const PaginationRoot = React.forwardRef<
HTMLDivElement,
PaginationRootProps
>(function PaginationRoot(props, ref) {
const { size = "sm", variant = "outline", getHref, ...rest } = props;
return (
<RootPropsProvider
value={{ size, variantMap: variantMap[variant], getHref }}
>
<ChakraPagination.Root
ref={ref}
type={getHref ? "link" : "button"}
{...rest}
/>
</RootPropsProvider>
);
});
export const PaginationEllipsis = React.forwardRef<
HTMLDivElement,
ChakraPagination.EllipsisProps
>(function PaginationEllipsis(props, ref) {
const { size, variantMap } = useRootProps();
return (
<ChakraPagination.Ellipsis ref={ref} {...props} asChild>
<Button as="span" variant={variantMap.ellipsis} size={size}>
{/* <HiMiniEllipsisHorizontal /> */}
</Button>
</ChakraPagination.Ellipsis>
);
});
export const PaginationItem = React.forwardRef<
HTMLButtonElement,
ChakraPagination.ItemProps
>(function PaginationItem(props, ref) {
const { page } = usePaginationContext();
const { size, variantMap, getHref } = useRootProps();
const current = page === props.value;
const variant = current ? variantMap.current : variantMap.default;
if (getHref) {
return (
<LinkButton href={getHref(props.value)} variant={variant} size={size}>
{props.value}
</LinkButton>
);
}
return (
<ChakraPagination.Item ref={ref} {...props} asChild>
<Button variant={variant} size={size}>
{props.value}
</Button>
</ChakraPagination.Item>
);
});
export const PaginationPrevTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.PrevTriggerProps
>(function PaginationPrevTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { previousPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={previousPage != null ? getHref(previousPage) : undefined}
variant={variantMap.default}
size={size}
>
<HiChevronLeft />
</LinkButton>
);
}
return (
<ChakraPagination.PrevTrigger ref={ref} asChild {...props}>
<IconButton variant={variantMap.default} size={size}>
<HiChevronLeft />
</IconButton>
</ChakraPagination.PrevTrigger>
);
});
export const PaginationNextTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.NextTriggerProps
>(function PaginationNextTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { nextPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={nextPage != null ? getHref(nextPage) : undefined}
variant={variantMap.default}
size={size}
>
<HiChevronRight />
</LinkButton>
);
}
return (
<ChakraPagination.NextTrigger ref={ref} asChild {...props}>
<Button
w="136px"
borderRadius="94px"
bgColor="#02A0A0"
variant={variantMap.default}
size={size}
>
{/* <HiChevronRight /> */}
Next
</Button>
</ChakraPagination.NextTrigger>
);
});
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
return (
<ChakraPagination.Context>
{({ pages }) =>
pages.map((page, index) => {
return page.type === "ellipsis" ? (
<PaginationEllipsis key={index} index={index} {...props} />
) : (
<PaginationItem
key={index}
type="page"
value={page.value}
{...props}
/>
);
})
}
</ChakraPagination.Context>
);
};
interface PageTextProps extends TextProps {
format?: "short" | "compact" | "long";
}
export const PaginationPageText = React.forwardRef<
HTMLParagraphElement,
PageTextProps
>(function PaginationPageText(props, ref) {
const { format = "compact", ...rest } = props;
const { page, totalPages, pageRange, count } = usePaginationContext();
const content = React.useMemo(() => {
if (format === "short") return `${page} / ${totalPages}`;
if (format === "compact") return `${page} of ${totalPages}`;
return `${pageRange.start + 1} - ${Math.min(pageRange.end, count)} of ${count}`;
}, [format, page, totalPages, pageRange, count]);
return (
<Text fontWeight="medium" ref={ref} {...rest}>
{content}
</Text>
);
});

View File

@@ -0,0 +1,39 @@
import { Switch as ChakraSwitch } from "@chakra-ui/react"
import * as React from "react"
export interface SwitchProps extends ChakraSwitch.RootProps {
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
rootRef?: React.Ref<HTMLLabelElement>
trackLabel?: { on: React.ReactNode; off: React.ReactNode }
thumbLabel?: { on: React.ReactNode; off: React.ReactNode }
}
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
function Switch(props, ref) {
const { inputProps, children, rootRef, trackLabel, thumbLabel, ...rest } =
props
return (
<ChakraSwitch.Root ref={rootRef} {...rest}>
<ChakraSwitch.HiddenInput ref={ref} {...inputProps} />
<ChakraSwitch.Control>
<ChakraSwitch.Thumb>
{thumbLabel && (
<ChakraSwitch.ThumbIndicator fallback={thumbLabel?.off}>
{thumbLabel?.on}
</ChakraSwitch.ThumbIndicator>
)}
</ChakraSwitch.Thumb>
{trackLabel && (
<ChakraSwitch.Indicator fallback={trackLabel.off}>
{trackLabel.on}
</ChakraSwitch.Indicator>
)}
</ChakraSwitch.Control>
{children != null && (
<ChakraSwitch.Label>{children}</ChakraSwitch.Label>
)}
</ChakraSwitch.Root>
)
},
)