diff --git a/app/(site)/docs/components/tabs/page.tsx b/app/(site)/docs/components/tabs/page.tsx new file mode 100644 index 0000000..47674bb --- /dev/null +++ b/app/(site)/docs/components/tabs/page.tsx @@ -0,0 +1,169 @@ +import { ComponentPreview } from "@/components/docs/component-preview"; + +export default function TabsPage() { + return ( + \n Click me\n \n );\n}", + "language": "tsx" + } +]} + componentCode={`import * as React from "react"; +import { View, Text, Pressable, Platform } from "react-native"; +import { cn } from "@/lib/utils"; + +interface TabsProps { + defaultValue?: string; + value?: string; + onValueChange?: (value: string) => void; + children: React.ReactNode; + className?: string; +} + +interface TabsListProps { + children: React.ReactNode; + className?: string; +} + +interface TabsTriggerProps { + value: string; + children: React.ReactNode; + className?: string; +} + +interface TabsContentProps { + value: string; + children: React.ReactNode; + className?: string; +} + +const TabsContext = React.createContext<{ + value: string; + onValueChange: (value: string) => void; +}>({ + value: "", + onValueChange: () => {}, +}); + +const Tabs = React.forwardRef( + ({ defaultValue, value, onValueChange, children, className }, ref) => { + const [selectedValue, setSelectedValue] = React.useState( + value || defaultValue || "" + ); + + const handleValueChange = React.useCallback( + (newValue: string) => { + setSelectedValue(newValue); + onValueChange?.(newValue); + }, + [onValueChange] + ); + + return ( + + + {children} + + + ); + } +); + +const TabsList = React.forwardRef( + ({ children, className }, ref) => { + return ( + + {children} + + ); + } +); + +const TabsTrigger = React.forwardRef( + ({ value, children, className }, ref) => { + const { value: selectedValue, onValueChange } = + React.useContext(TabsContext); + const isSelected = selectedValue === value; + + return ( + onValueChange(value)} + className={cn( + "flex-1 items-center justify-center rounded-lg px-4 py-2", + Platform.OS === "ios" ? "h-10" : "h-12", + isSelected ? "bg-background" : "bg-transparent", + className + )} + > + + {children} + + + ); + } +); + +const TabsContent = React.forwardRef( + ({ value, children, className }, ref) => { + const { value: selectedValue } = React.useContext(TabsContext); + const isSelected = selectedValue === value; + + if (!isSelected) return null; + + return ( + + {children} + + ); + } +); + +Tabs.displayName = "Tabs"; +TabsList.displayName = "TabsList"; +TabsTrigger.displayName = "TabsTrigger"; +TabsContent.displayName = "TabsContent"; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; +`} + previewCode={`import { Tabs } from "@nativeui/ui"; + +export default function TabsDemo() { + return ( +
+ Default Tabs + Delete + Outline + Secondary + Ghost + Link +
+ ); +}`} + registryName="tabs" + packageName="@nativeui/ui" + /> + ); +} diff --git a/public/r/tabs.json b/public/r/tabs.json new file mode 100644 index 0000000..be940df --- /dev/null +++ b/public/r/tabs.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "tabs", + "type": "registry:component", + "title": "Tabs", + "description": "A tabs component for React Native applications.", + "dependencies": [ + "react-native" + ], + "registryDependencies": [], + "files": [ + { + "path": "registry/tabs/tabs.tsx", + "content": "import * as React from \"react\";\nimport { View, Text, Pressable, Platform } from \"react-native\";\nimport { cn } from \"@/lib/utils\";\n\ninterface TabsProps {\n defaultValue?: string;\n value?: string;\n onValueChange?: (value: string) => void;\n children: React.ReactNode;\n className?: string;\n}\n\ninterface TabsListProps {\n children: React.ReactNode;\n className?: string;\n}\n\ninterface TabsTriggerProps {\n value: string;\n children: React.ReactNode;\n className?: string;\n}\n\ninterface TabsContentProps {\n value: string;\n children: React.ReactNode;\n className?: string;\n}\n\nconst TabsContext = React.createContext<{\n value: string;\n onValueChange: (value: string) => void;\n}>({\n value: \"\",\n onValueChange: () => {},\n});\n\nconst Tabs = React.forwardRef(\n ({ defaultValue, value, onValueChange, children, className }, ref) => {\n const [selectedValue, setSelectedValue] = React.useState(\n value || defaultValue || \"\"\n );\n\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n setSelectedValue(newValue);\n onValueChange?.(newValue);\n },\n [onValueChange]\n );\n\n return (\n \n \n {children}\n \n \n );\n }\n);\n\nconst TabsList = React.forwardRef(\n ({ children, className }, ref) => {\n return (\n \n {children}\n \n );\n }\n);\n\nconst TabsTrigger = React.forwardRef(\n ({ value, children, className }, ref) => {\n const { value: selectedValue, onValueChange } =\n React.useContext(TabsContext);\n const isSelected = selectedValue === value;\n\n return (\n onValueChange(value)}\n className={cn(\n \"flex-1 items-center justify-center rounded-lg px-4 py-2\",\n Platform.OS === \"ios\" ? \"h-10\" : \"h-12\",\n isSelected ? \"bg-background\" : \"bg-transparent\",\n className\n )}\n >\n \n {children}\n \n \n );\n }\n);\n\nconst TabsContent = React.forwardRef(\n ({ value, children, className }, ref) => {\n const { value: selectedValue } = React.useContext(TabsContext);\n const isSelected = selectedValue === value;\n\n if (!isSelected) return null;\n\n return (\n \n {children}\n \n );\n }\n);\n\nTabs.displayName = \"Tabs\";\nTabsList.displayName = \"TabsList\";\nTabsTrigger.displayName = \"TabsTrigger\";\nTabsContent.displayName = \"TabsContent\";\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent };\n", + "type": "registry:component" + } + ] +} \ No newline at end of file diff --git a/registry.json b/registry.json index f97cfb7..f4b42b0 100644 --- a/registry.json +++ b/registry.json @@ -253,7 +253,25 @@ "type": "registry:component" } ], - "dependencies": ["react-native", "react-native-safe-area-context", "@expo/vector-icons"], + "dependencies": [ + "react-native", + "react-native-safe-area-context", + "@expo/vector-icons" + ], + "registryDependencies": [] + }, + { + "name": "tabs", + "type": "registry:component", + "title": "Tabs", + "description": "A tabs component for React Native applications.", + "files": [ + { + "path": "registry/tabs/tabs.tsx", + "type": "registry:component" + } + ], + "dependencies": ["react-native"], "registryDependencies": [] } ] diff --git a/registry/tabs/tabs.tsx b/registry/tabs/tabs.tsx new file mode 100644 index 0000000..9760456 --- /dev/null +++ b/registry/tabs/tabs.tsx @@ -0,0 +1,134 @@ +import * as React from "react"; +import { View, Text, Pressable, Platform } from "react-native"; +import { cn } from "@/lib/utils"; + +interface TabsProps { + defaultValue?: string; + value?: string; + onValueChange?: (value: string) => void; + children: React.ReactNode; + className?: string; +} + +interface TabsListProps { + children: React.ReactNode; + className?: string; +} + +interface TabsTriggerProps { + value: string; + children: React.ReactNode; + className?: string; +} + +interface TabsContentProps { + value: string; + children: React.ReactNode; + className?: string; +} + +const TabsContext = React.createContext<{ + value: string; + onValueChange: (value: string) => void; +}>({ + value: "", + onValueChange: () => {}, +}); + +const Tabs = React.forwardRef( + ({ defaultValue, value, onValueChange, children, className }, ref) => { + const [selectedValue, setSelectedValue] = React.useState( + value || defaultValue || "" + ); + + const handleValueChange = React.useCallback( + (newValue: string) => { + setSelectedValue(newValue); + onValueChange?.(newValue); + }, + [onValueChange] + ); + + return ( + + + {children} + + + ); + } +); + +const TabsList = React.forwardRef( + ({ children, className }, ref) => { + return ( + + {children} + + ); + } +); + +const TabsTrigger = React.forwardRef( + ({ value, children, className }, ref) => { + const { value: selectedValue, onValueChange } = + React.useContext(TabsContext); + const isSelected = selectedValue === value; + + return ( + onValueChange(value)} + className={cn( + "flex-1 items-center justify-center rounded-lg px-4 py-2", + Platform.OS === "ios" ? "h-10" : "h-12", + isSelected ? "bg-background" : "bg-transparent", + className + )} + > + + {children} + + + ); + } +); + +const TabsContent = React.forwardRef( + ({ value, children, className }, ref) => { + const { value: selectedValue } = React.useContext(TabsContext); + const isSelected = selectedValue === value; + + if (!isSelected) return null; + + return ( + + {children} + + ); + } +); + +Tabs.displayName = "Tabs"; +TabsList.displayName = "TabsList"; +TabsTrigger.displayName = "TabsTrigger"; +TabsContent.displayName = "TabsContent"; + +export { Tabs, TabsList, TabsTrigger, TabsContent };